tldr-experts 0.18.3 → 0.20.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 +112 -0
- package/README.md +7 -1
- package/dist/tldrx.js +1045 -388
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/README.md +2 -1
- package/plugin/skills/tldrx-plan/SKILL.md +153 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,117 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.20.0 — 2026-09-13
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`tldrx seed check <file|dir>` — a read-only seed validator, and `/tldrx-plan`, a second
|
|
8
|
+
managed skill that plans seeds a run can finish (#291).** Measured this week across four
|
|
9
|
+
unattended runs on two workspaces: the difference between a run that finishes alone and one
|
|
10
|
+
that needs four rescues is decided BEFORE `run new`, in the seed — and nothing in the
|
|
11
|
+
framework helped a person write one. `install --claude` installed exactly one skill, the
|
|
12
|
+
facilitator; the only authoring guidance was the hand-written grammar list in the seeds
|
|
13
|
+
guide, which said nothing about stories, `touches`, `dod` lines, dependencies, size or
|
|
14
|
+
boundaries; the seeds that ran cleanly were written by a subagent that had to build its own
|
|
15
|
+
validator to check them. `seed check` is that validator, in the CLI: the seed goes through the
|
|
16
|
+
SAME importer chain `run new --seed` runs (`collectSeeds` → `seedClaims` →
|
|
17
|
+
`renderSeedHandoff` → `validateHandoff`, into a temp dir that stands in for the run dir), and
|
|
18
|
+
then through the authoring rules each traceable to a run that died without it — bullets
|
|
19
|
+
under 200 characters, `[src:]` last on its line and resolving to a real line, `dod` lines
|
|
20
|
+
byte-equal to a `commands:` value with no shell separator (`unquotedShellSeparator`, the
|
|
21
|
+
gate's own reader), a `Recommended:` on every open question (#251), `touches:` +
|
|
22
|
+
`depends_on:` + a ```dod fence on every story, and no two stories sharing a touched file in
|
|
23
|
+
one wave (#286: one conflicted file became four). One `file:line rule — text` line per
|
|
24
|
+
finding, exit `1`; an `advisory:` line for more than 4 stories or 2 waves — the framework's
|
|
25
|
+
CURRENT limit, named as a patch for #286/#244/#280 so the number is never read as a design
|
|
26
|
+
preference — never moves the exit code. `--budget <usd>` prints the stage split `run new`
|
|
27
|
+
would write and the per-story developer and reviewer caps, off `planBudget` and `caps.ts`
|
|
28
|
+
as they are (#244/#289: a `--budget 60` feature run gives Build $10.80 per attempt, and
|
|
29
|
+
nobody was told). Nothing here is a second reading of a rule: every check calls the function
|
|
30
|
+
that enforces it at run time. The planning skill, `plugin/skills/tldrx-plan/SKILL.md`, is
|
|
31
|
+
installed by `tldrx install --claude` beside the facilitator under the same
|
|
32
|
+
`<!-- tldrx-managed -->` marker, the same foreign-file refusal (a `SKILL.md` without the
|
|
33
|
+
marker at EITHER path refuses the whole install, nothing written) and the same uninstall;
|
|
34
|
+
`--dry-run` lists it as its own row. It reads `workspace.yml` and the repo tree before
|
|
35
|
+
writing, splits work into runs sized to what the framework carries today, chains stories
|
|
36
|
+
that share a counted or snapshot file, names only declared tools (patch for #290 — the
|
|
37
|
+
planner checks by hand what Plan cannot yet detect; the cure names tool + subcommand, and a
|
|
38
|
+
`git` line is never a `commands:` slot), gives every question a `Recommended:`, derives the
|
|
39
|
+
budget with `seed check --budget`, and ends with the exact
|
|
40
|
+
`run new … --gates none --questions none --ship merge` line. Every rule in the skill and on
|
|
41
|
+
the guide page is marked either **craft** (holds for any version) or **patch for #N**
|
|
42
|
+
(delete when the issue closes) — and the skill CITES the guide for the grammar instead of
|
|
43
|
+
restating it, which `test/plan-skill.test.ts` pins the way `test/maintain-skill.test.ts`
|
|
44
|
+
pins the maintain skill. The seed guide's "Writing a seed by hand" gained the story rules
|
|
45
|
+
with the same markers; the unattended recipe, both documentation sites (EN and ES) and the
|
|
46
|
+
README quick start name the validator and the skill.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **A permission refusal the workspace's `commands:` could have granted now names the operator's
|
|
51
|
+
cure, on the FIRST dead developer instead of the fourth (#285).** Measured by a peer session on a
|
|
52
|
+
live unattended run: one story's acceptance criterion required the EF migration to be *generated by
|
|
53
|
+
`dotnet ef`* in a workspace declaring `dotnet build` / `dotnet test`; four developers died and two
|
|
54
|
+
reviewer rounds ran over ~3 h, and the fourth wrote, verbatim, "dotnet ef is not grantable,
|
|
55
|
+
confirmed absent from .tldrx/workspace.yml:1 commands and refused twice already... No code changes
|
|
56
|
+
made this round" — the agent knew why it could not proceed, said so in plain words, and the system
|
|
57
|
+
bought a fifth attempt anyway. The field workaround was three exact-string slots added to
|
|
58
|
+
`workspace.yml` by hand, which a person had to deduce from four failures. That edit is now the
|
|
59
|
+
recorded reason: #278's classifier gains the case it had no name for, so a non-git refusal the
|
|
60
|
+
declared commands do not grant is no longer `unknown` with nothing to say but names the fix an
|
|
61
|
+
OPERATOR can apply — add a `commands:` slot whose value is exactly `dotnet ef`. The slot names the
|
|
62
|
+
tool and its subcommand, never the story's own arguments (`sha256sum s1.txt` asks for `sha256sum`,
|
|
63
|
+
not for a slot with one file baked into it), and the grant it is checked against is the real one:
|
|
64
|
+
`bashGrantsFor` writes `Bash(<declared>)` and `Bash(<declared> *)`, so `dotnet ef …` is ungranted
|
|
65
|
+
where `dotnet build` is declared even though both start with `dotnet`. That one notion lives beside
|
|
66
|
+
`DEVELOPER_GIT_VERBS` in `build/developerGrants.ts` and every reader calls it (§7). A `git` line is
|
|
67
|
+
never blamed on `commands:` — its allowance is that verb list, so "add a slot" would be a false
|
|
68
|
+
cure — and a caller that does not pass the declared commands classifies exactly as before, so every
|
|
69
|
+
sentence #278 shipped stays byte-identical. The story still blocks after one attempt with the same
|
|
70
|
+
exit code: #261's sentence is still the base, byte for byte, and the cure is the half it was
|
|
71
|
+
missing. **A Plan-time reader of acceptance PROSE was built for this too and measured OUT of the
|
|
72
|
+
change** — the signal that caught the field case went blind on the issue's own workspace, and the
|
|
73
|
+
signal that caught that one fired on `user profile` and `dotnet handles retries` — so it is filed
|
|
74
|
+
with both measurements as #290 instead of shipped half-working. A check that sometimes stays quiet
|
|
75
|
+
where it matters and sometimes shouts where it does not is worse than no check. The Definition of
|
|
76
|
+
Done, which is structured and run for real, has refused a command no slot declares since the
|
|
77
|
+
2026-08-29 audit and is untouched here.
|
|
78
|
+
|
|
79
|
+
## 0.19.0 — 2026-09-13
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- **`tldrx story reopen <id> --as-is --note "…"` settles a story a person finished BY HAND
|
|
84
|
+
from its branch as it stands, with no developer spawned (#279).** Measured on a real
|
|
85
|
+
unattended run at 0.18.2: S2's merge into its epic hit the #268 conflict, a person rebased
|
|
86
|
+
the branch by hand (DoD green, `git merge-tree` clean), and then there was no way to get that
|
|
87
|
+
branch merged. `story reopen` hands the story to a developer; the developer had nothing to
|
|
88
|
+
do; #271's rule — work is measured SINCE THE SPAWN — blocked the story after one attempt,
|
|
89
|
+
correctly, because work that already exists, older than the spawn, is indistinguishable from
|
|
90
|
+
a developer that did nothing. A second reopen buys the same outcome, so the only way out was
|
|
91
|
+
to invent a commit for the developer to make. This is the case that rule could not see, added
|
|
92
|
+
beside it and not carved out of it: `--as-is` spawns nothing at all, so there is no spawn to
|
|
93
|
+
measure work since. Everything after the missing developer is the path every other story
|
|
94
|
+
takes — the epic is merged in if it moved (#268), the DoD runs in the story's worktree, the
|
|
95
|
+
same reviewer judges the same diff, the same merge lands it. The worktree is found BY NAME
|
|
96
|
+
from the branch and reopened when the build had removed it, which is the ordinary case: a
|
|
97
|
+
blocked story's tree is pruned as it settles, and the hand fix is typically made in a scratch
|
|
98
|
+
worktree that is then removed. Two refusals are STRUCTURAL and no flag skips either, because
|
|
99
|
+
a verb that merges a branch nobody's agent wrote is exactly where a `--force` gets added at
|
|
100
|
+
3 a.m. to unstick a run: the branch must carry at least one commit its epic has not already
|
|
101
|
+
got (`commitsBetween`, whose `null` stays "could not count" and refuses rather than reading
|
|
102
|
+
as "did not move", #273), and the DoD must go green under the same `dodProves` every other
|
|
103
|
+
story faces — the story blocks with the reason naming which. And the record does not lie
|
|
104
|
+
about who did the work (§7): `story.reopened` carries `reason: as_is` with the actor and the
|
|
105
|
+
note, `task.done` carries `as_is`/`as_is_by`/`as_is_note`, the review log's developer line
|
|
106
|
+
opens **none** and names the branch it took and the person who signed for it, and no task row
|
|
107
|
+
is written for a turn nothing was spawned for. The signature is cleared the moment a real
|
|
108
|
+
developer attempt starts, so a story requeued after a `changes` verdict over a hand-finished
|
|
109
|
+
branch records a DEVELOPER and not an as-is — found by review before it shipped, and pinned.
|
|
110
|
+
`--for-fix` and `--as-is` together are a usage error rather than a resolution in favour of
|
|
111
|
+
one: they answer different questions, and quietly performing the other is the CLI reporting
|
|
112
|
+
success for work it did not do. `tldrx next --prepare` refuses an `--as-is` story rather than
|
|
113
|
+
dispatching a developer bundle for it.
|
|
114
|
+
|
|
3
115
|
## 0.18.3 — 2026-09-13
|
|
4
116
|
|
|
5
117
|
### Fixed
|
package/README.md
CHANGED
|
@@ -18,9 +18,13 @@ npm i -g tldr-experts # installs `tldrx` (short) and `tldr-experts` (same bi
|
|
|
18
18
|
cd your-project
|
|
19
19
|
tldrx doctor # check the environment — it is the authority, not a list in a README
|
|
20
20
|
tldrx init # detect repos, map the code, write .tldrx/, ask only the gaps
|
|
21
|
-
tldrx install --claude # write the
|
|
21
|
+
tldrx install --claude # write the skills, hooks and status line into ./.claude/
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
Planning a feature for an unattended run? **`/tldrx-plan`** (the second skill `install --claude`
|
|
25
|
+
writes) turns "I want X" into seed files that pass `tldrx seed check`, and ends with the exact
|
|
26
|
+
`run new` line.
|
|
27
|
+
|
|
24
28
|
Later: **`tldrx update`** pulls the newest published version and prints the CHANGELOG between the
|
|
25
29
|
one you had and the one you now have. Any command will tell you, in one line, when there is a newer
|
|
26
30
|
one — off the hot path, cached for a day, silent when it cannot reach the registry, and never in
|
|
@@ -331,6 +335,8 @@ back on the registry is 0.3.0.
|
|
|
331
335
|
|
|
332
336
|
| Version | Date | Status | Contains |
|
|
333
337
|
|---|---|---|---|
|
|
338
|
+
| 0.20.0 | 2026-09-13 | `beta` | `tldrx seed check <file\|dir>` runs a hand-written seed through the same importer chain `run new --seed` runs, plus the authoring rules four unattended runs paid to learn — bullets under 200 characters, `[src:]` citations that resolve, `dod` lines byte-equal to a declared command with no shell separator, `depends_on` wherever two stories touch one file, a `Recommended:` on every open question — and prints the budget split and per-story caps a run would set, creating no run and spending nothing; `tldrx install --claude` now writes a second managed skill, `tldrx-plan`, that reads `workspace.yml` and the repo tree and turns "I want X" into seeds that pass the same check, naming only declared tools (#291). And a permission refusal over a command the workspace's `commands:` could have granted now names the operator's cure on the first dead developer instead of the fourth, measured on a live unattended run where four developers died and two review rounds ran before the missing command turned out to be one `workspace.yml` line away (#285). Minor release: a new CLI verb, `tldrx seed check`. |
|
|
339
|
+
| 0.19.0 | 2026-09-13 | `beta` | `tldrx story reopen <id> --as-is --note "…"` settles a story a person finished by hand from its branch as it stands, spawning no developer — measured on a live unattended run where a hand-rebased branch had a green DoD and a clean merge-tree but no way to land, blocked by #271's since-the-spawn rule from a developer with nothing to do (#279). Everything after the missing developer is the ordinary path: the epic merges in first if it moved, the same DoD and reviewer judge the diff, the same merge lands it. The record never lies about who did the work — `story.reopened` carries `reason: as_is` with the actor and note, `task.done` carries `as_is`/`as_is_by`/`as_is_note`, and the review log names the branch and the signer. Two refusals are structural with no flag to skip either: a branch with no commit ahead of its epic, and a red DoD. The signature clears the moment a real developer attempt starts, so a requeued story after a `changes` verdict records a developer, not an as-is. Minor release: a new flag, `--as-is`, on `story reopen`. |
|
|
334
340
|
| 0.18.3 | 2026-09-13 | `beta` | four fixes to the unattended build path, all measured on live runs: a headless permission refusal is now classified — a chained shell command, a git verb outside the developer's allowance, or neither — so a chained line gets one retry with the cure stated first, an ungranted verb names its granted equivalent, and the developer prompt now lists the git verbs it holds from the one constant the grant is built from, after six refusals in one day left a ledger that recorded the symptom and not the cause; a wave no longer merges a story into its epic from the base it was cut from once a sibling has moved that epic — the story is measured against the epic tip immediately before merge, the epic is merged into the story and its Definition of Done re-run only when the epic actually moved, and a conflict blocks the story naming the files rather than merging half of one; a seed bullet over the claim cap no longer has its citation cut in half, with the clip moving back to the citation's start instead; and a failed commit count is no longer read as zero, so `--discard-pending` can no longer delete a plan just because git could not answer. |
|
|
335
341
|
| 0.18.2 | 2026-09-13 | `beta` | three things measured on the first fully unattended run and on the live runs that followed it, one of them a regression 0.18.1 shipped hours earlier: `--ship merge` armed GitHub's auto-merge over a base that required nothing — the guard counted the checks the PR REPORTED while `--auto` waits on the base's REQUIREMENTS, so a proof run's pull request merged at 06:20:14 while all four of its checks finished between 06:21:38 and 06:24:56, and the record said `queued — GitHub merges when its checks pass`; ship now asks the base what it requires through rulesets and classic protection, names its three absences apart, and every unreadable answer arms nothing; the plan's per-story price had become a hard wall at 0.8x the planner's guess once 0.18.1 made those fields actually read, killing stories mid-flight at $1.28 and $3.25 against real costs an order of magnitude higher, so the ceiling is now `max(price x 3, $4.00)` derived at DISPATCH from the budget as it sits on disk — a run already in flight is covered without migrating anything — and, the half that carries the expensive end, a developer that dies on its cap with work in its tree commits it and lets the Definition of Done decide instead of parking the story, the same authority #271 gave a refused one; and the zero-touch recipe is written down where a person looks for it, seed file to backgrounded loop, on the README quick start and both documentation sites, with the honest boundary that this is the happy path without a person |
|
|
336
342
|
| 0.18.1 | 2026-09-13 | `beta` | five things a run could not survive on its own, every one measured on the unattended proof runs that followed 0.18.0 rather than reasoned about: a priced plan was never priced — the planner wrote `stories[].estimate_usd` and Build read only `per_phase_usd` + `spent_usd`, so every story got the same $5.40 cap while the plan said $28, and the contract now names the shape and the plan check refuses a budget.yml that does not carry it; a headless refusal under a host-tokens ceiling wrote nothing to the ledger, so `--until-done` relaunched over a refusal it could not see, and now writes its `budget.blocked` first; a developer that had committed its work and was then refused a compound verification command was blocked BEFORE the facilitator ran the Definition of Done, so the DoD now decides when there is work and the refusal is recorded either way, with the prompt saying to run each DoD command verbatim and alone because shell separators split a line into subcommands that each need their own grant; a workspace can declare `<slot>_scoped` DoD commands that run per story on the paths it touched with the full suite once per epic head, after the full suite was measured running three times per story attempt; and a cancelled run no longer leaves an epic branch that refuses the ordinary retry — `run cancel` releases it and Build renames aside an epic whose owner run is closed, while an open or unknown owner still refuses verbatim and an uncounted branch is never deleted |
|