plan: !task type at genesis + haustoria-side VTODO field mapping#100
plan: !task type at genesis + haustoria-side VTODO field mapping#100friedenberg wants to merge 12 commits intomasterfrom
Conversation
Drops the !vtodo persisted-type plan in favor of haustoria-side hardcoded VTODO ↔ !task field mapping. Formally commits !task into the bigbang/genesis process so every fresh repo has it as a built-in with status/priority/due fields. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
||
| ``` toml | ||
| file-extension = "task" | ||
| vim-syntax-type = "taskpaper" |
|
|
||
| [[fields]] | ||
| name = "priority" | ||
| kind = "u32" |
There was a problem hiding this comment.
should be an enum that maps to the vtodo default priorities from tasks.org (!, !!, !!!, none -- but as text, not exclamation points)
There was a problem hiding this comment.
actually enum values of p0, p1, p2, p3
|
|
||
| The new step is gated on the existing `BigBang.ExcludeDefaultType` flag --- same | ||
| flag that already gates `!md`. This means `init-workspace` and `clone` both skip | ||
| it, which matches existing behavior for default types. |
There was a problem hiding this comment.
default should be don't include it -- opt-in for now, and once it matures can become opt-out.
| (matches the field-mutation work in `19c6f63`). Alternative: keep VTODO | ||
| casing (`needs-action` / `in-process` / `completed` / `cancelled`). | ||
|
|
||
| 2. **`!chore` handling**: drop `!chore` entirely and have both `tasks` and |
There was a problem hiding this comment.
ship both for now, but eventually would like to explore an !actionable abstract type that !task and !chore can be built on top of (less extension and more composition)
| indexFields.Add(fields.Field{ | ||
| Key: "status", | ||
| Value: statusValue, | ||
| TypeBlobDigest: s.taskTypeBlobDigest, |
There was a problem hiding this comment.
the task type blob digest should always be looked-up-fresh for each commit cycle.
also, let's confirm that this approach (setting the field on the object struct) will cause the commit cycle to update the blob as part of the field-reading/writing process
- Status enum stays as todo/in-process/done/cancelled - Priority becomes p0/p1/p2/p3 enum (tasks.org convention) - Ship !chore as separate built-in alongside !task; future !actionable - New opt-in BigBang.IncludeBuiltinActionableTypes flag (default false) - File extension toml; instances are TOML-mirrored field blobs - Fresh type-blob-digest lookup per compile/decompile cycle - Add field-codec-without-scripts verification test as gating step Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Pushed
Updated plan also tightens implementation order, drops the now-stale fixture-regeneration step (opt-in means the existing fresh-store fixtures don't change), and updates the live workspace migration to a clean re-init flow with the new flag. 🤖 Generated with Claude Code |
Two BATS probes added to fields.bats to answer the open verification question on PR #100: does the binary stream-index codec persist Metadata.Index.Fields when no fields-reader/fields-writer scripts are configured on the type? field_persists_without_any_scripts: type with [[fields]] only, no scripts. Organize-set status field is DROPPED entirely on commit. Blob digest also disappears. Locked assertion: [one/uno !task "my task"]. field_persists_with_reader_only_no_writer: type with reader, no writer. Organize-set status=done is silently overwritten by the reader re-projecting status=todo from the unchanged blob, AND the field appears TWICE in show output (status=todo status=todo). Both findings invalidate the original plan's assumption that the haustoria can set fields directly on metadata without a fields-writer script. The plan needs revision: either ship a TOML field-projector script with !task, or add a code path that bypasses the script gate. The duplicated-field result in probe 2 looks like a separate bug to file independently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Probe results: the original plan's core assumption is wrong. Pushed Probe 1:
|
Three additional BATS probes verify the "ship !task with reader+writer scripts" path: field_full_task_three_fields_from_blob: blob with 3 fields baked in → reader projects all 3 → all display in show. WORKS. field_full_task_organize_mutate_one_of_three: start with 3 fields in blob, organize-set status=done, all 3 persist with writer rewriting the TOML. WORKS. field_full_task_organize_from_empty_blob: empty starting blob → organize-set 3 fields → fields and blob digest both dropped. FAILS the same way as field_persists_without_any_scripts. Conclusion: option 1 + option 2 combined works. !task ships with [[fields]] + [fields-reader] + [fields-writer]. The haustoria writes a complete TOML blob with field values baked in (compile path). The reader projects fields on commit; the writer projects edits back into the blob on subsequent organize mutations. The decompile path reads fields from metadata.Index. The empty-blob case (probe 13) is a non-issue because the haustoria always writes a full blob, never an empty one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Adding Probe 11: blob with all three fields baked in → reader projects them✅ Reader script with Probe 12: organize-mutate one of three fields, others preserved✅ Status changes from Probe 13: organize-set fields starting from EMPTY blob❌ Same failure as probe 1. With an empty starting blob, This is a non-issue for the haustoria because the haustoria always writes a complete TOML blob with field values baked in (the compile path). It never tries to commit a fields-only object with an empty blob. Revised plan: option 1 + option 2 combinedThe plan now becomes:
Bonus benefits over the original plan
Drawbacks
Will update the plan markdown next. WDYT? 🤖 Generated with Claude Code |
PR #100 probes proved the original "set fields directly on metadata" assumption wrong. Both tryWriteFields and tryReadFields early-return on missing scripts AND drop the daughter fields before they reach the binary codec. The plan now uses [fields-reader] + [fields-writer] scripts on !task instead. - §1: !task type blob now declares both reader and writer scripts. - §1a: !chore documented as separate built-in with same field set. Future !actionable abstract type captured as out-of-scope. - §3: rewritten as blob-canonical haustoria flow. Compile path writes a TOML blob; reader script projects fields on commit. Decompile reads fields from Metadata.Index.Fields. No fresh type-blob-digest lookup needed; no new code paths in papa/store. - §4: tests updated to reference the already-landed fields.bats probes (cfdb846, c5ebd34) instead of the dropped TestFieldsPersistThroughCommitWithoutScripts. - Open verification → Resolved verification, citing issues #101 and #102 filed against the fields infrastructure. - Implementation order updated to drop the gating test and add the buildTaskTomlBlob compile-path step. - Out of Scope: !chore separate-type bullet replaced with !actionable future-work note; conflict resolution explicitly out of scope. Also annotates docs/plans/2026-04-05-fields-doddish-organize-design.md with #101 and #102 in the Open issues list. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| [[fields]] | ||
| name = "status" | ||
| kind = "enum" | ||
| values = ["todo", "in-process", "done", "cancelled"] |
There was a problem hiding this comment.
should be "in_progress"
| 5 `p2` `!!` | ||
| 1 `p3` `!!!` | ||
|
|
||
| Other PRIORITY values fall back to the closest bucket on read; on write the |
There was a problem hiding this comment.
the mapping is wrong, it's reversed. !!! should be p0, and none should be P3
- Status enum: in-process -> in_progress (snake_case underscore)
- Priority mapping reversed: p0 is now HIGHEST (matches sev-0 ticket
convention), p3 is lowest. New table:
p0 = !!! = VTODO PRIORITY 1
p1 = !! = VTODO PRIORITY 5
p2 = ! = VTODO PRIORITY 9
p3 = (none) = VTODO PRIORITY 0/absent
- Default priority: p3 (most tasks have no priority assigned)
- Decompile inverse mapping updated accordingly
- Three BATS probes updated with new enum values + recaptured digests
- TestPriorityValueRoundTrip integers swapped to match new mapping
- caldav_round_trip_priority_field example values updated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Pushed
All 13 probes pass with locked-in assertions. 🤖 Generated with Claude Code |
Add built-in TomlV2 constructors for !task and !chore types per the plan in docs/plans/2026-04-06-task-type-genesis-and-haustoria-fields.md. Both types share the actionable field set (status enum todo/in_progress/ done/cancelled, priority enum p0/p1/p2/p3 with p0 highest, due string) plus reader and writer scripts using yq for TOML projection. The shared constructors actionableFields/Reader/Writer are private helpers in the golf/type_blobs package. Re-exported from hotel/type_blobs for downstream consumers. Unit tests verify field definitions, default values, and that the reader/writer scripts contain the expected DODDER_FIELD_* and DODDER_BLOB_PATH variables. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| // DODDER_FIELD_priority, DODDER_FIELD_due env vars and writes them into the | ||
| // blob at DODDER_BLOB_PATH. | ||
| func actionableFieldsWriter() *script_config.ScriptConfig { | ||
| return &script_config.ScriptConfig{ |
There was a problem hiding this comment.
should turn this into a go:embed. same for the reader script
…steps 2-3)
- Add BigBang.IncludeBuiltinActionableTypes (default false).
- prepareBuiltinActionableTypes commits both built-in types via the
typed blob store and adds them to the genesis import plan, gated on
the new flag.
- Expose -include-builtin-actionable-types on the dodder genesis CLI.
- Add genesis_actionable_types.bats with four probe tests:
- default init omits !task and !chore (existing behavior preserved)
- opt-in init commits both alongside !md
- !task type blob round-trips through TOML with the actionable field
set and yq reader/writer scripts (note: tommy serializes script as
triple-quoted multiline)
- !chore and !task have byte-identical blob digests since they share
the same field set + scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ep 4)
Replace the lossy status-tags config + raw-DESCRIPTION blob model with
a TOML blob format that mirrors the !task field set.
mike/haustoria_caldav:
- Drop CalendarMapping.StatusTags. The status-tag tag mapping is gone.
- Replace raw-description writeBlob with buildTaskTomlBlob, which emits
a four-key TOML document:
status = mapVTODOStatusToFieldValue(...)
priority = mapVTODOPriorityToFieldValue(...)
due = task.Due
notes = task.Description
status / priority / due project as typed fields when the !task type
with reader script is committed (genesis -include-builtin-actionable-
types). notes stays in the blob as free-form text — not declared as
a [[fields]] entry per "blob-only for now" decision.
- New task_blob.go with buildTaskTomlBlob, the four mapping helpers
(vtodo↔field for status and priority, plus inverse versions for the
upcoming decompile path in step 5), and quoteTomlString.
echo/workspace_config_blobs:
- Drop StatusTags from CalendarConfig. v2_tommy.go regenerated.
november/env_workspace:
- Drop StatusTags from the haustoria_caldav.CalendarMapping construction.
The 10 existing CalDAV BATS tests in current_version/haustoria_caldav.bats
are now broken because their assertions encode the old blob digests (built
from raw VTODO description). Step 6 updates those alongside the new
round-trip tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The decompile path (CheckoutOne → Decompile) now reads status, priority, due, and notes from the !task TOML blob produced by buildTaskTomlBlob. The blob is the canonical source of truth — we don't read from Metadata.Index.Fields, so the path works whether or not the !task type with reader script is committed in the repo. task_blob.go gains parseTaskTomlBlob, a constrained line-based parser for the four-key TOML format. It uses strconv.Unquote for value parsing (symmetric with strconv.Quote in the writer). Unknown keys are ignored; blank lines and # comments are skipped. The parser is intentionally NOT a full TOML implementation — the blob shape is owned by buildTaskTomlBlob and parseTaskTomlBlob is the single consumer. Decompile now constructs the caldav.Task with: Status = mapFieldValueToVTODOStatus(values.Status) Priority = mapFieldValueToVTODOPriority(values.Priority) Due = values.Due Description = values.Notes Replaces the previous Description = string(req.Blob) (raw text) and Status = "NEEDS-ACTION" hardcode. task_blob_test.go covers the round-trip: - TestStatusValueRoundTrip: 5 VTODO STATUS values + unknowns - TestPriorityValueRoundTrip: canonical 0/1/5/9 plus out-of-band 2,3,4, 6,7,8 bucketing - TestBuildTaskTomlBlobBasic: known-good TOML output for a populated task - TestBuildTaskTomlBlobEmptyDefaults: zero-value task → todo/p3/empty - TestParseTaskTomlBlobRoundTrip: build then parse, all four keys preserved including multi-line notes - TestParseTaskTomlBlobIgnoresBlankAndCommentLines - TestParseTaskTomlBlobUnknownKeysIgnored Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… step 6) mike/haustoria_caldav/checked_out.go: - Implements ReadCheckedOutFromTransacted by fetching the live VTODO via HTTP GET, projecting it through buildTaskTomlBlob into a fresh *sku.CheckedOut. Required for any commit path that sets options.MergeCheckedOut (organize, etc.). - Implements UpdateCheckoutFromCheckedOut by parsing the daughter's TOML blob, applying inverse status/priority mappings, and PUTting a VTODO to CalDAV. Falls back to the internal slot's ExternalObjectId when ResetWithExceptFields clears the external slot's binding. - Implements Merge as a no-op (last-write-wins toward dodder); proper conflict resolution belongs to #19. - Compile-time interface assertions ensure all three optional store_workspace interfaces are satisfied so the env_workspace wrapper's type assertions don't fail at runtime. mike/haustoria_caldav/main.go: - CheckoutOne now passes object.GetExternalObjectId() through to Decompile as ExternalId. Without this fix, decompile generated a fresh `dodder-N@dodder` UID on every checkout, orphaning the original .ics resource on the server. Pre-existing bug exposed by the new round-trip BATS tests. zz-tests_bats/current_version/haustoria_caldav.bats: - bootstrap helpers now pass -include-builtin-actionable-types so the workspace's experimental repo commits the !task and !chore type definitions. Without this the reader script can't find the type and silently skips field projection. - Drop status-tags blocks from the multi-calendar config; the haustoria no longer reads them. - Update existing 10 tests for the new TOML blob digest layout and the field-column box format. - Rename multi_calendar_status_with_status_tags → multi_calendar_status_field_projection. - Rename completed_tasks_get_status_tag → completed_tasks_get_status_field. - Rewrite assertions from zz-archive-task-done tags to status=done / status=todo field columns. - Add put_vtodo_full and get_vtodo_ical helpers for the round-trip tests. - Add four round-trip BATS tests: - caldav_round_trip_all_fields: full status/priority/due/notes round-trip via checkin → checkout. Doesn't use organize because of a pre-existing blob-digest bug filed as #104. - caldav_round_trip_empty_optionals: defaults flow correctly. - caldav_round_trip_multiline_notes: multi-line VTODO DESCRIPTION survives via strconv.Quote's \n escapes. - caldav_round_trip_out_of_band_priority: PRIORITY:3 buckets to p1. zz-tests_bats/current_version/genesis_actionable_types.bats: - Add genesis_dodder_new_task_projects_fields probe verifying field projection via dodder new (validates the standalone genesis flow). Two follow-up issues filed: - #103: haustoria CalDAV caching via ETag/Last-Modified - #104: organize commit panics on Id.IsNull when daughter blob digest reaches haustoria UpdateCheckoutFromCheckedOut All 14 haustoria_caldav BATS tests pass. Full test suite green. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementation status (pause point)Steps 1–7 complete and pushed (14 commits). Full test suite green. What's done
What's remaining
Issues filed during this PR
🤖 Generated with Claude Code |
Cosmetic: trailing blank line removals and struct field alignment changes applied by `just codemod-go-fmt` during the tommy codegen regeneration in step 4. No behavioral changes.
- Status enum stays as todo/in-process/done/cancelled - Priority becomes p0/p1/p2/p3 enum (tasks.org convention) - Ship !chore as separate built-in alongside !task; future !actionable - New opt-in BigBang.IncludeBuiltinActionableTypes flag (default false) - File extension toml; instances are TOML-mirrored field blobs - Fresh type-blob-digest lookup per compile/decompile cycle - Add field-codec-without-scripts verification test as gating step Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two BATS probes added to fields.bats to answer the open verification question on PR #100: does the binary stream-index codec persist Metadata.Index.Fields when no fields-reader/fields-writer scripts are configured on the type? field_persists_without_any_scripts: type with [[fields]] only, no scripts. Organize-set status field is DROPPED entirely on commit. Blob digest also disappears. Locked assertion: [one/uno !task "my task"]. field_persists_with_reader_only_no_writer: type with reader, no writer. Organize-set status=done is silently overwritten by the reader re-projecting status=todo from the unchanged blob, AND the field appears TWICE in show output (status=todo status=todo). Both findings invalidate the original plan's assumption that the haustoria can set fields directly on metadata without a fields-writer script. The plan needs revision: either ship a TOML field-projector script with !task, or add a code path that bypasses the script gate. The duplicated-field result in probe 2 looks like a separate bug to file independently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three additional BATS probes verify the "ship !task with reader+writer scripts" path: field_full_task_three_fields_from_blob: blob with 3 fields baked in → reader projects all 3 → all display in show. WORKS. field_full_task_organize_mutate_one_of_three: start with 3 fields in blob, organize-set status=done, all 3 persist with writer rewriting the TOML. WORKS. field_full_task_organize_from_empty_blob: empty starting blob → organize-set 3 fields → fields and blob digest both dropped. FAILS the same way as field_persists_without_any_scripts. Conclusion: option 1 + option 2 combined works. !task ships with [[fields]] + [fields-reader] + [fields-writer]. The haustoria writes a complete TOML blob with field values baked in (compile path). The reader projects fields on commit; the writer projects edits back into the blob on subsequent organize mutations. The decompile path reads fields from metadata.Index. The empty-blob case (probe 13) is a non-issue because the haustoria always writes a full blob, never an empty one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR #100 probes proved the original "set fields directly on metadata" assumption wrong. Both tryWriteFields and tryReadFields early-return on missing scripts AND drop the daughter fields before they reach the binary codec. The plan now uses [fields-reader] + [fields-writer] scripts on !task instead. - §1: !task type blob now declares both reader and writer scripts. - §1a: !chore documented as separate built-in with same field set. Future !actionable abstract type captured as out-of-scope. - §3: rewritten as blob-canonical haustoria flow. Compile path writes a TOML blob; reader script projects fields on commit. Decompile reads fields from Metadata.Index.Fields. No fresh type-blob-digest lookup needed; no new code paths in papa/store. - §4: tests updated to reference the already-landed fields.bats probes (cfdb846, c5ebd34) instead of the dropped TestFieldsPersistThroughCommitWithoutScripts. - Open verification → Resolved verification, citing issues #101 and #102 filed against the fields infrastructure. - Implementation order updated to drop the gating test and add the buildTaskTomlBlob compile-path step. - Out of Scope: !chore separate-type bullet replaced with !actionable future-work note; conflict resolution explicitly out of scope. Also annotates docs/plans/2026-04-05-fields-doddish-organize-design.md with #101 and #102 in the Open issues list. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Status enum: in-process -> in_progress (snake_case underscore)
- Priority mapping reversed: p0 is now HIGHEST (matches sev-0 ticket
convention), p3 is lowest. New table:
p0 = !!! = VTODO PRIORITY 1
p1 = !! = VTODO PRIORITY 5
p2 = ! = VTODO PRIORITY 9
p3 = (none) = VTODO PRIORITY 0/absent
- Default priority: p3 (most tasks have no priority assigned)
- Decompile inverse mapping updated accordingly
- Three BATS probes updated with new enum values + recaptured digests
- TestPriorityValueRoundTrip integers swapped to match new mapping
- caldav_round_trip_priority_field example values updated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add built-in TomlV2 constructors for !task and !chore types per the plan in docs/plans/2026-04-06-task-type-genesis-and-haustoria-fields.md. Both types share the actionable field set (status enum todo/in_progress/ done/cancelled, priority enum p0/p1/p2/p3 with p0 highest, due string) plus reader and writer scripts using yq for TOML projection. The shared constructors actionableFields/Reader/Writer are private helpers in the golf/type_blobs package. Re-exported from hotel/type_blobs for downstream consumers. Unit tests verify field definitions, default values, and that the reader/writer scripts contain the expected DODDER_FIELD_* and DODDER_BLOB_PATH variables. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…steps 2-3)
- Add BigBang.IncludeBuiltinActionableTypes (default false).
- prepareBuiltinActionableTypes commits both built-in types via the
typed blob store and adds them to the genesis import plan, gated on
the new flag.
- Expose -include-builtin-actionable-types on the dodder genesis CLI.
- Add genesis_actionable_types.bats with four probe tests:
- default init omits !task and !chore (existing behavior preserved)
- opt-in init commits both alongside !md
- !task type blob round-trips through TOML with the actionable field
set and yq reader/writer scripts (note: tommy serializes script as
triple-quoted multiline)
- !chore and !task have byte-identical blob digests since they share
the same field set + scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ep 4)
Replace the lossy status-tags config + raw-DESCRIPTION blob model with
a TOML blob format that mirrors the !task field set.
mike/haustoria_caldav:
- Drop CalendarMapping.StatusTags. The status-tag tag mapping is gone.
- Replace raw-description writeBlob with buildTaskTomlBlob, which emits
a four-key TOML document:
status = mapVTODOStatusToFieldValue(...)
priority = mapVTODOPriorityToFieldValue(...)
due = task.Due
notes = task.Description
status / priority / due project as typed fields when the !task type
with reader script is committed (genesis -include-builtin-actionable-
types). notes stays in the blob as free-form text — not declared as
a [[fields]] entry per "blob-only for now" decision.
- New task_blob.go with buildTaskTomlBlob, the four mapping helpers
(vtodo↔field for status and priority, plus inverse versions for the
upcoming decompile path in step 5), and quoteTomlString.
echo/workspace_config_blobs:
- Drop StatusTags from CalendarConfig. v2_tommy.go regenerated.
november/env_workspace:
- Drop StatusTags from the haustoria_caldav.CalendarMapping construction.
The 10 existing CalDAV BATS tests in current_version/haustoria_caldav.bats
are now broken because their assertions encode the old blob digests (built
from raw VTODO description). Step 6 updates those alongside the new
round-trip tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The decompile path (CheckoutOne → Decompile) now reads status, priority, due, and notes from the !task TOML blob produced by buildTaskTomlBlob. The blob is the canonical source of truth — we don't read from Metadata.Index.Fields, so the path works whether or not the !task type with reader script is committed in the repo. task_blob.go gains parseTaskTomlBlob, a constrained line-based parser for the four-key TOML format. It uses strconv.Unquote for value parsing (symmetric with strconv.Quote in the writer). Unknown keys are ignored; blank lines and # comments are skipped. The parser is intentionally NOT a full TOML implementation — the blob shape is owned by buildTaskTomlBlob and parseTaskTomlBlob is the single consumer. Decompile now constructs the caldav.Task with: Status = mapFieldValueToVTODOStatus(values.Status) Priority = mapFieldValueToVTODOPriority(values.Priority) Due = values.Due Description = values.Notes Replaces the previous Description = string(req.Blob) (raw text) and Status = "NEEDS-ACTION" hardcode. task_blob_test.go covers the round-trip: - TestStatusValueRoundTrip: 5 VTODO STATUS values + unknowns - TestPriorityValueRoundTrip: canonical 0/1/5/9 plus out-of-band 2,3,4, 6,7,8 bucketing - TestBuildTaskTomlBlobBasic: known-good TOML output for a populated task - TestBuildTaskTomlBlobEmptyDefaults: zero-value task → todo/p3/empty - TestParseTaskTomlBlobRoundTrip: build then parse, all four keys preserved including multi-line notes - TestParseTaskTomlBlobIgnoresBlankAndCommentLines - TestParseTaskTomlBlobUnknownKeysIgnored Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… step 6) mike/haustoria_caldav/checked_out.go: - Implements ReadCheckedOutFromTransacted by fetching the live VTODO via HTTP GET, projecting it through buildTaskTomlBlob into a fresh *sku.CheckedOut. Required for any commit path that sets options.MergeCheckedOut (organize, etc.). - Implements UpdateCheckoutFromCheckedOut by parsing the daughter's TOML blob, applying inverse status/priority mappings, and PUTting a VTODO to CalDAV. Falls back to the internal slot's ExternalObjectId when ResetWithExceptFields clears the external slot's binding. - Implements Merge as a no-op (last-write-wins toward dodder); proper conflict resolution belongs to #19. - Compile-time interface assertions ensure all three optional store_workspace interfaces are satisfied so the env_workspace wrapper's type assertions don't fail at runtime. mike/haustoria_caldav/main.go: - CheckoutOne now passes object.GetExternalObjectId() through to Decompile as ExternalId. Without this fix, decompile generated a fresh `dodder-N@dodder` UID on every checkout, orphaning the original .ics resource on the server. Pre-existing bug exposed by the new round-trip BATS tests. zz-tests_bats/current_version/haustoria_caldav.bats: - bootstrap helpers now pass -include-builtin-actionable-types so the workspace's experimental repo commits the !task and !chore type definitions. Without this the reader script can't find the type and silently skips field projection. - Drop status-tags blocks from the multi-calendar config; the haustoria no longer reads them. - Update existing 10 tests for the new TOML blob digest layout and the field-column box format. - Rename multi_calendar_status_with_status_tags → multi_calendar_status_field_projection. - Rename completed_tasks_get_status_tag → completed_tasks_get_status_field. - Rewrite assertions from zz-archive-task-done tags to status=done / status=todo field columns. - Add put_vtodo_full and get_vtodo_ical helpers for the round-trip tests. - Add four round-trip BATS tests: - caldav_round_trip_all_fields: full status/priority/due/notes round-trip via checkin → checkout. Doesn't use organize because of a pre-existing blob-digest bug filed as #104. - caldav_round_trip_empty_optionals: defaults flow correctly. - caldav_round_trip_multiline_notes: multi-line VTODO DESCRIPTION survives via strconv.Quote's \n escapes. - caldav_round_trip_out_of_band_priority: PRIORITY:3 buckets to p1. zz-tests_bats/current_version/genesis_actionable_types.bats: - Add genesis_dodder_new_task_projects_fields probe verifying field projection via dodder new (validates the standalone genesis flow). Two follow-up issues filed: - #103: haustoria CalDAV caching via ETag/Last-Modified - #104: organize commit panics on Id.IsNull when daughter blob digest reaches haustoria UpdateCheckoutFromCheckedOut All 14 haustoria_caldav BATS tests pass. Full test suite green. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…step 8) FDR-0007 (checkout-bridges): status exploring → experimental. The promotion criteria (CheckoutStore with Compile/Decompile + round-trip BATS test) are met by the CalDAV haustoria with typed field round-tripping. Updated Implementation Status section to reflect PR #100 work: - 14 BATS tests + 4 round-trip tests - !task and !chore built-in types with status/priority/due fields - Compile/decompile paths through TOML blob + reader/writer scripts - Remaining gaps: partial property coverage, no three-way merge, no sub-object decomposition, no ETag caching !vtodo langlang design: added supersede note pointing at the task-type-genesis plan.
Plan-only PR. Comment on
docs/plans/2026-04-06-task-type-genesis-and-haustoria-fields.mddirectly to drive decisions.Drops the
!vtodopersisted-type plan (docs/plans/2026-04-05-vtodo-langlang-design.md) — VTODO format becomes a haustoria-side concern only. Two changes proposed:!taskinto the bigbang/genesis process withstatus/priority/duefield definitions, alongside the existing!mddefault type.!taskfield mapping insidemike/haustoria_caldav(compile + decompile), replacing the lossystatus-tagsconfig.Six decisions to confirm in the "Decisions to confirm" section.
🤖 Generated with Claude Code