Repository navigation
Flags that mean what they say + time-aware capture · Closes #244 · Refs #179 - #248
Merged
Merged
Conversation
Two QA defects and the #179 opener. 1. Flag tangle. The workflow executor gated moments/index on BOTH the flag AND the presence of a drain step, so a document without a moments/index step silently disabled the Settings toggle under workflow.enabled — the headline QA case (flags ON, empty Moments/Relevant-now). Make the flags AUTHORITATIVE: a present step may re-bind its gate (documents stay meaningful as data), but its ABSENCE falls back to the flag, exactly as the legacy direct drain does. distill.fields is already immune — it rides the shared distillThrottled seam, gated by its flag directly, not a step. 2. First-person extraction. The extract-moments template defined a commitment as "someone promised to do something"; small models returned [] for "I need to…/I'll…". The commitment kind now explicitly includes first-person intent, keeping the 4 shipped kinds and the strict-JSON invent-nothing rule. 3. Deadlines (#179 opener). Add optional TodoItem.due (validated absolute time) + a dueSource provenance marker. task-extract gets a {{now}} anchor and requests an optional ISO due; the engine validates post-hoc (parseable ISO, within a -60s..+60d horizon; invalid dropped, item kept) and falls back to a deterministic "in N minutes/hours/days" resolver (digits + number words) over the item text so the flagship "in eighteen minutes" works on weak models. todos surface renders due as an honest, unselectable "due 3:29p" decoration. Closes #244 · Refs #179
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Live QA: with extraction feature flags ON, Moments and Relevant-now stayed empty while distillates flowed, and a first-person intent with a spoken deadline ("provide feedback to QA in eighteen minutes") produced no moment, no to-do, and no deadline.
What
1. Flags are authoritative across both drain paths (the silent-inert fix)
The direct drain read
distill.moments/distill.indexfrom the flag store; the workflow executor ADDITIONALLY required amoments/indexdrain step, so a document without those steps silently disabled the Settings toggle underworkflow.enabled.Design chosen: the executor treats the flag as authoritative. moments/index are not independent pipeline stages — they are two boolean OPTIONS on the single distill call the drain already makes — so the user-facing Settings flag is the authority. A present step may re-bind its gate to a different flag (advanced document composition stays meaningful as data); a step's absence falls back to the flag, exactly as the legacy direct drain does. For the seeded default (which binds these very flags) behavior is identical.
distill.fieldswas audited and is immune: it ridesdistillThrottled(the shared distill seam), gated by its flag directly, never by a workflow step. Drain acts (task-extract) are intentionally left step-keyed — an act names a runner + template, so the flag alone cannot drive it.2. First-person commitments
The extract-moments template's commitment definition now explicitly includes first-person intent ("I need to… / I'll… / I have to… / let me… / I should…"), keeping the 4 shipped kinds and the strict-JSON invent-nothing discipline.
3. Deadlines — the #179 opener (smallest roadmap-true slice)
TodoItem.due(optional, validated absolute ISO time) + adueSourceprovenance marker (model|anchored). Chose TodoItem over Commitment: the to-do path is already wired end-to-end (extract → merge → store → render);Commitmenthas zero producers and no store/render path, so extending it would be a much larger slice, not the smallest opener. Commitment remains the eventual durable home for #179.{{now}}anchor (the extraction wall-clock = window end) and requests an optional ISOdue.-60s .. +60 dayshorizon (60s absorbs clock skew; >60 days is almost certainly a hallucinated date, not a live deadline). Invalid ⇒ due dropped, todo kept.in N minutes/hours/days, digits + number words incl. "eighteen", "forty-five") anchored tonow, so the flagship case works on weak local models that echo the phrase but cannot compute ISO.due 3:29pdecoration — absent/invalid due ⇒ no decoration, no fake urgency; copy payload stays the bare todo text.Tests
{{now}}anchor + optional ISO due)..dueunselectable) and a copy-payload negative guard.Full gate green: contracts 114, engine 1125, client 621. Schema regen committed zero-drift; governance dry-run PASS.
Do not merge pending review.