tldr-experts 0.6.1 → 0.8.0
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.
- package/CHANGELOG.md +171 -1
- package/README.md +23 -5
- package/dist/hooks/answer-capture.js +7 -7
- package/dist/hooks/budget-gate.js +8 -8
- package/dist/hooks/{chunk-x6n8b5fp.js → chunk-2y3kwfrx.js} +1 -1
- package/dist/hooks/{chunk-97ncnegd.js → chunk-37fwvg3x.js} +1 -1
- package/dist/hooks/{chunk-g4db8rbs.js → chunk-5w5eg00k.js} +1 -1
- package/dist/hooks/{chunk-v4ay50nq.js → chunk-6405vkzk.js} +1 -1
- package/dist/hooks/{chunk-dgct01h0.js → chunk-b9rjx4qc.js} +2 -2
- package/dist/hooks/{chunk-dhbxzjfs.js → chunk-cf4az0j5.js} +1 -1
- package/dist/hooks/{chunk-17gv74sr.js → chunk-ecfqpeyj.js} +3 -3
- package/dist/hooks/{chunk-pstax1g9.js → chunk-md1c7z7q.js} +3 -3
- package/dist/hooks/{chunk-yvp9ayxs.js → chunk-pf9d8ag8.js} +5 -5
- package/dist/hooks/{chunk-ka6bkb64.js → chunk-rk1nm39z.js} +1 -1
- package/dist/hooks/{chunk-vrhczzxs.js → chunk-x3zy7zrn.js} +1 -1
- package/dist/hooks/{chunk-9w64mxdh.js → chunk-y3cxqvnx.js} +154 -12
- package/dist/hooks/claim-sources.js +5 -5
- package/dist/hooks/dod-gate.js +6 -6
- package/dist/hooks/no-reask.js +8 -8
- package/dist/hooks/session-start.js +10 -10
- package/dist/hooks/statusline.js +7 -7
- package/dist/tldrx.js +1511 -975
- package/env.yml +9 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,176 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0 — 2026-09-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`tldrx drive --tldr` — essentials only, for a run whose trail nobody will read.** It adds
|
|
8
|
+
one section to either mandate and stamps the header `· tldr ·`. The session reports in a
|
|
9
|
+
fixed shape — what `tldrx run status` already prints (phases, percentages, spend against the
|
|
10
|
+
ceiling, what is next) plus **at most three bullets of delta** — and stops narrating: no
|
|
11
|
+
recap of a sub-agent's report, no summary of a diff, no restating the status block in prose.
|
|
12
|
+
Free text is reserved for a strict blocker's guided question and for a correction.
|
|
13
|
+
It also turns off the half of the trail nothing consumes: no `tldrx note`, and gate evidence
|
|
14
|
+
at the template's minimum. A fact that must outlive the turn goes to `tldrx facts add`, which
|
|
15
|
+
every later prompt **does** read.
|
|
16
|
+
Measured on a ten-run workspace: of ~4.0 MB written, 2.16 MB is trail, and all **261**
|
|
17
|
+
declared stage `inputs:` contain **zero** occurrences of `handoff.md`, `retro.md` or
|
|
18
|
+
`gate-evidence` — ~445k tokens of output across those runs that no prompt ever reads back.
|
|
19
|
+
Operator notes alone are 133,689 B.
|
|
20
|
+
What `--tldr` deliberately does **not** do is drop the handoff: `claim-sources` is condition 5
|
|
21
|
+
of the seven `auto` conditions and runs whether or not a stage declared it, so a run without
|
|
22
|
+
one cannot close an `auto` or `agent` gate. The mandate briefs sub-agents to trim the *prose*
|
|
23
|
+
and never the `[src: …]` citations, and says why. `--tldr` works on `--attended` too — terse
|
|
24
|
+
output is orthogonal to who signs. Absence is today: without the flag both mandates render
|
|
25
|
+
byte-identically to before, and a test asserts it.
|
|
26
|
+
- `MANDATE_TLDR_MAX_LINES` (`165`) bounds the `--tldr` variants; the standard mandate keeps the
|
|
27
|
+
tighter `MANDATE_MAX_LINES`. Two constants rather than one looser one, so the terse mode does
|
|
28
|
+
not spend every other run's skimmability budget.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`tldrx drive --unattended` told the driver four times to stop and never once to
|
|
33
|
+
continue, and the runs it drove did exactly that.** Measured over the eight driven runs
|
|
34
|
+
of a real workspace: 26 `budget.raised` and 26 `question.answered` events, and an owner
|
|
35
|
+
who had to type *"sigue con todas desatendido, no esperes por mi"* **inside** an
|
|
36
|
+
unattended run to restart a session the mandate had correctly halted. `grep -ic
|
|
37
|
+
"continue|keep going|proceed|do not stop|resume"` over `mandate.ts` returned `0`. The
|
|
38
|
+
unattended mandate now opens the discipline with a **`## Do not stop`** section that
|
|
39
|
+
defines the only thing that may halt a run — a STRICT blocker, one where no remaining
|
|
40
|
+
turn can proceed until the owner answers — and makes the driver **name the work the
|
|
41
|
+
blocker does not block** before it may call one strict. The three remaining halts are
|
|
42
|
+
narrowed to match: the preflight refusal is now *asked* rather than gone quiet on, the
|
|
43
|
+
budget bullet keeps "do not raise one, do not route around one" but no longer halts the
|
|
44
|
+
run (it asks, then keeps spending what the ceiling still funds), and the interrupt list
|
|
45
|
+
is strict blockers only, "never as a bare halt".
|
|
46
|
+
- **A parked question is now a GUIDED question.** "State the question in one sentence" got
|
|
47
|
+
open prompts nobody could answer from a phone, so a product question stopped a run for
|
|
48
|
+
hours. Parking now asks for 2–5 lettered options with their consequences, what the run's
|
|
49
|
+
own docs and facts already decide, the option the driver would take, and what it will do
|
|
50
|
+
if no answer arrives. Both modes carry it.
|
|
51
|
+
- **The old halt licence is gone.** "If the only safe version is *do nothing yet*, do
|
|
52
|
+
nothing yet and park it" was true about the write and read as true about the run. The
|
|
53
|
+
text now says which it means: not shipping an unguarded write is not the same as not
|
|
54
|
+
shipping anything.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **The ask channel is the console, and the framework stays agnostic about anything else.**
|
|
59
|
+
The mandate says *"Ask on the console, unless my launch message named another channel"* —
|
|
60
|
+
no chat vendor is named in shipped text, and a test asserts none ever is, so one
|
|
61
|
+
operator's bridge never becomes a dependency of everybody's run. A default the driver
|
|
62
|
+
falls back on when no answer reaches it is recorded as the **driver's** decision and may
|
|
63
|
+
never be cited back as the owner's — the distinction one run drew by hand and the text
|
|
64
|
+
now carries.
|
|
65
|
+
- `MANDATE_MAX_LINES` moved once, `120` → `140`, with the reason recorded in the source.
|
|
66
|
+
The bound is still real and still asserted; the unattended mandate renders 137 lines and
|
|
67
|
+
the attended one 123. File formats remain `version: 1`.
|
|
68
|
+
|
|
69
|
+
## 0.7.0 — 2026-09-03
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- **Codex is now a second honest automated runner.** Set `TLDRX_AGENT_PROVIDER=codex` to
|
|
74
|
+
run plain `codex exec --json` through the existing facilitator seam; `TLDRX_CODEX_BIN`
|
|
75
|
+
selects a wrapper or pinned executable. The adapter is pinned to a real codex-cli 0.152.0
|
|
76
|
+
JSONL transcript and a real executable stub, preserves thread identity and token usage,
|
|
77
|
+
feeds the existing structured envelopes, runs developers in `workspace-write`, and makes
|
|
78
|
+
Build reviewers mechanically `read-only`. Because Codex exposes neither provider-metered
|
|
79
|
+
USD nor a provider-side USD cap, every Codex turn is recorded `cost_usd: null,
|
|
80
|
+
metered: false`; no Codex prices were added and dollar totals remain lower bounds. Agent
|
|
81
|
+
gate provenance uses the measured Codex thread id as `executed_by.id`. Claude remains the
|
|
82
|
+
byte-identical default. File formats remain `version: 1`; `DASHBOARD_MODEL_VERSION` remains
|
|
83
|
+
`3`.
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- **A citation to a file that exists only on the run's unmerged epic branch passed unflagged, or broke,
|
|
88
|
+
depending on whether a temp directory still existed (#140).** Live evidence, run
|
|
89
|
+
`260830-money-and-payments` (aparece-v2, closed 2026-09-03): `retro.md` was committed to `main` carrying
|
|
90
|
+
96 `[src: src/Modules/Payments/…:28]` citations to files that exist on `epic/money-and-payments` and on
|
|
91
|
+
no merged ref. The driver's words: *"cuatro de mis citas apuntaban a archivos que solo existen en el epic.
|
|
92
|
+
Nadie me las señaló."* #16 had made those resolve against the epic WORKTREE
|
|
93
|
+
(`.tldrx/worktrees/<repo>/_epic-<run>-<epic>`), and that is a temp directory, so the same citation had two
|
|
94
|
+
silent answers — measured on `24e9358` with the new fixture:
|
|
95
|
+
- worktree **present** (the state the retro was written in): the whole check detail read
|
|
96
|
+
`1 handoff(s) sourced`, with no mention of the branch the path is only on;
|
|
97
|
+
- worktree **gone** (the state `main` is always in, and the state after cleanup):
|
|
98
|
+
`no such file: src/Modules/Payments/CreateChargeHandler.cs — tried repo \`api\` (api)` — the stage's own
|
|
99
|
+
evidence refused for being true.
|
|
100
|
+
- **A `file` src now gets one more chance after every base on disk: the branches the run RECORDED.**
|
|
101
|
+
`run.yml`'s `build.epic_branch` — the same record `tldrx ship` opens its PR from — read as a git blob with
|
|
102
|
+
`git cat-file blob <ref>:<path>` in each declared repo. No worktree, and no retention policy needed for
|
|
103
|
+
this purpose. `cat-file blob` and not `show`: `git show <ref>:<dir>` prints a tree listing and exits 0, so
|
|
104
|
+
`show` would resolve a citation to a directory as though it were a file (measured 2026-09-03: `cat-file blob`
|
|
105
|
+
exits 0 for a blob, 128 for a tree, 128 for a path the ref does not have).
|
|
106
|
+
- **It resolves, and it is NAMED.** A citation whose only home is unmerged is `ok` — refusing it would refuse
|
|
107
|
+
a stage for reporting its own evidence — and the resolution carries the ref, so `claim-sources` prints
|
|
108
|
+
`on unmerged refs: 96 (epic/money-and-payments — unmerged)` in the one detail string the gate, `tldrx next`
|
|
109
|
+
and the run record all read. A reader of `main` is told which branch to look on. A hit on the epic
|
|
110
|
+
worktree is named the same way, so the "passes in silence" half is closed too.
|
|
111
|
+
- **Still refused:** a path on no ref at all (the failure now admits it tried the recorded branches), and a
|
|
112
|
+
cited line past the end of the epic's blob — which names the ref and the length the file has there. Only
|
|
113
|
+
branches `build.epic_branch` records are tried; a branch that merely exists in the repo is not a base.
|
|
114
|
+
An `absent:` src deliberately does NOT reach for the refs: an absence is a claim about where somebody
|
|
115
|
+
looked, and a branch nobody checked out is not somewhere anybody looked.
|
|
116
|
+
- **The blob read is opt-in, and the `claim-sources` hook does not opt in.** It is the one subprocess the
|
|
117
|
+
§2.8 reader spawns, and that hook runs on every PreToolUse write inside the 50 ms budget of spec §0. The
|
|
118
|
+
guard is reachability rather than a cap: `toSrcContext(workspace, runDir)` — the hook's spelling — leaves
|
|
119
|
+
`epicRefs` empty, so no handoff can reach a `spawnSync` from a write. Measured 2026-09-03 on 96 epic-only
|
|
120
|
+
citations: **0.36 ms** on the hook path, **1166 ms** cold on the gate path with all 96 reads paid, **0.36 ms**
|
|
121
|
+
warm (memoised per repo/ref/path, capped at 256 reads per process). `tldrx approve`, the stage/gate
|
|
122
|
+
`claim-sources` check, `tldrx next`'s auto gate, `tldrx watch` and `watch arm` opt in — every one of them a
|
|
123
|
+
boundary that already spawns git.
|
|
124
|
+
- **It behaves like `noted`, not like `unverified`:** it passes the stage and it does not block an auto gate
|
|
125
|
+
(spec §5, condition 5). It is a check that ran and came back true, of a branch nothing has merged.
|
|
126
|
+
- **The auto gate's NOTE carries the ref too.** `claimSourcesCondition` carried `outcome.detail` into its
|
|
127
|
+
note only when the unchecked-absence count was non-zero — #110's rule reading one of the two things that
|
|
128
|
+
detail now holds. So a stage whose handoff cited nothing but the epic and held no absence at all
|
|
129
|
+
auto-signed with a note that read, in full, `claim-sources=passed`. Both counts are consulted now, and
|
|
130
|
+
the branch reaches the sentence a person actually reads when a stage signs itself.
|
|
131
|
+
- **A watcher card could cite a path only the unmerged epic has, and say nothing (#143).** The one artefact
|
|
132
|
+
#140's annotation did not reach. `watcherFile.ts` recorded an issue only when a resolution was NOT `ok`,
|
|
133
|
+
and every issue it records makes the card fail — so "true, and true only on `epic/…`" could not be said
|
|
134
|
+
without failing a card that is not wrong. Since `tldrx watch`, `watch arm` and the Watch executor opt into
|
|
135
|
+
the recorded epic refs (`toSrcContext(…, { epicRefs: true })`), such a citation resolved in silence, and a
|
|
136
|
+
card committed to the trunk could point a reader at paths no merged ref has. Measured RED, on a card whose
|
|
137
|
+
four checked sections all cite `epic/money-and-payments`: `watch check` said `ok — verified; every source
|
|
138
|
+
resolves` and `watch list`'s footer said `1 card(s): 1 verified, 0 draft`, neither naming the branch.
|
|
139
|
+
- The card now carries a **separate, non-fatal `epicOnly` list** — the shape `handoff.ts` already uses for
|
|
140
|
+
the same reason, rather than a third `WatcherIssueKind`, because `ok` reads `issues` and nothing else, so
|
|
141
|
+
the annotation cannot fail a card however long it gets.
|
|
142
|
+
- It is printed in the words `claim-sources` already uses at a gate — `on unmerged refs: 4
|
|
143
|
+
(epic/money-and-payments — unmerged)` — beside the card's status in `watch check`, as a footer under the
|
|
144
|
+
`watch list` table, as `unmerged_refs` (plus an `unmerged` count) in `watch list --json`, and on the Watch
|
|
145
|
+
executor's own per-card line, which is where the driver reads a card's status.
|
|
146
|
+
- Three guards say it is not a rubber stamp, and all three were green before the change: a path on a
|
|
147
|
+
**merged** ref gets no annotation, a citation that resolves **nowhere** is still a failing `source` issue,
|
|
148
|
+
and with epic refs **off** — the context the PreToolUse hook builds — nothing resolves and nothing is
|
|
149
|
+
annotated.
|
|
150
|
+
- **A run could close with a question nobody ever answered, and nothing said so (#141).** Filed from the
|
|
151
|
+
driver of `260830-money-and-payments` (aparece-v2) as *"D7.6 nunca recibió respuesta ni disparó su
|
|
152
|
+
default"*, labelled INFERRED. **Measured first, and the reported mechanism does not exist:**
|
|
153
|
+
- `D7.6` was never a question. The §2.7 heading grammar is `^## (Q\d{1,6}) · ` — `D7.6` is a
|
|
154
|
+
Definition-of-Done criterion in that run's own seeded documents
|
|
155
|
+
(`docs/domain-design/docs/12-DEFINITION-OF-DONE.md:118-125`). The run's `questions.md` files hold exactly
|
|
156
|
+
three blocks — `Q1`, `Q2`, `Q3` — and every one is `status: answered`.
|
|
157
|
+
- A question **cannot declare** a default. §2.7's metadata keys are `id status area asked_by asked_at` plus
|
|
158
|
+
the optional `affects:`; there is no `default:` and no `timeout:`.
|
|
159
|
+
- **Nothing fires one.** The only thing in the codebase called a default is `tldrx interview
|
|
160
|
+
--yes-to-defaults`, which an operator invokes by hand, takes option A, and is labelled `[assumption]` in
|
|
161
|
+
its own implementation. No timer, no gate and no close applies anything to an open question.
|
|
162
|
+
|
|
163
|
+
The fail-open the report was reaching for is real, and narrower guards had hidden it: the auto gate's
|
|
164
|
+
`questions` condition reads only the CURRENT stage's declared file, a human `approve` does not look at
|
|
165
|
+
questions at all, and `closeRun` read `run.yml` and git and nothing else. A question raised in `01-what`
|
|
166
|
+
could age through every later stage, past a signed gate and out of the run in silence. Measured RED, on a
|
|
167
|
+
run cancelled with `Q1` open: `cancelled 260828-demo — 1 stage(s) closed: 01-what/alpha` and not one word
|
|
168
|
+
about the question. **All three close paths** — `tldrx next` closing the last stage, `tldrx approve` signing
|
|
169
|
+
the last gate, `tldrx run cancel` — now name every open block by id, title and file, plus any heading the
|
|
170
|
+
§2.7 parser cannot read (worse than open: the block was never visible to anything). The sentence ends by
|
|
171
|
+
saying that nothing was going to answer them, because that belief is what produced the report. It is a
|
|
172
|
+
report and nothing else: no exit code changes, no close is refused, not one byte is written.
|
|
173
|
+
|
|
3
174
|
## 0.6.1 — 2026-09-03
|
|
4
175
|
|
|
5
176
|
### Fixed
|
|
@@ -301,7 +472,6 @@
|
|
|
301
472
|
correctly and is spliced into no prompt is the `templates/story.md` failure again (#48).
|
|
302
473
|
6 red before, green after. `docs/spec.md` §2.13 and the `delivery` expert each carry one
|
|
303
474
|
line pointing at the checklist.
|
|
304
|
-
|
|
305
475
|
- **The landing page now sells the unattended flow it never mentioned (#128).** Measured at
|
|
306
476
|
`95a39db`: `grep -c 'tldrx drive' docs-site/index.md` returned `0`, and so did its Spanish
|
|
307
477
|
twin — a bare `grep drive` exited `1` on both. `tldrx drive` is the star command for handing
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/tldr-experts) [](https://github.com/ederwii/tldr-experts/actions/workflows/ci.yml) 
|
|
4
4
|
|
|
5
|
-
**An evidence-first, file-based AI development framework: five stages, a gate on every one, and every claim cited or refused.** Open source. The workflow and the persisted state format are provider-independent; the automated runner currently supports Claude Code. **Beta:** every command is implemented and verified by running it, the `version: 1` file formats only grow from here, and `tldrx --help` is the authoritative command surface.
|
|
5
|
+
**An evidence-first, file-based AI development framework: five stages, a gate on every one, and every claim cited or refused.** Open source. The workflow and the persisted state format are provider-independent; the automated runner currently supports Claude Code and Codex. **Beta:** every command is implemented and verified by running it, the `version: 1` file formats only grow from here, and `tldrx --help` is the authoritative command surface.
|
|
6
6
|
|
|
7
7
|
One loop — *Investigate → Handoff → Interview → Gate* — five phases, **what · how · plan · build ·
|
|
8
8
|
watch**, one stage per command, each stopping at a gate you own; the files ARE the state, the
|
|
@@ -59,7 +59,7 @@ and names the `--prepare` command instead.
|
|
|
59
59
|
|
|
60
60
|
| | who executes each turn | what a turn costs | where it stops |
|
|
61
61
|
|---|---|---|---|
|
|
62
|
-
| `tldrx run auto` | the framework —
|
|
62
|
+
| `tldrx run auto` | the framework — Claude Code by default, or `codex exec` when selected | Claude reports metered USD; Codex reports tokens and is unmetered in dollars | the first human gate or open question (`4`), stage failure (`5`), ceiling (`2`) |
|
|
63
63
|
| `tldrx run attend host`, driven from a session | your session's own sub-agents | host-billed; the framework records `cost_usd: null, metered: false` | every turn — `--prepare` writes the bundle, `--commit` settles it |
|
|
64
64
|
| the same, under a **mandate** | your session's own sub-agents | host-billed | a new product decision, a ceiling raise, a boundary exit — nothing else |
|
|
65
65
|
|
|
@@ -75,14 +75,30 @@ Two commands and a prompt — and the prompt now ships with the package:
|
|
|
75
75
|
```bash
|
|
76
76
|
tldrx drive --unattended # print the mandate; paste it into the session that drives the run
|
|
77
77
|
tldrx drive --attended # the same disciplines, but every gate stays yours to sign
|
|
78
|
+
tldrx drive --unattended --tldr # essentials only, for a run whose trail you will not read
|
|
78
79
|
```
|
|
79
80
|
|
|
80
81
|
`tldrx drive` needs no workspace, opens no run and writes nothing: it prints the discipline the
|
|
81
82
|
first real runs were driven by — the three-role protocol (developer → a **fresh** adversarial
|
|
82
83
|
reviewer, never the author → the host verifying both in the code, not in their reports), evidence
|
|
83
|
-
labelled `measured` / `inferred` / `assumed`, product questions parked
|
|
84
|
-
reviewer calibrated to the story's stakes, and the cost declared once. The two
|
|
85
|
-
exactly two places: who drives the turns, and who may close a gate.
|
|
84
|
+
labelled `measured` / `inferred` / `assumed`, product questions parked as **guided** ones rather
|
|
85
|
+
than decided, the reviewer calibrated to the story's stakes, and the cost declared once. The two
|
|
86
|
+
modes differ in exactly two places: who drives the turns, and who may close a gate.
|
|
87
|
+
|
|
88
|
+
**The unattended mandate leads with `## Do not stop`.** A run only ends early because the session
|
|
89
|
+
decides to, so the text defines the one thing that may end it — a strict blocker, where no
|
|
90
|
+
remaining turn can proceed until you answer — and makes the driver name the work a blocker does
|
|
91
|
+
*not* block before it may halt for it. Everything short of that is parked as a guided question
|
|
92
|
+
(lettered options, the option the driver would take, asked on the console unless your launch
|
|
93
|
+
message names another channel) and the run carries on down every path the question does not block.
|
|
94
|
+
|
|
95
|
+
**`--tldr` is for the runs you will not audit.** The session reports what `tldrx run status`
|
|
96
|
+
already prints — phases, percentages, spend against the ceiling, what is next — plus at most three
|
|
97
|
+
bullets of delta, and stops narrating. It also drops the half of the trail nothing consumes:
|
|
98
|
+
measured across ten real runs, of ~4.0 MB written 2.16 MB is trail, and all 261 declared stage
|
|
99
|
+
`inputs:` contain **zero** references to `handoff.md`, `retro.md` or `gate-evidence`. It is a
|
|
100
|
+
reporting contract, not a quality setting — the evidence discipline and the gate checks are
|
|
101
|
+
untouched, and handoffs keep their citations because `claim-sources` gates on them.
|
|
86
102
|
|
|
87
103
|
The rest of this section is what that mandate says, in the shape you would type it by hand.
|
|
88
104
|
|
|
@@ -298,6 +314,8 @@ back on the registry is 0.3.0.
|
|
|
298
314
|
|
|
299
315
|
| Version | Date | Status | Contains |
|
|
300
316
|
|---|---|---|---|
|
|
317
|
+
| 0.8.0 | 2026-09-04 | `beta` | the unattended mandate learns to keep going: a `## Do not stop` section that defines the one thing allowed to end a run early (a strict blocker, named against the work it does not block), product questions parked as **guided** ones with lettered options and a pre-declared fallback, and a budget stop that asks instead of halting — written against 26 `budget.raised` and 26 `question.answered` events on a real ten-run workspace where the owner had to re-authorise "unattended" mid-run. Plus `tldrx drive --tldr`: a reporting contract for runs nobody will audit — the `run status` block plus three bullets of delta, no operator notes, minimal gate evidence, handoffs trimmed of prose but never of the citations `claim-sources` gates on. The ask channel stays the console and the framework names no chat vendor |
|
|
318
|
+
| 0.7.0 | 2026-09-03 | `beta` | Codex as a second honest automated runner: recorded JSONL contract, structured envelopes, role-based sandboxes, token/session provenance, and explicitly unmetered USD accounting; Claude remains the default and the pilot harness. Also absorbs the citation-honesty work previously staged as 0.6.2: a `file` src resolves against the branches the run RECORDED and NAMES the unmerged ref instead of passing in silence or breaking with the temp dir (#140), watcher cards name it the same way (#143), and every run close reports the questions nobody answered (#141) |
|
|
301
319
|
| 0.6.1 | 2026-09-03 | `beta` | dogfooding fixes from the first fully-unattended runs: blocked stories never lose uncommitted work (rescue commits + `story.work_rescued`), a fix is only Resolved with a reachable sha, re-entered stages reconstruct their handoff from the ledger instead of degrading it, the Cost header reports the phase and names its lower bound (shared `spendBasis`), feature presets resolve their per-repo maps, Plan sees the command allowlist its gate enforces, the landing sells the unattended flow |
|
|
302
320
|
| 0.6.0 | 2026-09-02 | `beta` | the dashboard suite — a "Now" hero strip, `--serve` live refresh, stage durations and gate notes on page and CLI, and a public demo generated from fixtures; honest dual-economy spend (metered + host, lower-bound named); gate provenance — `executed_by` + `authority` so a delegated signature never reads as a personal one, machine-signed reporting fixed; ONE `absent:` semantic shared by claim-sources and the auto gate; superseded stamps when an owner answer flips an earlier phase doc; run close commits its state and `ship` refuses a state-carrying epic; merge-wave gates `docs:build`, survives interruption and self-rewrite; a public-surface drift guard; env.yml validation (unique ids, tool cap) |
|
|
303
321
|
| 0.5.0 | 2026-09-02 | `beta` | `tldrx drive` and its own preflight, `watch check` / `watch arm`, `questions cards`, `plan schema`, `retro --all` (with its findings fed back into every reviewer prompt) and `story reopen --for-fix`; `tldrx update` plus a cached newer-version notice; the dashboard reads `budget.yml` and `events.jsonl` — operator notes, reopens and retries, the per-phase budget panel, and a host-attended run metered in tokens against `ceiling_host_tokens`; a rejected review envelope no longer burns a story attempt; `ship` opens one PR per repo; merge-wave lock + ref guard; five golden-transcript evals, one per stage; `CONTRIBUTING.md` and a model-provider contract |
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
FactsStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ecfqpeyj.js";
|
|
5
5
|
import {
|
|
6
6
|
parseHookInput,
|
|
7
7
|
readStdin
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-x3zy7zrn.js";
|
|
9
9
|
import {
|
|
10
10
|
EventLog,
|
|
11
11
|
PHASE_ID_RE
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import"./chunk-
|
|
14
|
-
import"./chunk-
|
|
12
|
+
} from "./chunk-b9rjx4qc.js";
|
|
13
|
+
import"./chunk-5w5eg00k.js";
|
|
14
|
+
import"./chunk-6405vkzk.js";
|
|
15
15
|
import {
|
|
16
16
|
MAX_FACT_CHARS,
|
|
17
17
|
detectAnswered,
|
|
@@ -19,12 +19,12 @@ import {
|
|
|
19
19
|
recordAnswer,
|
|
20
20
|
replaceBlock,
|
|
21
21
|
serializeQuestions
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-37fwvg3x.js";
|
|
23
23
|
import"./chunk-39zh2e44.js";
|
|
24
24
|
import {
|
|
25
25
|
PROJECT_WORK_DIR,
|
|
26
26
|
factsPath
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-y3cxqvnx.js";
|
|
28
28
|
|
|
29
29
|
// src/hooks/answer-capture.ts
|
|
30
30
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
budgetGateDeny
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-cf4az0j5.js";
|
|
5
5
|
import {
|
|
6
6
|
allow,
|
|
7
7
|
deny,
|
|
8
8
|
readPayload,
|
|
9
9
|
runHook,
|
|
10
10
|
toolInput
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import"./chunk-
|
|
11
|
+
} from "./chunk-2y3kwfrx.js";
|
|
12
|
+
import"./chunk-x3zy7zrn.js";
|
|
13
13
|
import {
|
|
14
14
|
asRunBudget,
|
|
15
15
|
currentActor,
|
|
@@ -29,15 +29,15 @@ import {
|
|
|
29
29
|
validateRunBudget,
|
|
30
30
|
wouldExceed,
|
|
31
31
|
wouldExceedHostTokens
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-md1c7z7q.js";
|
|
33
33
|
import {
|
|
34
34
|
EventLog
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-b9rjx4qc.js";
|
|
36
36
|
import"./chunk-rrkdfk7s.js";
|
|
37
|
-
import"./chunk-
|
|
37
|
+
import"./chunk-5w5eg00k.js";
|
|
38
38
|
import {
|
|
39
39
|
noteDeprecations
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-37fwvg3x.js";
|
|
41
41
|
import"./chunk-39zh2e44.js";
|
|
42
42
|
import {
|
|
43
43
|
PROJECT_WORK_DIR,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
locateWork,
|
|
46
46
|
parseYaml,
|
|
47
47
|
stageYamlPath
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-y3cxqvnx.js";
|
|
49
49
|
|
|
50
50
|
// src/hooks/budget-gate.ts
|
|
51
51
|
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROJECT_FRAMEWORK_DIR,
|
|
3
3
|
PROJECT_WORK_DIR
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-y3cxqvnx.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
|
parseFrontMatter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5w5eg00k.js";
|
|
4
4
|
import {
|
|
5
5
|
asDocument,
|
|
6
6
|
isRecord,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "./chunk-39zh2e44.js";
|
|
15
15
|
import {
|
|
16
16
|
parseHandoff
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-y3cxqvnx.js";
|
|
18
18
|
|
|
19
19
|
// src/core/events/EventLog.ts
|
|
20
20
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
EMPTY_SECTION_RULE,
|
|
4
4
|
noneBullet,
|
|
5
5
|
srcRule
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-y3cxqvnx.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
|
withWorkspaceLock,
|
|
4
4
|
workspaceRootOfFactsPath,
|
|
5
5
|
writeAtomic
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6405vkzk.js";
|
|
7
7
|
import {
|
|
8
8
|
FACT_CONFIDENCES,
|
|
9
9
|
FACT_KINDS,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
isLive,
|
|
15
15
|
isRetired,
|
|
16
16
|
noteDeprecations
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-37fwvg3x.js";
|
|
18
18
|
import {
|
|
19
19
|
asDocument,
|
|
20
20
|
isRecord,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
SRC_PATTERNS,
|
|
30
30
|
parseYaml,
|
|
31
31
|
readableSource
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-y3cxqvnx.js";
|
|
33
33
|
|
|
34
34
|
// src/core/facts/FactsStore.ts
|
|
35
35
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EVIDENCE_FILE,
|
|
3
3
|
gateEvidenceRelPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-b9rjx4qc.js";
|
|
5
5
|
import {
|
|
6
6
|
MAX_PLAN_STORIES,
|
|
7
7
|
MAX_STORIES_PER_WAVE,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
requirePattern,
|
|
12
12
|
requireStringList,
|
|
13
13
|
requireVersion1
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-5w5eg00k.js";
|
|
15
15
|
import {
|
|
16
16
|
asDocument,
|
|
17
17
|
isRecord,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
listRunDirs,
|
|
32
32
|
parseYaml,
|
|
33
33
|
readableSource
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-y3cxqvnx.js";
|
|
35
35
|
|
|
36
36
|
// src/hooks/lib/runFile.ts
|
|
37
37
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
nowRfc3339,
|
|
8
8
|
openRunViews,
|
|
9
9
|
validateRunBudget
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-md1c7z7q.js";
|
|
11
11
|
import {
|
|
12
12
|
EventLog,
|
|
13
13
|
asRunFile,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
isTerminal,
|
|
20
20
|
stageAt,
|
|
21
21
|
validateRunFile
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-b9rjx4qc.js";
|
|
23
23
|
import {
|
|
24
24
|
backupPathFor,
|
|
25
25
|
isAlive,
|
|
@@ -28,17 +28,17 @@ import {
|
|
|
28
28
|
workspaceRootOfRunDir,
|
|
29
29
|
writeAtomic,
|
|
30
30
|
yamlScalar
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6405vkzk.js";
|
|
32
32
|
import {
|
|
33
33
|
noteDeprecations,
|
|
34
34
|
openBlocks,
|
|
35
35
|
parseQuestions
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-37fwvg3x.js";
|
|
37
37
|
import {
|
|
38
38
|
listRunDirs,
|
|
39
39
|
parseYaml,
|
|
40
40
|
parseYamlRepairing
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-y3cxqvnx.js";
|
|
42
42
|
|
|
43
43
|
// src/core/statusline/runSnapshot.ts
|
|
44
44
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|