tldr-experts 0.30.0 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/README.md +2 -0
  3. package/dist/hooks/answer-capture.js +9 -8
  4. package/dist/hooks/budget-gate.js +9 -9
  5. package/dist/hooks/{chunk-fbmj1bk6.js → chunk-04kpbhvk.js} +3 -3
  6. package/dist/hooks/{chunk-pne7afnf.js → chunk-27v2rwa9.js} +1 -1
  7. package/dist/hooks/{chunk-przta0a0.js → chunk-4ygy9w7j.js} +16 -6
  8. package/dist/hooks/{chunk-857jhjmb.js → chunk-5kv2vtha.js} +1 -1
  9. package/dist/hooks/{chunk-7xascvee.js → chunk-72et1xzx.js} +1 -1
  10. package/dist/hooks/{chunk-0d4csx4s.js → chunk-8ds2ret8.js} +1 -1
  11. package/dist/hooks/{chunk-qmp5p77c.js → chunk-9bd6b3xf.js} +1 -0
  12. package/dist/hooks/chunk-ae6bkfs5.js +0 -0
  13. package/dist/hooks/{chunk-77x6v0gg.js → chunk-akemhezh.js} +3 -2
  14. package/dist/hooks/{chunk-gr83pq7x.js → chunk-f9d2efhb.js} +3 -3
  15. package/dist/hooks/{chunk-zpch8e2j.js → chunk-me0kzc6k.js} +2 -2
  16. package/dist/hooks/{chunk-mg3aj0sa.js → chunk-q1ge3nex.js} +1 -1
  17. package/dist/hooks/{chunk-yanmz0vz.js → chunk-x1f4dxwk.js} +1 -1
  18. package/dist/hooks/{chunk-g4d2v4jc.js → chunk-yyhwf3bp.js} +1 -1
  19. package/dist/hooks/{chunk-z9hv47ps.js → chunk-zyz0fbz5.js} +1 -1
  20. package/dist/hooks/claim-sources.js +5 -5
  21. package/dist/hooks/dod-gate.js +7 -7
  22. package/dist/hooks/no-reask.js +8 -8
  23. package/dist/hooks/session-start.js +13 -12
  24. package/dist/hooks/statusline.js +9 -8
  25. package/dist/tldrx.js +1238 -827
  26. package/package.json +1 -1
  27. package/plugin/.claude-plugin/plugin.json +1 -1
  28. package/stages/how/stage.md +0 -1
  29. package/stages/how/stage.yml +31 -2
  30. package/workflows/bugfix.yml +5 -1
  31. package/workflows/feature.yml +5 -1
  32. package/workflows/integration.yml +5 -1
  33. package/workflows/performance.yml +5 -1
  34. package/workflows/refactor.yml +5 -1
  35. package/workflows/upgrade.yml +5 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,216 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.31.1 — 2026-09-16
4
+
5
+ ### Fixed
6
+
7
+ - **A seed placed at the documented `.tldrx/seeds/<slug>.md` location was invisible to the #346
8
+ `seed_solution` skip, so `how` ran at full price even when the seed already declared its own
9
+ `## Solution` (#358).** `seedDocumentPaths` (`src/core/facilitator/seedSolution.ts`) filtered
10
+ out every first-stage input starting with `.tldrx/` — meant to drop the `what` stage's own
11
+ template inputs (`.tldrx/memory/facts.yml`, `.tldrx/map/{repo}/domains.md`), it also swallowed
12
+ `.tldrx/seeds/…`, the exact path `run new --seed` records and the docs tell writers to use. Now
13
+ only those two template-input families are excluded, so a seed document is recognised wherever
14
+ `run new --seed` accepted it from.
15
+
16
+ ## 0.31.0 — 2026-09-16
17
+
18
+ ### Added
19
+
20
+ - **A `[src:]` citation on a Watch card that only has a punctuation slip — the marker missing its
21
+ space, a token sitting mid-sentence, an ASCII `->` in place of the real arrow — is repaired
22
+ locally, for $0.00, before the card is judged, instead of failing the stage over formatting a
23
+ script already knew how to fix (#345, watch-card half). Measured over two field audits: 10 of 54
24
+ failed tasks across 22 runs in one workspace were malformed watch cards — caught only after a
25
+ full paid turn wrote the card, by the same `parseWatcherCard` this repair now runs ahead of.
26
+ `repairSrcSyntax` (`src/core/text/srcToken.ts`) only accepts a fix it can VERIFY
27
+ re-parses clean (mirrors `parseYamlRepairing`'s own rule) and only touches the three rules that
28
+ are pure syntax — `marker-spelling`, `trailing-position`, `cmd-arrow` — never a rule that would
29
+ need an invented line number, path or fact id (AGENTS.md §7). The repair is written back to disk
30
+ whether or not the card ends up valid, and it is never silent: named in the stage's own report
31
+ when it clears the card, and in the failure reason when a genuine defect remains — the file on
32
+ disk already carries the fix, so a retry's `previousCard` prompt (`watchPrompt.ts`) shows a writer
33
+ only the part a script could not repair (owner decision 2026-09-15: auto-repair is visible, never
34
+ silent).
35
+
36
+ - **`how` is skipped when the seed already declares its own technical solution, and `plan` reads
37
+ that section instead (#346).** Owner decision, measured against three samples where `how`
38
+ reworked a seed that already carried the answer: 11.4-45% of a run's spend and 43-53% of its
39
+ own bytes went unread downstream. The trigger is one exact, documented marker — an H2 `##
40
+ Solution` or `## Technical approach` in a seed document — never inferred from prose:
41
+ `src/core/facilitator/seedSolution.ts` reuses `seed/seedClaims.ts`'s fence-aware heading reader
42
+ rather than a second regex, and exposes it to the existing `skip_if` grammar as a new
43
+ `seed_solution` predicate (`skipIf.ts`, `(stories|repos|questions|seed_solution)<op>N`). Since no
44
+ shipped `workflows/*.yml` uses the §2.4 record shape a workflow-level `skip_if` needs, a stage's
45
+ own top-level `skip_if:` in `stage.yml` is now read as its built-in default when the workflow
46
+ names none (`stageSpec.ts`'s `overlay`, a workflow's own `skip_if` for that stage id still wins);
47
+ the shipped `stages/how/stage.yml` sets `skip_if: "seed_solution==1"` this way. The skip is
48
+ recorded exactly like any other `skip_if` (`stage.skipped`, named on the run), and — because this
49
+ is the one skip that would otherwise leave `plan` reading a `02-how/design.md` that silently
50
+ looks empty — `tldrx next` additionally materialises that file from the seed's declared section
51
+ verbatim, cited back to the seed, the moment the skip fires.
52
+
53
+ - **A failed sub-agent turn now carries a named `failure_kind`** — `timeout`, `rate_limit`
54
+ (reusing #298's own quota-frame detection), `process_killed`, `empty_result`, `non_zero_exit`,
55
+ `result_error`, `malformed_result`, or `unclassified` (with the raw signal still in `error`) —
56
+ on the task row and the `agent.result` event, additive and absent on every ordinary/successful
57
+ turn and on a read-cap kill (`stopped_by` already names that one). `result_error` is
58
+ `non_zero_exit`'s exitCode-0 sibling (pre-merge review, 2026-09-15): the result document itself
59
+ reports `is_error: true` with a named reason while the process exited `0`, which used to read
60
+ `non_zero_exit` — a label contradicting its own exit code. Measured, one field audit (workspace
61
+ B, 2026-09-15): 24 of 54 failed tasks in that sample were an undifferentiated "timeout / generic
62
+ error" — the largest single bucket, unnamed until now. Classification only: no new retry
63
+ budgets, and nothing decides a retry off this field (#348, the family of #341/#298).
64
+
65
+ ### Changed
66
+
67
+ - **`watch` now follows `build`'s gate policy in every shipped scope where `build` is already
68
+ `auto` — `feature`, `bugfix`, `integration`, `refactor` and `performance` (#349, owner decision
69
+ 2026-09-16).** Every one of these scopes shipped `build: auto` with `watch: human` regardless,
70
+ so a run that trusted Build's own auto-gate still stopped a person at the very next stage over
71
+ a transcription job with a validator behind it. The reasoning is field evidence, not a guess:
72
+ auto-gating `what`/`how`/`plan` in a real workspace since 2026-09-12 produced zero measured
73
+ auto-gate incidents across 26 runs (77 `gate.rejected`, 100% human, 0 auto-rejections). The
74
+ mechanism is unchanged — `evaluateAutoGate` (`src/core/run/autoGate.ts`) already closes any
75
+ stage's gate the same way once its policy is `auto`, and a self-signed `watch` gate is
76
+ announced through the exact same `gate.requested`/`gate.approved`/`stage.done` events an
77
+ auto-signed `what`/`how`/`plan` gate already is — this does not widen the notify-window gap
78
+ tracked separately in #250, it only extends the existing behavior to one more stage. `upgrade`
79
+ is the one shipped scope excluded: `what`/`plan`/`build` are already all `auto` there, and
80
+ following `build` would leave it with no human gate at all, which spec.md's "no all-auto
81
+ preset" guarantee forbids — its `watch` stays `human`. `hotfix`/`security-patch`/`migration`
82
+ are unaffected: their `build` gate is `human`, so the "build already signed" condition never
83
+ applies. The tutorial's attended chapter (`tldrx learn`, chapter 7) ran its `next --commit` on
84
+ a `feature`-scope run expecting the Watch gate to still stop it (`expectExit: [4]`) — now that
85
+ `watch` self-signs there, the chapter sets it back to `human` explicitly first
86
+ (`run gates set watch:human --note …`), because the lesson is the attended human handoff, not
87
+ the shipped default.
88
+
89
+ - **`how`'s default model is `sonnet`, not `opus`** (#346). Owner decision, measured across a
90
+ single-run analysis and two workspace audits: `how` cost $10.40-$269.90 per sample, 11.4-45% of
91
+ the run's total spend. A workspace or a single invocation that wants the strong model back
92
+ overrides it exactly as before — `.tldrx/stages/how/stage.yml` with `model: opus`, or
93
+ `tldrx next --model opus` / `tldrx run auto --model opus` for one invocation.
94
+
95
+ - **`how` stops generating `risks.md`** (#350). Owner decision 2026-09-16 — "stop generating,"
96
+ not "generate and drop from the bundle" — because nothing downstream ever read it: measured
97
+ on a real run, `risks.md` (8,025 bytes) was excluded by `stages/plan/stage.yml`'s own
98
+ `inputs:` (only `design.md`, `contracts.md`, `test-strategy.md`) and a repo-wide grep found no
99
+ other reader. `handoff.md` and `questions.md` are unchanged — they carry no bundle content
100
+ either, but they are load-bearing elsewhere (the auto gate, `claim-sources`, `boundary`'s
101
+ `SURFACE_HANDOFFS`, the dashboard). `validateOutputs` only ever checks the DECLARED output
102
+ list, so a run directory written before this change that still has `02-how/risks.md` on disk
103
+ is unaffected — the file is simply not asked for anymore, never flagged as missing or
104
+ re-demanded on resume.
105
+
106
+ ### Fixed
107
+
108
+ - **A headless turn whose parent `tldrx` process is SIGKILL-class killed mid-spawn now banks its
109
+ cost as unmetered rather than nowhere at all (#337, the remaining half of #246).** #246's field
110
+ case: a `run auto` process died while blocked in `spawnAgent`'s `await` (`runNext.ts`); the
111
+ orphaned `claude` child kept running to completion, but `run.yml`'s `budget.spent_usd` stayed
112
+ `0.00` forever, because `demoteStaleRunning` — the code that finds the dead `.lock` and puts the
113
+ stage back to `ready` — wrote no task row for that attempt at all, not even an unmetered one. A
114
+ confident `0.00` for money a provider may really have charged is the one answer AGENTS.md §7
115
+ rules out. `demoteStaleRunning` now reads `startedHeadless` (`run/lastStart.ts`, the one
116
+ derivation of which mode opened a stage's last turn — already used by the Ctrl-C path) and, for
117
+ a genuinely orphaned HEADLESS spawn (never a `--prepare` bundle waiting for a human, and never a
118
+ Build executor phase, both of which are `preparedRefusal`'s and the executor's own business),
119
+ records a `status: "failed"` task with `cost_usd: null, metered: false` and
120
+ `error: "turn outlived its parent; no result line was read"` before demoting the stage — so
121
+ `spendBasis`/`tallyOf` (the one derivation, unchanged) count it as a LOWER BOUND, and `run
122
+ status`/`budget show`/the dashboard say so instead of printing a silent `$0.00`.
123
+
124
+ - **`run auto` now names `--wait-gates` as the fix, at the moment an all-`auto` gate's only
125
+ blocking questions are answered but nothing will sign it (#342).** Measured live on a
126
+ `--gates none --questions none` run launched with no `--wait-gates`/`--wait-answers`: the
127
+ loop answers a blocking question itself (`questions_policy: recommended`) or once
128
+ `--wait-answers` polls one in, but the ONLY thing that ever self-closes a parked `auto`
129
+ gate is `selfCloseAutoGate`, reached only from `waitForGate`'s poll — so the next `next`
130
+ call reports the stage as `awaiting_gate` with a generic `gate pending: tldrx approve`,
131
+ never saying the gate would have closed itself with one more flag. `settleDeferredGate`
132
+ (`runAuto.ts`) now says so, by name, at the exact moment the gap is decided. The deeper fix
133
+ — `next` re-evaluating a parked `auto` gate on its own, so this holds even for a `next`
134
+ launched by hand — is recommendation (1) on the issue and stays open there; it touches
135
+ `runNext.ts`, out of scope for this change.
136
+
137
+ - **The base-tree DoD refusal now names the workspace's own declared `install:` as the fix
138
+ (#343).** Measured on a fresh clone where a multi-step installer had only partly run: the
139
+ refusal reported `eslint`/`tsc`/`vitest` all `command not found`, identical in shape to a
140
+ genuinely broken repo, even though the same `WorkspaceContext` the refusal already reads
141
+ carries the workspace's own `install:` line. `baseRefusalLines` (`preflight.ts`) now names
142
+ it, once per repo — never runs it: running an installer against the operator's own
143
+ checkout, unasked, ahead of a refusal that has not yet told them anything, is exactly the
144
+ side effect the base-measurement design already avoids for gate commands. The zero-touch
145
+ first-run guide (EN/ES) now says explicitly to run the declared `install:` in the checkout
146
+ itself before the first `run auto`, not only in a story's worktree.
147
+
148
+ - **`run status` now warns NO-RETRY on a phase that cannot afford a second attempt of its own
149
+ stage, not only `budget show` (#232).** The narrowed #232 asked for this at both screens;
150
+ `budget show` shipped it in `bd19763`/`efb4eee` and this closes the other half. `run status`
151
+ computed no retry verdict at all, so a pre-#170 run (sized for exactly one attempt) read every
152
+ phase as an ordinary progress bar right up to the refusal — the exact "operator discovers it at
153
+ the retry" failure the issue is about, just on the screen that gets opened more often. Shares
154
+ the one `retrySizing` derivation and the one `NO-RETRY` sentence (`noRetryBlock`, now exported
155
+ from `budgetView.ts`) that `budget show` already used, so the two screens cannot disagree about
156
+ the same measured shortfall. `buildStatus` takes an optional `root` (both CLI and `run auto`'s
157
+ heartbeat now pass it) to resolve the next stage's own `attempts:` the same tolerant way
158
+ `budget show` does; omitted, it falls back to the shipped default, so a caller that does not pass
159
+ it behaves exactly as before.
160
+
161
+ - **A fix list dispositioned away from `fix-now` by hand, after the story already parked `review`
162
+ behind it, now settles `done` with no agent spawned instead of buying a fresh developer round and
163
+ a full DoD re-run for nothing (#218).** Measured live: a reviewer signed `fixlist` with an open
164
+ finding, parking the story at `review`; the finding was later re-routed away from `fix-now`
165
+ outside the audited auto-close (which only ever closes what a spawned reviewer's approve was
166
+ shown); nothing else re-read the file, so the next `--prepare`/headless pass read `fixlistFor`'s
167
+ unnamed door returning `null` (0 open — correctly, it is not to be re-rendered) as "no fix list
168
+ ever happened" and dispatched a plain developer bundle for a story nothing faulted — one
169
+ developer task and one full DoD re-run over an unchanged tree. `closedFixlistCandidates` /
170
+ `settleClosedFixlists` (gh #329's pre-pass) now also recognizes a `review` story parked on a spent
171
+ `fixlist` verdict, alongside the `blocked`/`approve` shape it already settled, and asks
172
+ `openFixNow` before either. `--fixlist <path>` naming a file with 0 open findings is now a refusal
173
+ that names the file and the count, not a silent downgrade to a bundle.
174
+
175
+ - **A fix list the parser could not fully read — a typo'd `Disposition:` word, or a round file
176
+ emptied by a crash or a disk-full write — can no longer settle a story `done` (#218, pre-merge
177
+ review).** Reviewer-measured: `**fix-now**` mistyped `**fix-noww**` is silently dropped by
178
+ `parseFixlistFile` (by design — a heading with no readable disposition is not a finding, and
179
+ inventing `fix-now` for it would block a story over a typo), so `openFindings(...).length` read 0
180
+ exactly as it would for a genuinely closed round, and a plain `--prepare` settled the story `done`
181
+ with no spawn and no re-review over a live, undetected defect. `parseFixlistFile`'s parse now also
182
+ reports what it could not read (`unreadableFindings`/`fixlistFullyParsed`, `fixlist.ts`), and
183
+ `openFixNow`/`closedFixlistCandidates` (both the `blocked`/`approve` shape and the `review`/
184
+ `fixlist` shape above share this one check) hold rather than settle when a round parsed
185
+ uncleanly, naming the exact heading and line that could not be read.
186
+
187
+ - **`--fixlist <path>` naming a file this framework cannot fully parse — corrupted, truncated, or
188
+ another story's misnamed file — refuses with exit 1 (usage), not exit 5 (agent failed) (#218,
189
+ pre-merge review).** The refusal used to throw out of `fixlistFor` and land in the generic
190
+ executor `catch`, which reads any thrown `Error` as a STAGE failure: `run.yml`'s stage was stamped
191
+ `status: failed` with `cost_usd: 0.00`, and the next `tldrx next` printed "retrying … (cost already
192
+ spent is not refunded)" — a lie, since the refusal fires before anything is opened or spent. It
193
+ now returns the same `refusedOnSequence` precondition-refusal `offerAtFrontier`'s dependency wait
194
+ already uses: exit 1, `run.yml` untouched, no false retry line. The unnamed door's own corruption
195
+ check is scoped to `--prepare` only (the one caller with a `try`/`catch` around it) — the headless
196
+ in-session fix-round spawn keeps the pre-#218 fallback (a corrupted round is treated as absent
197
+ rather than crashing the run mid-wave), since the correctness half above already closes the
198
+ dangerous direction independently of this door.
199
+
200
+ - **A relaunch of `tldrx run auto <runId>` resuming its OWN already-claimed epic branch now
201
+ verifies it instead of trusting it silently (#347).** `run auto` does not expose `--reuse-epic`
202
+ (there is nobody present to type it), so `foreignEpicRefusal`'s `claimed.has(branch)` case — this
203
+ run's own `build.epic_branch` already naming the branch a killed attempt cut and claimed before
204
+ it died — was a bare `continue`: no check that the branch head still resolved, no gate, and no
205
+ record that anything had been resumed at all. It now confirms the branch is still reachable and,
206
+ when the repo declares a `typecheck` command, runs it once in a throwaway detached worktree
207
+ (removed immediately after) before trusting the claim; a repo with no `typecheck` role is
208
+ adopted with that said explicitly (`typecheck: absent`) rather than assumed green. Recorded
209
+ honestly either way — an `epic.resumed` line and event carrying the sha and the typecheck
210
+ verdict — and a typecheck that FAILS refuses the stage by name instead of building on a possibly
211
+ broken branch (`tldrx next --reuse-epic` still adopts it deliberately, unchanged). A claim
212
+ another run wrote is refused exactly as before — nothing here relaxes that guard.
213
+
3
214
  ## 0.30.0 — 2026-09-15
4
215
 
5
216
  ### Fixed
package/README.md CHANGED
@@ -335,6 +335,8 @@ back on the registry is 0.3.0.
335
335
 
336
336
  | Version | Date | Status | Contains |
337
337
  |---|---|---|---|
338
+ | 0.31.1 | 2026-09-16 | `beta` | One fix, measured on the first unattended run under 0.31.0: a seed placed at the documented `.tldrx/seeds/` location was invisible to the seed-solution detector, because the filter that drops the `what` stage's own framework inputs dropped every `.tldrx/` path, so `how` ran at full price for exactly the seeds #346 was written to skip (#358). |
339
+ | 0.31.0 | 2026-09-16 | `beta` | Ten efficiency adjustments, ranked from a measured audit of 48 runs, so an unattended run spends less and stalls less. `how` is skipped when the seed already declares its own solution, and runs on `sonnet` when it does run (#346); `risks.md` is no longer generated (#350); `watch` follows `build`'s gate policy, so an all-auto run signs itself (#349); a Watch card's `[src:]` punctuation slip is repaired locally instead of costing a turn (#345); a fix list with zero open findings settles the round, an unreadable one holds it by name (#218); `run status` warns NO-RETRY before a retry the budget refuses (#232); a failed headless turn carries a named `failure_kind`, so the loop stops buying the same retry for every death (#348); an orphaned turn is banked as unmetered instead of a confident zero (#337); a relaunch resumes its own epic branch instead of restarting it (#347); the base-tree DoD refusal names the workspace `install:` (#343) and `run auto` names `--wait-gates` (#342). |
338
340
  | 0.30.0 | 2026-09-15 | `beta` | Seventeen changes that keep an unattended run moving instead of stranding. A cached Build refusal says so and a relaunch re-measures it (#339); a rate-limit warning is read instead of dropped, so a Build parks before the wall (#298); the plan-over-stage advisory speaks only past 2× (#302); a stage death stops recommending a retry the budget refuses (#232); a DoD command is measured twice, a fix-list finding is checked against the epic tip, and an over-long sha is refused by name (#163); a formatting slip gets one bounded repair turn (#288); five Checks stop asking the reviewer for what it can't do (#195); a Codex review no longer dies before it runs (#148); `tldrx init` probes four commands at once (#180); `tldrx ship` refuses a merged diff nobody judged (#311). Docs: the zero-touch recipe pairs `run auto` with `--wait-gates`/`--wait-answers` (#342). |
339
341
  | 0.29.0 | 2026-09-15 | `beta` | Sixteen changes that make an unattended run trust its own gates and its own numbers. Verdict integrity: a reviewer's `changes` must cite evidence (#326), a re-reviewed story's `changes` is consumed instead of parking it (#327), and a story blocked on a stale fix list settles `done` once resolved (#329). Fix-list flow: a headless fix list now buys its own fix round, and an approving reviewer's signature closes what it was shown (#327). Money and phase sizing: `run auto` rebalances a blocked phase's shortfall out of finished phases by default (#330), the `budget-gate` hook stops denying the launch that would fix the shortfall (#321), a Build gate no longer stops on paths outside the declared surface but carries them into the PR instead (#331), a parallel wave no longer hands two developers the same unspent money (#325), `budget show`/`run estimate`/the budget-gate hook price remaining work off the stage's own `attempts:` (#214), `run auto --until-done` states a token refusal in tokens rather than invented dollar words (#270), a Watch turn is recorded as unmetered rather than a false `$0.00` (#224), and a Watch spawn now records the ceiling it was given (#190). Dependency and safety: a Build gate names the story a dependent waits on (#303), the conflict-turn marker guard names unreadable paths, bounds its scan, and covers modified files too (#324), a developer's array-valued `notes` is joined instead of silently dropped (#217), and the Plan prompt states its per-item character cap where each field is described so an over-cap finding survives into the retry (#328). |
340
342
  | 0.28.1 | 2026-09-15 | `beta` | Two fixes so a reopened story's reason reaches the agents that need it. The developer and reviewer prompts now carry `## Why this story was reopened` — who signed it, whether it's a fix round, the note verbatim — off the same ledger value #308 reads, instead of the note reaching only a report line and #308's check (closes #322). `tldrx note --help` now says an operator note reaches no agent and names `dispatch-notes.md` as the channel that does (closes #151). |
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  conflictOf
4
- } from "./chunk-fbmj1bk6.js";
4
+ } from "./chunk-04kpbhvk.js";
5
5
  import {
6
6
  FactsStore,
7
7
  formatJaccard
8
- } from "./chunk-gr83pq7x.js";
8
+ } from "./chunk-f9d2efhb.js";
9
9
  import {
10
10
  parseHookInput,
11
11
  readStdin
12
- } from "./chunk-z9hv47ps.js";
12
+ } from "./chunk-zyz0fbz5.js";
13
+ import"./chunk-ae6bkfs5.js";
13
14
  import {
14
15
  EventLog,
15
16
  PHASE_ID_RE
16
- } from "./chunk-77x6v0gg.js";
17
+ } from "./chunk-akemhezh.js";
17
18
  import {
18
19
  PHASE_IDS
19
- } from "./chunk-g4d2v4jc.js";
20
- import"./chunk-857jhjmb.js";
20
+ } from "./chunk-yyhwf3bp.js";
21
+ import"./chunk-5kv2vtha.js";
21
22
  import {
22
23
  ADVISORY_KEY,
23
24
  MAX_FACT_CHARS,
@@ -27,7 +28,7 @@ import {
27
28
  renderQuestionBlock,
28
29
  replaceBlock,
29
30
  serializeQuestions
30
- } from "./chunk-yanmz0vz.js";
31
+ } from "./chunk-x1f4dxwk.js";
31
32
  import {
32
33
  ITERATION_ONLY_SLOT,
33
34
  PROJECT_FRAMEWORK_DIR,
@@ -37,7 +38,7 @@ import {
37
38
  isScopedTemplate,
38
39
  parseYaml,
39
40
  scopedSlotOf
40
- } from "./chunk-qmp5p77c.js";
41
+ } from "./chunk-9bd6b3xf.js";
41
42
 
42
43
  // src/hooks/answer-capture.ts
43
44
  import { existsSync as existsSync5 } from "fs";
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  budgetGateDeny
4
- } from "./chunk-mg3aj0sa.js";
4
+ } from "./chunk-q1ge3nex.js";
5
5
  import {
6
6
  allow,
7
7
  deny,
8
8
  readPayload,
9
9
  runHook,
10
10
  toolInput
11
- } from "./chunk-pne7afnf.js";
12
- import"./chunk-z9hv47ps.js";
11
+ } from "./chunk-27v2rwa9.js";
12
+ import"./chunk-zyz0fbz5.js";
13
13
  import {
14
14
  REBALANCE_SOURCE,
15
15
  applyRebalance,
@@ -27,10 +27,10 @@ import {
27
27
  validateRunBudget,
28
28
  wouldExceed,
29
29
  wouldExceedHostTokens
30
- } from "./chunk-zpch8e2j.js";
30
+ } from "./chunk-me0kzc6k.js";
31
31
  import {
32
32
  EventLog
33
- } from "./chunk-77x6v0gg.js";
33
+ } from "./chunk-akemhezh.js";
34
34
  import {
35
35
  cursorStage,
36
36
  hostTokensIn,
@@ -39,20 +39,20 @@ import {
39
39
  newestActiveRun,
40
40
  renderRunEconomies,
41
41
  runSpend
42
- } from "./chunk-0d4csx4s.js";
42
+ } from "./chunk-8ds2ret8.js";
43
43
  import {
44
44
  buildStageDefaults
45
- } from "./chunk-g4d2v4jc.js";
45
+ } from "./chunk-yyhwf3bp.js";
46
46
  import {
47
47
  noteDeprecations
48
- } from "./chunk-yanmz0vz.js";
48
+ } from "./chunk-x1f4dxwk.js";
49
49
  import {
50
50
  PROJECT_WORK_DIR,
51
51
  findWorkspaceRoot,
52
52
  locateWork,
53
53
  parseYaml,
54
54
  stageYamlPath
55
- } from "./chunk-qmp5p77c.js";
55
+ } from "./chunk-9bd6b3xf.js";
56
56
 
57
57
  // src/hooks/budget-gate.ts
58
58
  import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "node:fs";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  findDuplicate
3
- } from "./chunk-gr83pq7x.js";
3
+ } from "./chunk-f9d2efhb.js";
4
4
  import {
5
5
  evidencePath,
6
6
  gateEvidencePath,
7
7
  parseEvidence
8
- } from "./chunk-77x6v0gg.js";
8
+ } from "./chunk-akemhezh.js";
9
9
  import {
10
10
  openBlocks,
11
11
  parseQuestions
12
- } from "./chunk-yanmz0vz.js";
12
+ } from "./chunk-x1f4dxwk.js";
13
13
 
14
14
  // src/core/distill/distill.ts
15
15
  var CONFLICT_THRESHOLD = 0.6;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parseHookInput,
3
3
  readStdin
4
- } from "./chunk-z9hv47ps.js";
4
+ } from "./chunk-zyz0fbz5.js";
5
5
 
6
6
  // src/hooks/lib/decide.ts
7
7
  function deny(reason) {
@@ -9,7 +9,7 @@ import {
9
9
  spentBasis,
10
10
  tallyOf,
11
11
  validateRunBudget
12
- } from "./chunk-zpch8e2j.js";
12
+ } from "./chunk-me0kzc6k.js";
13
13
  import {
14
14
  EventLog,
15
15
  OUTCOME_NOT_RECORDED,
@@ -22,12 +22,12 @@ import {
22
22
  isTerminal,
23
23
  stageAt,
24
24
  validateRunFile
25
- } from "./chunk-77x6v0gg.js";
25
+ } from "./chunk-akemhezh.js";
26
26
  import {
27
27
  cursorStage,
28
28
  isAttendedByHostView,
29
29
  openRunViews
30
- } from "./chunk-0d4csx4s.js";
30
+ } from "./chunk-8ds2ret8.js";
31
31
  import {
32
32
  backupPathFor,
33
33
  isAlive,
@@ -36,21 +36,22 @@ import {
36
36
  workspaceRootOfRunDir,
37
37
  writeAtomic,
38
38
  yamlScalar
39
- } from "./chunk-857jhjmb.js";
39
+ } from "./chunk-5kv2vtha.js";
40
40
  import {
41
41
  isAdvisory,
42
42
  noteDeprecations,
43
43
  openBlocks,
44
44
  parseQuestions
45
- } from "./chunk-yanmz0vz.js";
45
+ } from "./chunk-x1f4dxwk.js";
46
46
  import {
47
47
  FRAMEWORK_ROOT,
48
48
  MAX_ITEM_CHARS,
49
49
  PLAN_STATUSES,
50
+ PROJECT_FRAMEWORK_DIR,
50
51
  listRunDirs,
51
52
  parseYaml,
52
53
  parseYamlRepairing
53
- } from "./chunk-qmp5p77c.js";
54
+ } from "./chunk-9bd6b3xf.js";
54
55
 
55
56
  // src/core/statusline/runSnapshot.ts
56
57
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
@@ -134,6 +135,7 @@ function task(t, indent) {
134
135
  `${inner}error: ${yamlScalar(t.error)}, session_id: ${yamlScalar(t.session_id)},`,
135
136
  `${inner}started_at: ${yamlScalar(t.started_at)}, ended_at: ${yamlScalar(t.ended_at)},`,
136
137
  ...t.stopped_by === undefined || t.stopped_by === null ? [] : [`${inner}stopped_by: ${yamlScalar(t.stopped_by)},`],
138
+ ...t.failure_kind === undefined || t.failure_kind === null ? [] : [`${inner}failure_kind: ${yamlScalar(t.failure_kind)},`],
137
139
  ...t.banked_before_refusal === undefined ? [] : [`${inner}banked_before_refusal: true,`],
138
140
  ...t.dedupe === undefined ? [] : [`${inner}dedupe: ${yamlScalar(t.dedupe)},`],
139
141
  ...t.duration_ms === undefined ? [] : [`${inner}duration_ms: ${String(Math.round(t.duration_ms))}, ` + `duration_basis: ${yamlScalar(t.duration_basis ?? null)},`],
@@ -725,6 +727,14 @@ function describeGateSignature(sig) {
725
727
 
726
728
  // src/core/facilitator/skipIf.ts
727
729
  import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3 } from "node:fs";
730
+
731
+ // src/core/facilitator/seedSolution.ts
732
+ var WHAT_STAGE_OWN_INPUT_PREFIXES = [
733
+ `${PROJECT_FRAMEWORK_DIR}/memory/`,
734
+ `${PROJECT_FRAMEWORK_DIR}/map/`
735
+ ];
736
+
737
+ // src/core/facilitator/skipIf.ts
728
738
  function phaseDirs(runDir) {
729
739
  try {
730
740
  return readdirSync(runDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^0[1-9]-/.test(entry.name)).map((entry) => entry.name).sort();
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PROJECT_FRAMEWORK_DIR,
3
3
  PROJECT_WORK_DIR
4
- } from "./chunk-qmp5p77c.js";
4
+ } from "./chunk-9bd6b3xf.js";
5
5
 
6
6
  // src/core/lock/workspaceLock.ts
7
7
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync2, rmSync as rmSync2, writeSync, closeSync } from "node:fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toolInput
3
- } from "./chunk-pne7afnf.js";
3
+ } from "./chunk-27v2rwa9.js";
4
4
 
5
5
  // src/hooks/lib/wouldBe.ts
6
6
  import { existsSync, readFileSync } from "node:fs";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  listRunDirs,
3
3
  parseYaml
4
- } from "./chunk-qmp5p77c.js";
4
+ } from "./chunk-9bd6b3xf.js";
5
5
 
6
6
  // src/hooks/lib/runFile.ts
7
7
  import { existsSync, readFileSync } from "node:fs";
@@ -7969,6 +7969,7 @@ function diagnoseSrcToken(line, repos) {
7969
7969
  }
7970
7970
  return { rule: srcRule(id), line: quotable(line), piece: null };
7971
7971
  }
7972
+ var MECHANICALLY_REPAIRABLE = new Set(["marker-spelling", "trailing-position", "cmd-arrow"]);
7972
7973
  function parseSrcToken(line, repos) {
7973
7974
  const trimmed = trimTrailingClosers(line);
7974
7975
  const match = TRAILING_TOKEN_RE.exec(trimmed);
File without changes
@@ -2,7 +2,7 @@ import {
2
2
  GATE_POLICIES,
3
3
  validateGatesPolicy,
4
4
  validateStagePolicy
5
- } from "./chunk-g4d2v4jc.js";
5
+ } from "./chunk-yyhwf3bp.js";
6
6
  import {
7
7
  asDocument,
8
8
  isRecord,
@@ -15,7 +15,7 @@ import {
15
15
  requireString,
16
16
  requireVersion,
17
17
  result
18
- } from "./chunk-qmp5p77c.js";
18
+ } from "./chunk-9bd6b3xf.js";
19
19
 
20
20
  // src/core/events/EventLog.ts
21
21
  import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
@@ -57,6 +57,7 @@ var EVENT_TYPES = [
57
57
  "story.touches_widened",
58
58
  "plan.fix_round",
59
59
  "epic.released",
60
+ "epic.resumed",
60
61
  "worktree.foreign_work_aside",
61
62
  "worktree.foreign_work_restored",
62
63
  "result.unreadable",
@@ -3,7 +3,7 @@ import {
3
3
  withWorkspaceLock,
4
4
  workspaceRootOfFactsPath,
5
5
  writeAtomic
6
- } from "./chunk-857jhjmb.js";
6
+ } from "./chunk-5kv2vtha.js";
7
7
  import {
8
8
  FACT_CONFIDENCES,
9
9
  FACT_DECIDERS,
@@ -15,7 +15,7 @@ import {
15
15
  isLive,
16
16
  isRetired,
17
17
  noteDeprecations
18
- } from "./chunk-yanmz0vz.js";
18
+ } from "./chunk-x1f4dxwk.js";
19
19
  import {
20
20
  SRC_PATTERNS,
21
21
  asDocument,
@@ -28,7 +28,7 @@ import {
28
28
  requireString,
29
29
  requireVersion,
30
30
  result
31
- } from "./chunk-qmp5p77c.js";
31
+ } from "./chunk-9bd6b3xf.js";
32
32
 
33
33
  // src/core/facts/FactsStore.ts
34
34
  import { existsSync, readFileSync } from "node:fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  STAGE_TUNING_DEFAULTS
3
- } from "./chunk-g4d2v4jc.js";
3
+ } from "./chunk-yyhwf3bp.js";
4
4
  import {
5
5
  MAX_PLAN_STORIES,
6
6
  MAX_STORIES_PER_WAVE,
@@ -25,7 +25,7 @@ import {
25
25
  requireVersion,
26
26
  requireVersion1,
27
27
  result
28
- } from "./chunk-qmp5p77c.js";
28
+ } from "./chunk-9bd6b3xf.js";
29
29
 
30
30
  // src/hooks/lib/actor.ts
31
31
  function currentActor() {
@@ -3,7 +3,7 @@ import {
3
3
  EMPTY_SECTION_RULE,
4
4
  noneBullet,
5
5
  srcRule
6
- } from "./chunk-qmp5p77c.js";
6
+ } from "./chunk-9bd6b3xf.js";
7
7
 
8
8
  // src/hooks/lib/messages.ts
9
9
  var GRAMMAR = "[src: <repo:path:line> | https://… | Q<n> | F<n> | $ <cmd> → exit <n> | graph:<node> | absent:<path>]";
@@ -3,7 +3,7 @@ import {
3
3
  parseSrcToken,
4
4
  srcToken,
5
5
  withoutSrcToken
6
- } from "./chunk-qmp5p77c.js";
6
+ } from "./chunk-9bd6b3xf.js";
7
7
 
8
8
  // src/core/text/questions.ts
9
9
  var REQUIRED_METADATA_KEYS = ["id", "status", "area", "asked_by", "asked_at"];
@@ -6,7 +6,7 @@ import {
6
6
  isRecord,
7
7
  loadWorkspace,
8
8
  parseYaml
9
- } from "./chunk-qmp5p77c.js";
9
+ } from "./chunk-9bd6b3xf.js";
10
10
 
11
11
  // src/core/run/workflowPreset.ts
12
12
  import { existsSync, readFileSync } from "node:fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runtime
3
- } from "./chunk-qmp5p77c.js";
3
+ } from "./chunk-9bd6b3xf.js";
4
4
 
5
5
  // src/core/hooks/passthrough.ts
6
6
  async function readStdin() {
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  wouldBeContent
4
- } from "./chunk-7xascvee.js";
4
+ } from "./chunk-72et1xzx.js";
5
5
  import {
6
6
  claimSourcesDeny,
7
7
  claimSourcesEmptySectionDeny,
8
8
  claimSourcesMalformedDeny,
9
9
  claimSourcesUnresolvedDeny
10
- } from "./chunk-mg3aj0sa.js";
10
+ } from "./chunk-q1ge3nex.js";
11
11
  import {
12
12
  allow,
13
13
  deny,
@@ -16,8 +16,8 @@ import {
16
16
  postContext,
17
17
  readPayload,
18
18
  runHook
19
- } from "./chunk-pne7afnf.js";
20
- import"./chunk-z9hv47ps.js";
19
+ } from "./chunk-27v2rwa9.js";
20
+ import"./chunk-zyz0fbz5.js";
21
21
  import {
22
22
  isHandoff,
23
23
  loadWorkspace,
@@ -25,7 +25,7 @@ import {
25
25
  toSrcContext,
26
26
  validateCitations,
27
27
  validateHandoff
28
- } from "./chunk-qmp5p77c.js";
28
+ } from "./chunk-9bd6b3xf.js";
29
29
 
30
30
  // src/hooks/claim-sources.ts
31
31
  await runHook("claim-sources", async () => {