tldr-experts 0.3.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 +913 -0
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/hooks/answer-capture.js +174 -0
- package/dist/hooks/budget-gate.js +173 -0
- package/dist/hooks/chunk-0bt6yb2q.js +88 -0
- package/dist/hooks/chunk-1zwcxd3f.js +66 -0
- package/dist/hooks/chunk-9gb21660.js +66 -0
- package/dist/hooks/chunk-a8p2rc94.js +20 -0
- package/dist/hooks/chunk-ae6bkfs5.js +0 -0
- package/dist/hooks/chunk-azctppjh.js +198 -0
- package/dist/hooks/chunk-g395gk7e.js +503 -0
- package/dist/hooks/chunk-j234zf0t.js +339 -0
- package/dist/hooks/chunk-kw4tffzf.js +139 -0
- package/dist/hooks/chunk-p274ckxv.js +7435 -0
- package/dist/hooks/chunk-sdjnnmzz.js +497 -0
- package/dist/hooks/chunk-t56k6146.js +14 -0
- package/dist/hooks/chunk-t8tdv11p.js +35 -0
- package/dist/hooks/chunk-x98qs959.js +302 -0
- package/dist/hooks/chunk-y0jdr3et.js +627 -0
- package/dist/hooks/claim-sources.js +72 -0
- package/dist/hooks/dod-gate.js +198 -0
- package/dist/hooks/no-reask.js +67 -0
- package/dist/hooks/session-start.js +1348 -0
- package/dist/hooks/statusline.js +116 -0
- package/dist/tldrx.js +34219 -0
- package/env.yml +79 -0
- package/package.json +60 -0
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/README.md +113 -0
- package/plugin/agents/README.md +22 -0
- package/plugin/hooks/hooks.json +107 -0
- package/plugin/skills/tldrx/SKILL.md +170 -0
- package/stages/build/stage.md +70 -0
- package/stages/build/stage.yml +54 -0
- package/stages/how/stage.md +89 -0
- package/stages/how/stage.yml +53 -0
- package/stages/plan/stage.md +89 -0
- package/stages/plan/stage.yml +48 -0
- package/stages/watch/stage.md +85 -0
- package/stages/watch/stage.yml +61 -0
- package/stages/what/stage.md +89 -0
- package/stages/what/stage.yml +61 -0
- package/templates/budget.yml +17 -0
- package/templates/competencies.yml +14 -0
- package/templates/env.yml +19 -0
- package/templates/epic.md +38 -0
- package/templates/expert.md +51 -0
- package/templates/experts/architect.md +77 -0
- package/templates/experts/delivery.md +76 -0
- package/templates/experts/developer.md +78 -0
- package/templates/experts/operations.md +74 -0
- package/templates/experts/product.md +78 -0
- package/templates/facts.yml +18 -0
- package/templates/handoff.md +63 -0
- package/templates/process.yml +33 -0
- package/templates/questions.md +63 -0
- package/templates/run.yml +24 -0
- package/templates/story.md +55 -0
- package/templates/watcher.md +68 -0
- package/templates/waves.yml +17 -0
- package/templates/workspace.yml +30 -0
- package/workflows/bugfix.yml +26 -0
- package/workflows/docs.yml +23 -0
- package/workflows/feature.yml +22 -0
- package/workflows/hotfix.yml +24 -0
- package/workflows/integration.yml +24 -0
- package/workflows/migration.yml +24 -0
- package/workflows/performance.yml +23 -0
- package/workflows/prototype.yml +24 -0
- package/workflows/refactor.yml +24 -0
- package/workflows/retro.yml +20 -0
- package/workflows/security-patch.yml +23 -0
- package/workflows/spike.yml +23 -0
- package/workflows/upgrade.yml +23 -0
package/env.yml
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# schema: draft
|
|
2
|
+
#
|
|
3
|
+
# The local dev environment manifest. `tldrx doctor` reads this file, runs each
|
|
4
|
+
# `check` command, and prints what it found.
|
|
5
|
+
#
|
|
6
|
+
# The framework NEVER installs anything. `install` holds a copy-paste hint per OS
|
|
7
|
+
# and nothing more. Keys: macos | linux | windows | all.
|
|
8
|
+
#
|
|
9
|
+
# `check` must exit 0 when the tool is usable and print something version-shaped
|
|
10
|
+
# (the first dotted numeric run in stdout+stderr is taken as the version).
|
|
11
|
+
|
|
12
|
+
version: 1
|
|
13
|
+
|
|
14
|
+
tools:
|
|
15
|
+
- id: bun
|
|
16
|
+
required: true
|
|
17
|
+
min_version: "1.3.0"
|
|
18
|
+
check: "bun --version"
|
|
19
|
+
purpose: "Runs the tldrx CLI, the hooks and the test suite. Bun 1.3+ is required for native Bun.YAML."
|
|
20
|
+
install:
|
|
21
|
+
macos: "curl -fsSL https://bun.sh/install | bash"
|
|
22
|
+
linux: "curl -fsSL https://bun.sh/install | bash"
|
|
23
|
+
windows: "powershell -c \"irm bun.sh/install.ps1 | iex\" (or: npm install -g bun)"
|
|
24
|
+
|
|
25
|
+
- id: node
|
|
26
|
+
required: true
|
|
27
|
+
min_version: "20.0.0"
|
|
28
|
+
check: "node --version"
|
|
29
|
+
purpose: "Runs the published build (package.json bin + engines). Also required by Claude Code itself."
|
|
30
|
+
install:
|
|
31
|
+
macos: "brew install node (or: https://nodejs.org)"
|
|
32
|
+
linux: "https://nodejs.org/en/download/package-manager"
|
|
33
|
+
windows: "winget install OpenJS.NodeJS (or: https://nodejs.org)"
|
|
34
|
+
|
|
35
|
+
- id: git
|
|
36
|
+
required: true
|
|
37
|
+
min_version: "2.30.0"
|
|
38
|
+
check: "git --version"
|
|
39
|
+
purpose: "Workspace detection, worktrees for parallel stories, churn data for map/hotspots.md."
|
|
40
|
+
install:
|
|
41
|
+
macos: "xcode-select --install (or: brew install git)"
|
|
42
|
+
linux: "sudo apt-get install git (or your distro's package manager)"
|
|
43
|
+
windows: "winget install Git.Git"
|
|
44
|
+
|
|
45
|
+
- id: claude
|
|
46
|
+
required: true
|
|
47
|
+
min_version: "2.0.0"
|
|
48
|
+
check: "claude --version"
|
|
49
|
+
purpose: "The pilot harness. Sub-agents run as `claude -p --output-format json`; hooks and the statusline are Claude Code primitives."
|
|
50
|
+
install:
|
|
51
|
+
all: "npm install -g @anthropic-ai/claude-code (see https://code.claude.com/docs/en/quickstart)"
|
|
52
|
+
|
|
53
|
+
- id: python3
|
|
54
|
+
required: false
|
|
55
|
+
min_version: "3.10.0"
|
|
56
|
+
check: "python3 --version"
|
|
57
|
+
purpose: "Runtime for graphify (the code-map tool). Only needed if you want `tldrx map`."
|
|
58
|
+
install:
|
|
59
|
+
macos: "brew install python@3.12 (or: https://www.python.org/downloads)"
|
|
60
|
+
linux: "sudo apt-get install python3 python3-pip"
|
|
61
|
+
windows: "winget install Python.Python.3.12"
|
|
62
|
+
|
|
63
|
+
- id: graphify
|
|
64
|
+
required: false
|
|
65
|
+
min_version: "0.8.0"
|
|
66
|
+
check: "graphify --version"
|
|
67
|
+
purpose: "Deterministic tree-sitter code map. Feeds map/*.md. Absent = `tldrx map` cannot run; nothing else is affected."
|
|
68
|
+
install:
|
|
69
|
+
all: "pip install graphify (requires python3 >= 3.10)"
|
|
70
|
+
|
|
71
|
+
- id: gh
|
|
72
|
+
required: false
|
|
73
|
+
min_version: "2.0.0"
|
|
74
|
+
check: "gh --version"
|
|
75
|
+
purpose: "Optional ticket adapter (GitHub issues) and PR operations."
|
|
76
|
+
install:
|
|
77
|
+
macos: "brew install gh"
|
|
78
|
+
linux: "https://github.com/cli/cli/blob/trunk/docs/install_linux.md"
|
|
79
|
+
windows: "winget install GitHub.cli"
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tldr-experts",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "tldr-experts: a lightweight, file-based AI development workflow. Installs the `tldrx` (and `tldr-experts`) command. Alpha.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Alan Martinez",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ederwii/tldr-experts.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/ederwii/tldr-experts#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ederwii/tldr-experts/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai",
|
|
17
|
+
"workflow",
|
|
18
|
+
"claude-code",
|
|
19
|
+
"agentic",
|
|
20
|
+
"developer-experience",
|
|
21
|
+
"tldr",
|
|
22
|
+
"experts",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"bin": {
|
|
27
|
+
"tldrx": "dist/tldrx.js",
|
|
28
|
+
"tldr-experts": "dist/tldrx.js"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20",
|
|
32
|
+
"bun": ">=1.3.0"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"CHANGELOG.md",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"README.md",
|
|
38
|
+
"dist",
|
|
39
|
+
"env.yml",
|
|
40
|
+
"plugin",
|
|
41
|
+
"stages",
|
|
42
|
+
"templates",
|
|
43
|
+
"workflows"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"test": "bun test",
|
|
50
|
+
"build": "bun scripts/build.ts",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"doctor": "bun bin/tldrx.ts doctor",
|
|
53
|
+
"prepublishOnly": "bun run build"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/bun": "^1.4.0",
|
|
57
|
+
"typescript": "^7.0.2",
|
|
58
|
+
"yaml": "^2.9.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$doc": "Shape verified from https://code.claude.com/docs/en/plugins.md (Quickstart > Create the plugin manifest). Fields used here: name, description, version, author.name. Only plugin.json goes inside .claude-plugin/; skills/, agents/ and hooks/ live at the plugin root.",
|
|
3
|
+
"name": "tldrx",
|
|
4
|
+
"description": "tldr-experts: a file-based AI development workflow. One loop, five phases, everything on disk. Alpha.",
|
|
5
|
+
"version": "0.3.0",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Alan Martinez"
|
|
8
|
+
}
|
|
9
|
+
}
|
package/plugin/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# tldrx — Claude Code plugin packaging
|
|
2
|
+
|
|
3
|
+
Load it for development straight from this directory:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
claude --plugin-dir ./plugin
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Then type `/tldrx:tldrx`. (Plugin skills are always namespaced `/<plugin>:<skill>`.)
|
|
10
|
+
|
|
11
|
+
## Or install it, and skip the flag
|
|
12
|
+
|
|
13
|
+
`--plugin-dir` lasts one session and needs this checkout. For a project or a
|
|
14
|
+
machine that should just have it:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
tldrx install --claude # ./.claude/ (this project; needs a git repo)
|
|
18
|
+
tldrx install --claude --user # ~/.claude/ (this machine)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
That writes the same skill and the same six hooks into a real `.claude/`, plus the
|
|
22
|
+
status line this plugin cannot install (see below). It is idempotent, it never
|
|
23
|
+
touches `permissions`, and `--uninstall` takes exactly it back out. The README's
|
|
24
|
+
[Claude Code integration](../README.md#claude-code-integration) section has the
|
|
25
|
+
settings fragment it writes.
|
|
26
|
+
|
|
27
|
+
**The two wirings differ in one thing only: how a hook is named.** The plugin
|
|
28
|
+
spawns `bun ${CLAUDE_PLUGIN_ROOT}/../src/hooks/<name>.ts`, and it keeps doing that
|
|
29
|
+
on purpose — a plugin must work for someone who cloned the repo and installed
|
|
30
|
+
nothing, so it cannot depend on a global `tldrx`. The installed `settings.json`
|
|
31
|
+
uses `tldrx hook <name>` instead, because that file gets committed and cloned onto
|
|
32
|
+
a machine whose checkout is somewhere else, where an absolute path is simply wrong.
|
|
33
|
+
Same scripts, same matchers, same timeouts, same decisions.
|
|
34
|
+
|
|
35
|
+
## What is wired
|
|
36
|
+
|
|
37
|
+
| Path | What it is |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `.claude-plugin/plugin.json` | Manifest: `name`, `description`, `version`, `author`. |
|
|
40
|
+
| `skills/tldrx/SKILL.md` | The facilitator. `disable-model-invocation: true` — only you can invoke it, and its body costs nothing until you do. |
|
|
41
|
+
| `hooks/hooks.json` | Eight handlers over six hook scripts on four events. **All live** — see the table below. |
|
|
42
|
+
| `agents/` | Deliberately empty — experts are generated per project. |
|
|
43
|
+
|
|
44
|
+
## The hooks
|
|
45
|
+
|
|
46
|
+
| Script | Event(s) | Matcher | What it does |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `claim-sources.ts` | PreToolUse, PostToolUse | `Write\|Edit` | Computes the **would-be** content (Write: `content`; Edit: `old_string`→`new_string` applied to the file on disk) and, when it is a handoff under `tldrx-work/`, denies unless every `- ` bullet under Findings / Decisions / Unknowns / Evidence ledger ends with a resolvable `[src: …]` token (spec §2.8). On PostToolUse the same check can only report, so it emits `additionalContext`. |
|
|
49
|
+
| `no-reask.ts` | PreToolUse | `Write\|Edit` | On `questions.md`: for each question the file does not already carry, denies when a non-retired `facts.yml` row in the same `area` scores Jaccard ≥ 0.6 over ≥4-char tokens, and names the fact. |
|
|
50
|
+
| `answer-capture.ts` | PostToolUse, FileChanged | `Write\|Edit` / none | For every block that is `status: open` with a non-empty `[Answer]:`, writes the answer footer, appends a `facts.yml` row (`kind: answer`, `source.q`) plus `question.answered` and `fact.added` events, and echoes `tldrx: recorded Q4 → F020`. Never blocks. |
|
|
51
|
+
| `dod-gate.ts` | PreToolUse | `Write\|Edit` | On a `stories/*.md` write that sets `status: done`: re-runs every command in the story's fenced ```` ```dod ```` block from the repo named by `repo:` (resolved through `workspace.yml`), each within `timeout_s` (default 900). Denies unless all exit 0, or if the block is missing. |
|
|
52
|
+
| `budget-gate.ts` | PreToolUse | `Bash` | On a command matching `^(claude -p\|tldrx next)`: resolves the run (`--run`, the cwd, or the newest non-terminal `run.yml`), and denies when the cursor phase cannot afford the stage's `budget_usd` and `on_exceed: block`. Appends `budget.blocked`. |
|
|
53
|
+
| `session-start.ts` | SessionStart | none | Up to three lines of "where we are" via `additionalContext`. Silent when there is no non-terminal run. |
|
|
54
|
+
|
|
55
|
+
**Two rules the whole set obeys.** Only PreToolUse can block, and it blocks by
|
|
56
|
+
printing `{"hookSpecificOutput": {"hookEventName": "PreToolUse",
|
|
57
|
+
"permissionDecision": "deny", "permissionDecisionReason": "…"}}` and exiting `0` —
|
|
58
|
+
an exit code never denies here. And every hook except `dod-gate` fails **open**: an
|
|
59
|
+
internal error exits `0` and writes one line to stderr
|
|
60
|
+
(`tldrx hook <name>: internal error, allowing — …`). `dod-gate` fails **closed**
|
|
61
|
+
once it has identified the write as a story being marked done, because an unproven
|
|
62
|
+
story must stay not-done.
|
|
63
|
+
|
|
64
|
+
The `matcher` on the `FileChanged` entry is deliberately omitted: matcher support
|
|
65
|
+
for that event is not in the verified docs, so the script filters on the path
|
|
66
|
+
itself. The `budget-gate` matcher is `Bash`, not `Task` — the money is spent by a
|
|
67
|
+
shell command whose estimate is in `tool_input.command`, and nothing in the
|
|
68
|
+
verified docs says a subagent spawn arrives with a budget to check.
|
|
69
|
+
|
|
70
|
+
Shapes were copied from the official docs, with the source URL recorded next to
|
|
71
|
+
each one:
|
|
72
|
+
|
|
73
|
+
- https://code.claude.com/docs/en/plugins.md
|
|
74
|
+
- https://code.claude.com/docs/en/hooks.md
|
|
75
|
+
- https://code.claude.com/docs/en/skills.md
|
|
76
|
+
- https://code.claude.com/docs/en/statusline.md
|
|
77
|
+
|
|
78
|
+
## The status line is not a hook
|
|
79
|
+
|
|
80
|
+
`statusLine` is a **settings key**, not a hook event, and a plugin's own
|
|
81
|
+
`settings.json` supports only `agent` and `subagentStatusLine` — so the plugin
|
|
82
|
+
cannot install it for you. `tldrx install --claude` can, because it writes the real
|
|
83
|
+
settings file; it puts in `{"type": "command", "command": "tldrx statusline"}`, and
|
|
84
|
+
leaves any status line that is not tldrx's alone. If you are loading the plugin
|
|
85
|
+
instead, add this to your `~/.claude/settings.json` or the project's
|
|
86
|
+
`.claude/settings.json` yourself:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"statusLine": {
|
|
91
|
+
"type": "command",
|
|
92
|
+
"command": "bun /absolute/path/to/tldr-experts/src/hooks/statusline.ts",
|
|
93
|
+
"padding": 2
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
It renders `[tldrx] <model> ctx:<n>% $<cost>` from the fields Claude Code already
|
|
99
|
+
measures, and `[tldrx] no session data` when they are absent. The richer line from
|
|
100
|
+
the concept doc (run id, phase, progress bar, budget ceiling) needs `run.yml`,
|
|
101
|
+
which v0 does not write yet — so it is not rendered rather than faked.
|
|
102
|
+
|
|
103
|
+
## Known `claude plugin validate` warnings
|
|
104
|
+
|
|
105
|
+
`claude plugin validate ./plugin` exits 0 with two warnings. Both are deliberate:
|
|
106
|
+
|
|
107
|
+
1. **`$doc: Unknown field '$doc'`** — JSON has no comments, and this repo's rule is
|
|
108
|
+
that every Claude Code shape carries its source URL beside it. The validator
|
|
109
|
+
itself confirms the field is *ignored at load time*, so it costs nothing.
|
|
110
|
+
2. **`agents/README.md: No frontmatter block found`** — the directory holds
|
|
111
|
+
documentation, not an agent. Adding frontmatter would register a fake agent
|
|
112
|
+
named `README`, which is worse than a warning. Experts are generated per project
|
|
113
|
+
by `tldrx init`; nothing belongs here.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agents
|
|
2
|
+
|
|
3
|
+
**Nothing ships here.**
|
|
4
|
+
|
|
5
|
+
Experts in tldr-experts are *generated per project* by `tldrx init` (concept §4.5):
|
|
6
|
+
one stack expertise per language/framework detected, one domain expert per detected
|
|
7
|
+
domain. They are written to the project's `.tldrx/experts/<name>/` as a pair of
|
|
8
|
+
files:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
.tldrx/experts/<name>/
|
|
12
|
+
expert.md role, domain, how to reason, what to cite
|
|
13
|
+
competencies.yml {area, level 0-5, evidence: [...], last_trained}
|
|
14
|
+
knowledge/*.md trained material, with file:line provenance (v1.1)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
A shipped `agents/*.md` here would be the opposite of that: a fixed cast of
|
|
18
|
+
personas that knows nothing about your code. If a stage needs a persona, it names
|
|
19
|
+
it in `stage.yml` and the facilitator loads the generated file.
|
|
20
|
+
|
|
21
|
+
See `templates/expert.md` and `templates/competencies.yml` for the shapes
|
|
22
|
+
`tldrx init` will write.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "tldrx v0 hooks — LIVE. Shape verified from https://code.claude.com/docs/en/hooks.md: top-level `hooks` map keyed by event name, each entry { matcher?, hooks: [ { type, command, args?, timeout? } ] }. Exec form (`command` + `args`) and ${CLAUDE_PLUGIN_ROOT} are from that page. Only PreToolUse can deny, and it denies by printing {\"hookSpecificOutput\": {\"hookEventName\": \"PreToolUse\", \"permissionDecision\": \"deny\", \"permissionDecisionReason\": \"…\"}} and exiting 0 — never by an exit code. Every hook but DoD-gate fails OPEN. NOTE: the status line is NOT a hook event — it is the `statusLine` settings key, and a plugin settings.json only supports `agent` and `subagentStatusLine`. Wire it yourself; see plugin/README.md.",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"_note": "claim-sources (spec §4) — the gate. Denies a handoff under tldrx-work/ whose Findings/Decisions/Unknowns/Evidence-ledger bullets do not each end with a resolvable [src: …] token.",
|
|
7
|
+
"matcher": "Write|Edit",
|
|
8
|
+
"hooks": [
|
|
9
|
+
{
|
|
10
|
+
"type": "command",
|
|
11
|
+
"command": "bun",
|
|
12
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/claim-sources.ts"],
|
|
13
|
+
"timeout": 15
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"_note": "no-re-ask (spec §4, concept §1.2) — denies a NEW open question in tldrx-work/**/questions.md whose subject already has a non-retired facts.yml row (Jaccard >= 0.6 on >=4-char tokens, same area).",
|
|
19
|
+
"matcher": "Write|Edit",
|
|
20
|
+
"hooks": [
|
|
21
|
+
{
|
|
22
|
+
"type": "command",
|
|
23
|
+
"command": "bun",
|
|
24
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/no-reask.ts"],
|
|
25
|
+
"timeout": 15
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"_note": "DoD-gate (spec §4, concept §8) — re-runs every command in a story's fenced ```dod block, in its repo, and denies unless each exits 0. This hook is not <50 ms by design, and it is the one hook that fails CLOSED.",
|
|
31
|
+
"matcher": "Write|Edit",
|
|
32
|
+
"hooks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "bun",
|
|
36
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/dod-gate.ts"],
|
|
37
|
+
"timeout": 960
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"_note": "budget-gate (spec §4) — matcher is Bash, because the money is spent by `claude -p …` / `tldrx next`, which is a Bash command with the estimate in tool_input.command. The earlier `Task` matcher was a guess and is dropped: nothing in the verified docs says a subagent spawn arrives here with a budget to check.",
|
|
43
|
+
"matcher": "Bash",
|
|
44
|
+
"hooks": [
|
|
45
|
+
{
|
|
46
|
+
"type": "command",
|
|
47
|
+
"command": "bun",
|
|
48
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/budget-gate.ts"],
|
|
49
|
+
"timeout": 15
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"PostToolUse": [
|
|
55
|
+
{
|
|
56
|
+
"_note": "answer-capture (spec §2.7/§4) — writes the answer footer, the facts.yml row and the question.answered event for every block that is `status: open` with a non-empty [Answer]:. Never blocks; echoes one line of additionalContext.",
|
|
57
|
+
"matcher": "Write|Edit",
|
|
58
|
+
"hooks": [
|
|
59
|
+
{
|
|
60
|
+
"type": "command",
|
|
61
|
+
"command": "bun",
|
|
62
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/answer-capture.ts"],
|
|
63
|
+
"timeout": 15
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"_note": "claim-sources twin (spec §4: 'a PostToolUse twin re-checks and feeds back only'). Same script, same checks; on PostToolUse it can only report, so it emits additionalContext instead of a denial.",
|
|
69
|
+
"matcher": "Write|Edit",
|
|
70
|
+
"hooks": [
|
|
71
|
+
{
|
|
72
|
+
"type": "command",
|
|
73
|
+
"command": "bun",
|
|
74
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/claim-sources.ts"],
|
|
75
|
+
"timeout": 15
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"FileChanged": [
|
|
81
|
+
{
|
|
82
|
+
"_note": "answer-capture again — a human editing questions.md in an editor never goes through Write/Edit. Matcher omitted: FileChanged's matcher support is not in the verified docs, so the script filters on the path itself.",
|
|
83
|
+
"hooks": [
|
|
84
|
+
{
|
|
85
|
+
"type": "command",
|
|
86
|
+
"command": "bun",
|
|
87
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/answer-capture.ts"],
|
|
88
|
+
"timeout": 15
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"SessionStart": [
|
|
94
|
+
{
|
|
95
|
+
"_note": "session-start (concept §3) — up to three lines of 'where we are' from the newest non-terminal run.yml, injected as additionalContext. Matcher omitted so it fires for every start reason (startup, resume, clear, compact, fork).",
|
|
96
|
+
"hooks": [
|
|
97
|
+
{
|
|
98
|
+
"type": "command",
|
|
99
|
+
"command": "bun",
|
|
100
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../src/hooks/session-start.ts"],
|
|
101
|
+
"timeout": 15
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Fields verified from https://code.claude.com/docs/en/skills.md (§ "Frontmatter
|
|
3
|
+
# reference"). `disable-model-invocation: true` means ONLY the user can invoke this
|
|
4
|
+
# skill: its body stays out of context until someone types /tldrx — concept §1.3's
|
|
5
|
+
# non-intrusive requirement, satisfied natively.
|
|
6
|
+
name: tldrx
|
|
7
|
+
description: The tldr-experts facilitator. Finds what is pending in this workspace and walks the human through it one item at a time, reading and writing files only. Invoke with /tldrx.
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
argument-hint: "[optional: which item, or what you want to work on]"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# tldrx — status, then guide
|
|
13
|
+
|
|
14
|
+
**Alpha.** Every command is implemented. `tldrx --help` is the authoritative
|
|
15
|
+
surface — read it before you promise anything, and never narrate progress a tool
|
|
16
|
+
did not make.
|
|
17
|
+
|
|
18
|
+
## What you are
|
|
19
|
+
|
|
20
|
+
A facilitator, not an author. You read files, hand ONE sub-agent ONE task, write
|
|
21
|
+
the result back, and stop at the gate. You hold no state between steps — the files
|
|
22
|
+
are the state. You do not decide anything that is the human's to decide.
|
|
23
|
+
|
|
24
|
+
## Step 1, always
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
tldrx status --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
It is free, deterministic, and exits 0 whatever it finds (exit 3 only means there
|
|
31
|
+
is no `.tldrx/` here — then the answer is `tldrx init`). It returns
|
|
32
|
+
`{root, pending, items[], advice[]}`, each item `{kind, summary, command, details}`,
|
|
33
|
+
already in the order the items block each other. `items` are the BLOCKERS and all
|
|
34
|
+
`pending` counts; `advice` blocks nothing — relay it once, briefly. **That list is
|
|
35
|
+
the agenda.** Do not ask "what would you like to do?" first.
|
|
36
|
+
|
|
37
|
+
Then take item 1. One item at a time, in order. Say in one plain sentence what it
|
|
38
|
+
is and why it matters — no jargon a first-time user would not have — then either
|
|
39
|
+
ask or act, per the rule below. **After each item, re-run `tldrx status`**: acting
|
|
40
|
+
on one item changes the list.
|
|
41
|
+
|
|
42
|
+
## Ask, or act
|
|
43
|
+
|
|
44
|
+
**The human decides** — you present, quote the relevant file section, and ASK.
|
|
45
|
+
Never answer on their behalf, never pick a default, never "assume yes":
|
|
46
|
+
|
|
47
|
+
- `init-questions` — facts about their project nobody could detect. Run
|
|
48
|
+
`tldrx interview --init` and relay each question. Piped stdin is ONE LINE PER
|
|
49
|
+
QUESTION in file order; a single letter `A`–`E` picks that option, other text is
|
|
50
|
+
recorded verbatim, an empty line or `s` skips, `q` stops. **Never pass
|
|
51
|
+
`--yes-to-defaults`** — it answers every question with its first option.
|
|
52
|
+
- `seed-split` — a proposal that creates nothing until someone applies it. Show
|
|
53
|
+
`split.md`, the unanswered questions, and the seed documents still marked
|
|
54
|
+
`proposed`. Record decisions with `tldrx seed answer <split.yml> <Qid> "<text>"`;
|
|
55
|
+
edit `split.yml` if they want different runs.
|
|
56
|
+
- a gate, an answer, or any ADR/decision document — quote it and ask.
|
|
57
|
+
- a gate `tldrx status` reports as signed `by: auto` that they disagree with. It signs
|
|
58
|
+
only when its five conditions hold and cannot judge whether a decision was RIGHT: quote
|
|
59
|
+
the note — it carries all five measured values — and ask before revoking.
|
|
60
|
+
|
|
61
|
+
**You act** once they have said what they want — these are mechanical:
|
|
62
|
+
|
|
63
|
+
- `tldrx seed apply <split.yml> --dry-run`, then the real apply when they say so.
|
|
64
|
+
- `tldrx answer <Qid> "<what they said>" --run <id>` · `tldrx approve --run <id>`
|
|
65
|
+
after they said yes · `tldrx reject --run <id> --note "<their reason>"`, and
|
|
66
|
+
`tldrx reject --run <id> --stage <phase>/<stage> --note "…"` to take back an
|
|
67
|
+
approval already given (including one the harness signed `by: auto`).
|
|
68
|
+
- `tldrx questions lint --run <id>` when a stage wrote a `questions.md`: it exits 2
|
|
69
|
+
if any block is invisible to the parser, and `--fix` converts it without changing
|
|
70
|
+
a word. An unreadable file reads as "no questions" to everything downstream.
|
|
71
|
+
- one stage of a run, via the in-session recipe below.
|
|
72
|
+
- `tldrx expert train <name> --area <a> --mode <light|full> --print-prompt` — the
|
|
73
|
+
printed prompt costs nothing; running it is a spend, so see Money. The `expert`
|
|
74
|
+
entry arrives in `advice`, not `items`, and its `command` is always
|
|
75
|
+
`tldrx expert list`: it degrades a stage, it never blocks one. Its `details` name
|
|
76
|
+
the trainable experts and, separately, any role expert that has no past run to
|
|
77
|
+
mine — that one is not a task yet. Mention it once and carry on with `items`.
|
|
78
|
+
|
|
79
|
+
## When nothing is pending
|
|
80
|
+
|
|
81
|
+
`pending: 0` means open work — and what the work IS is the human's decision, not a
|
|
82
|
+
lookup. Offer `tldrx run new <slug> --scope <s> [--seed <path>] [--budget <usd>]`,
|
|
83
|
+
where `<s>` is a file stem in `.tldrx/workflows/` or the shipped `workflows/`:
|
|
84
|
+
`feature` `bugfix` `hotfix` `refactor` `docs` `spike` `prototype` `migration`
|
|
85
|
+
`integration` `performance` `security-patch` `upgrade` `retro`. If `run new --seed`
|
|
86
|
+
prints `note: seed is N files / ~T tokens …` on stderr, relay it and offer
|
|
87
|
+
`tldrx seed triage <path>` (free, spawns nothing): one run carrying that much seed
|
|
88
|
+
pays for it at every stage.
|
|
89
|
+
|
|
90
|
+
## Running one stage of a run
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
1 tldrx next --prepare [<run>] # writes the prompt bundle; exits 0 and stops
|
|
94
|
+
2 dispatch ONE sub-agent # Agent tool, prompt = .agent/<stage>/prompt.md
|
|
95
|
+
3 write .agent/<stage>/result.json # {outputs, questions_asked, notes}
|
|
96
|
+
4 tldrx next --commit [<run>] --cost-usd <n> # validates outputs + checks, rolls up cost, gates
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Step 1 names the bundle, the writable files and the finishing command. Step 2:
|
|
100
|
+
pass `prompt.md` to the Agent tool **unedited** — it already inlines the stage
|
|
101
|
+
body, the experts and every declared input — and tell the sub-agent to write ONLY
|
|
102
|
+
the files `pending.json` lists, read nothing else, and end every bullet under
|
|
103
|
+
Findings / Decisions / Unknowns / Evidence ledger with a `[src: …]` token. Step 4
|
|
104
|
+
re-reads every output off disk and re-runs the checks whatever step 3 claimed.
|
|
105
|
+
Pass `--cost-usd <n>` on step 4 when you know what the sub-agent cost: an in-session
|
|
106
|
+
turn has no meter of its own, and without a declared number the task is recorded as
|
|
107
|
+
`cost_usd: null, metered: false` — honest, but it makes the run's `spent` a lower
|
|
108
|
+
bound rather than a total. Never guess one; omitting it is the correct move when you
|
|
109
|
+
do not know.
|
|
110
|
+
|
|
111
|
+
**One stage per `/tldrx` call.** When a run's remaining gates are mostly `auto`
|
|
112
|
+
(`run.yml` `gates_policy:`) and nobody needs to watch, say so and offer
|
|
113
|
+
`tldrx run auto <id>` — the headless loop. It spawns its own sessions, so suggest
|
|
114
|
+
it for a terminal, never run it from inside this one.
|
|
115
|
+
|
|
116
|
+
| exit | meaning | what you do |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| 0 | done, cursor advanced | `tldrx status` again |
|
|
119
|
+
| 2 | refused — budget, a held lock, an uncommitted `--prepare` bundle, or you left off the run id | report it; do not retry blindly. A lock whose pid is dead clears with `tldrx run unlock <id>`; a run they have given up on closes with `tldrx run cancel <id> --note "<their reason>"` — both need their say-so first |
|
|
120
|
+
| 3 | not found | `tldrx status` says what exists instead |
|
|
121
|
+
| 4 | a human is needed | `tldrx approve` (gate) or `tldrx answer <Qid> "…"` (question) |
|
|
122
|
+
| 5 | the stage failed | report the reason verbatim; the cost is spent, not refunded. If it names an unreadable `questions.md`, `tldrx questions lint --fix --run <id>` converts it without changing a word, then `--commit` again |
|
|
123
|
+
|
|
124
|
+
**Several runs open**: every run-targeting command refuses with exit 2 rather than
|
|
125
|
+
guessing, and lists the candidates. That means "you forgot the id", not "something
|
|
126
|
+
broke" — pass it. `tldrx status` and `tldrx run status` always show all of them.
|
|
127
|
+
|
|
128
|
+
## Money
|
|
129
|
+
|
|
130
|
+
Before anything that spends: **state the ceiling and ask.** `tldrx next`,
|
|
131
|
+
`tldrx run auto`, `tldrx expert train` (without `--print-prompt`) and
|
|
132
|
+
`tldrx seed triage --propose` (`--max-usd 1.00` by default) all cost real money;
|
|
133
|
+
`seed triage` without `--propose` is free. Never raise `--max-usd` or run
|
|
134
|
+
`tldrx budget raise` for them — a stage that costs more than remains exits 2 and
|
|
135
|
+
names the exact command; report it and let them decide.
|
|
136
|
+
|
|
137
|
+
Three free read-only commands answer what it will cost and what it did: `tldrx run
|
|
138
|
+
estimate` (the only one that guesses, and says so), `tldrx cost [--all]` (per attempt —
|
|
139
|
+
retries are where the money is) and `tldrx budget show`. Quote them, never the arithmetic;
|
|
140
|
+
`cost` reports an in-session turn as UNMETERED unless step 4 declared `--cost-usd`.
|
|
141
|
+
|
|
142
|
+
## Rules you do not get to bend
|
|
143
|
+
|
|
144
|
+
1. **Never hand-edit `run.yml` or `events.jsonl`.** The tools own them; the log is
|
|
145
|
+
append-only. Want a state change? Run the command that owns it.
|
|
146
|
+
2. **Never answer a question on the human's behalf.** An invented answer poisons
|
|
147
|
+
`facts.yml` permanently — every future run will cite it.
|
|
148
|
+
3. **Every claim carries a source**: `[src: path:line]`, `[src: <url>]`,
|
|
149
|
+
`[src: Q<n>]`, `[src: F<n>]`. Unsourced goes in Unknowns and becomes a question.
|
|
150
|
+
4. **Never ask what is already known.** Grep `.tldrx/memory/facts.yml` first.
|
|
151
|
+
5. **Verify from the source, not from your own output.** After a write, re-read it
|
|
152
|
+
from disk. A sub-agent reporting "ok" is not evidence.
|
|
153
|
+
6. **Say which you are in: measured, inferred, or assumed.** Never blur them.
|
|
154
|
+
7. **Stop at gates.** You never close one — not even an `auto` gate, which the
|
|
155
|
+
framework closes itself and only when all five of its conditions hold.
|
|
156
|
+
8. **A checked section holds at least one item.** Nothing to report is still an
|
|
157
|
+
item: `- none [src: absent:<what you looked at>]`. Prose is refused.
|
|
158
|
+
9. **`.tldrx/` and `tldrx-work/` are committed** — the files ARE the state. `init`
|
|
159
|
+
gitignores only the machine-local scratch (`graphify-out/`, `cache/`,
|
|
160
|
+
`worktrees/`, `tldrx-work/*/.lock`, `tldrx-work/*/.agent/`).
|
|
161
|
+
|
|
162
|
+
## The loop, for orientation
|
|
163
|
+
|
|
164
|
+
Every stage is the same four steps: **Investigate** (read code, docs and memory;
|
|
165
|
+
findings carry sources) → **Handoff** (one `.md`: found, decided, still unknown) →
|
|
166
|
+
**Interview** (only the unknowns become questions; answers land in `facts.yml`) →
|
|
167
|
+
**Gate** (a human approves; recorded in `run.yml` + `events.jsonl`). The five
|
|
168
|
+
phases — **what · how · plan · build · watch** — are that loop with different
|
|
169
|
+
inputs, outputs and experts: `.tldrx/stages/<slug>/stage.yml` declares which,
|
|
170
|
+
`.tldrx/workflows/<scope>.yml` declares the order.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!-- schema: draft -->
|
|
2
|
+
<!-- Stage template: build (phase 4). -->
|
|
3
|
+
<!--
|
|
4
|
+
READ THIS FIRST: unlike every other stage, this file is NOT the prompt.
|
|
5
|
+
|
|
6
|
+
`04-build` is run by the wave executor (spec §5, "Build executor"), which builds
|
|
7
|
+
its own per-story developer prompt and per-story reviewer prompt from the Plan
|
|
8
|
+
artefacts, and writes `04-build/handoff.md` itself. Editing this file changes the
|
|
9
|
+
documentation of the phase, not what the sub-agents are told. The prompts live in
|
|
10
|
+
`src/core/build/prompts.ts`; the pipeline lives in
|
|
11
|
+
`src/core/facilitator/executors/build.ts`.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
# Build — what the phase does
|
|
15
|
+
|
|
16
|
+
## Role
|
|
17
|
+
|
|
18
|
+
The facilitator is the contractor here, not an author. It hands each story to a
|
|
19
|
+
developer sub-agent, proves the result, and merges it — and it writes the handoff
|
|
20
|
+
from what it measured rather than asking anyone to summarise it.
|
|
21
|
+
|
|
22
|
+
## Objective
|
|
23
|
+
|
|
24
|
+
Turn `03-plan/waves.yml` into merged code on epic branches, one story at a time,
|
|
25
|
+
in wave order. Done-when: every scheduled story is `done` (DoD green, reviewer
|
|
26
|
+
approved, evidence written into its front matter) or `blocked` with a reason a
|
|
27
|
+
human can act on, and every epic branch is left ready to merge **by hand**.
|
|
28
|
+
|
|
29
|
+
## Inputs
|
|
30
|
+
|
|
31
|
+
`03-plan/waves.yml`, `03-plan/stories/<id>.md`, `03-plan/epics/<id>.md`, the
|
|
32
|
+
workspace conventions, and — per story — the content of every path its `touches`
|
|
33
|
+
list names, read from that story's own worktree.
|
|
34
|
+
|
|
35
|
+
## Investigate
|
|
36
|
+
|
|
37
|
+
Per story, in `waves.yml` order:
|
|
38
|
+
|
|
39
|
+
1. resolve the story's repo from `workspace.yml`, and refuse the whole phase if
|
|
40
|
+
that repo's tree is dirty;
|
|
41
|
+
2. ensure `epic/<slug>` exists, cut from the repo's `default_branch`;
|
|
42
|
+
3. open a worktree at `.tldrx/worktrees/<repo>/<story-id>` on `story/<id>`;
|
|
43
|
+
4. spawn ONE developer sub-agent with cwd = that worktree.
|
|
44
|
+
|
|
45
|
+
## Produce
|
|
46
|
+
|
|
47
|
+
- `04-build/log/<story-id>.md` — the review log, one per story touched
|
|
48
|
+
- `04-build/handoff.md` — Findings per story, Evidence ledger of dod commands
|
|
49
|
+
- `03-plan/stories/<id>.md` — `status:` and `evidence:` written back
|
|
50
|
+
- `epic/<slug>` branches, merged from `story/<id>`, **never pushed**
|
|
51
|
+
|
|
52
|
+
## Rules
|
|
53
|
+
|
|
54
|
+
- Done means proven: the ```dod block is re-run by the facilitator, in the story's
|
|
55
|
+
worktree, and every command must exit 0. A sub-agent's own "it works" is not
|
|
56
|
+
evidence and is never recorded as any.
|
|
57
|
+
- A reviewer's `changes` requeues the story ONCE, with the review under
|
|
58
|
+
`## Previous attempt`. A second `changes` blocks it.
|
|
59
|
+
- A DoD failure or a merge conflict blocks that story only — the wave carries on.
|
|
60
|
+
- Nothing pushes. No epic is merged into a default branch.
|
|
61
|
+
|
|
62
|
+
## Questions
|
|
63
|
+
|
|
64
|
+
None. The Interview happened in What and How; a story that still needs a human
|
|
65
|
+
answer is a Plan bug, and it surfaces here as `blocked`.
|
|
66
|
+
|
|
67
|
+
## Stop
|
|
68
|
+
|
|
69
|
+
At the gate. `tldrx approve` after merging the epic branches, or
|
|
70
|
+
`tldrx reject --note "…"` to send the phase back.
|