@jaggerxtrm/specialists 3.15.1 → 3.15.3
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/README.md +175 -97
- package/config/skills/using-specialists-v3/SKILL.md +113 -35
- package/dist/asset-contract.json +2 -2
- package/dist/index.js +175 -68
- package/dist/lib.js +45 -25
- package/dist/types/cli/run.d.ts.map +1 -1
- package/dist/types/cli/serve.d.ts +1 -1
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -1,162 +1,241 @@
|
|
|
1
1
|
# Specialists
|
|
2
2
|
|
|
3
|
-
**One MCP server. Many
|
|
3
|
+
**One MCP server. Many specialist agents. Bead-first orchestration.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@jaggerxtrm/specialists)
|
|
6
|
-
[](
|
|
6
|
+
[](LICENSE)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Specialists is a project-scoped runtime for running focused AI agents from the CLI, MCP, scripts, CI, or HTTP sidecars. A specialist definition declares its model, tools, permission tier, prompt, skills, output contract, timeout/stall policy, worktree behavior, and tracking behavior. The orchestrator keeps task identity in a **bead**; specialists run as fresh scoped sessions that report evidence, changes, and results back to that bead.
|
|
10
10
|
|
|
11
|
-
Specialists
|
|
11
|
+
Specialists sits in the xt/xtrm stack:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- **[pi coding agent](https://github.com/Jaggerxtrm/pi-coding-agent)** supplies the model/provider execution layer, JSONL/RPC subprocess boundary, tool events, and extension hooks.
|
|
14
|
+
- **[xtrm-tools](https://github.com/Jaggerxtrm/xtrm-tools)** supplies the surrounding operator workflow: worktree sessions, `.xtrm/` skills/hooks, session reports, update tooling, and workflow enforcement.
|
|
15
|
+
- **[beads](https://github.com/steveyegge/beads)** supplies issue IDs, dependency edges, claims, and durable task/result notes.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
When a run starts from `--bead <id>`, the bead is the task prompt. Dependency context and relevant memory can be injected, the specialist output is appended back to the same bead, and edit-capable specialists work in isolated branches/worktrees that can be reviewed and merged through `sp merge` or `sp epic merge`.
|
|
16
18
|
|
|
17
19
|
---
|
|
18
20
|
|
|
19
21
|
## Vision
|
|
20
22
|
|
|
21
|
-
Specialists turns one overloaded agent chat into a coordinated agent mind: a central orchestrator keeps task identity and
|
|
23
|
+
Specialists turns one overloaded agent chat into a coordinated agent mind: a central orchestrator keeps task identity, evidence, and publication control, while fresh specialist sessions act as scoped capabilities with their own prompts, rules, tools, memory, and output contracts.
|
|
24
|
+
|
|
25
|
+
The problem it solves is not just token count. Long single-agent sessions accumulate old hypotheses, partial plans, tool residue, self-review bias, and forgotten constraints. Specialists uses **contract-bound cognition** instead: write the task contract once, dispatch the right expert role with only the relevant context, require a structured handoff, and let the orchestrator decide the next step.
|
|
26
|
+
|
|
27
|
+
See [specialists.scheme.md](specialists.scheme.md) for the full diagrams and rationale. The core shape is:
|
|
28
|
+
|
|
29
|
+
```mermaid
|
|
30
|
+
flowchart TD
|
|
31
|
+
U[User / project need] --> O[Orchestrator]
|
|
32
|
+
O --> B[Bead issue contract]
|
|
33
|
+
B --> C{Contract ready?}
|
|
34
|
+
C -->|no| R[Repair scope, success, constraints]
|
|
35
|
+
R --> B
|
|
36
|
+
C -->|yes| D[Dispatch specialist]
|
|
37
|
+
|
|
38
|
+
D --> E[Explorer\nfresh read-only context]
|
|
39
|
+
D --> G[Debugger\nfresh root-cause context]
|
|
40
|
+
D --> X[Executor\nfresh implementation context]
|
|
41
|
+
D --> T[Test-runner\nfresh validation context]
|
|
42
|
+
D --> S[Code-sanity / Security\nadvisory context]
|
|
43
|
+
D --> V[Reviewer\ncontract compliance context]
|
|
44
|
+
|
|
45
|
+
B --> E
|
|
46
|
+
B --> G
|
|
47
|
+
B --> X
|
|
48
|
+
B --> T
|
|
49
|
+
B --> S
|
|
50
|
+
B --> V
|
|
51
|
+
|
|
52
|
+
E --> H[Structured handoff / evidence]
|
|
53
|
+
G --> H
|
|
54
|
+
X --> H
|
|
55
|
+
T --> H
|
|
56
|
+
S --> H
|
|
57
|
+
V --> H
|
|
58
|
+
H --> O
|
|
59
|
+
O --> P[Merge, resume, re-review, or close]
|
|
60
|
+
```
|
|
22
61
|
|
|
23
|
-
##
|
|
62
|
+
## What you can run
|
|
24
63
|
|
|
25
|
-
|
|
64
|
+
| Need | Specialist / surface |
|
|
65
|
+
|---|---|
|
|
66
|
+
| Map unfamiliar local code | `explorer` |
|
|
67
|
+
| Diagnose a bug with unknown cause | `debugger` |
|
|
68
|
+
| Implement a scoped change | `executor` |
|
|
69
|
+
| Review an executor/debugger result | `reviewer --job <exec-job>` |
|
|
70
|
+
| Run/classify tests | `test-runner` |
|
|
71
|
+
| Current library/API/GitHub research | `researcher` |
|
|
72
|
+
| Plan a multi-file feature into beads | `planner` |
|
|
73
|
+
| Check code shape before review | `code-sanity` |
|
|
74
|
+
| Audit security-sensitive diffs | `security-auditor` |
|
|
75
|
+
| Sync exactly one doc | `sync-docs` |
|
|
76
|
+
| Draft changelog gaps | `changelog-keeper` |
|
|
77
|
+
| One-shot script/HTTP generation | `sp script` / `sp serve` |
|
|
78
|
+
|
|
79
|
+
The live registry is authoritative:
|
|
26
80
|
|
|
27
81
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
82
|
+
sp list
|
|
83
|
+
sp list --compact
|
|
84
|
+
sp list-rules
|
|
85
|
+
sp help
|
|
30
86
|
```
|
|
31
87
|
|
|
32
|
-
|
|
88
|
+
## Install and bootstrap
|
|
89
|
+
|
|
90
|
+
Specialists is **Bun-only** and expects xtrm-tools to be installed explicitly. xtrm-tools is a runtime prerequisite, not an npm dependency of this package.
|
|
33
91
|
|
|
34
92
|
```bash
|
|
93
|
+
# 1. Bun
|
|
94
|
+
curl -fsSL https://bun.sh/install | bash
|
|
95
|
+
bun --version
|
|
96
|
+
|
|
97
|
+
# 2. xtrm-tools
|
|
35
98
|
npm install -g xtrm-tools
|
|
36
99
|
xt install
|
|
37
100
|
xt init
|
|
38
|
-
```
|
|
39
101
|
|
|
40
|
-
3.
|
|
41
|
-
|
|
42
|
-
```bash
|
|
102
|
+
# 3. Specialists
|
|
43
103
|
npm install -g @jaggerxtrm/specialists
|
|
44
104
|
sp init
|
|
105
|
+
sp doctor
|
|
45
106
|
sp list
|
|
46
107
|
```
|
|
47
108
|
|
|
48
|
-
`sp` is
|
|
109
|
+
`sp` is an alias for `specialists`.
|
|
49
110
|
|
|
50
|
-
|
|
51
|
-
sp list
|
|
52
|
-
sp run bug-hunt --bead <id>
|
|
53
|
-
```
|
|
111
|
+
`sp init` is an interactive, human-run bootstrap. It checks for `xt` and `.xtrm/`, wires project MCP registration, hooks, skill symlinks, `.specialists/` runtime directories, and the Specialists block in `AGENTS.md`. It does **not** require copying package-owned defaults into every repo.
|
|
54
112
|
|
|
55
|
-
|
|
113
|
+
## Update and drift repair
|
|
114
|
+
|
|
115
|
+
Specialists uses two distribution tracks:
|
|
116
|
+
|
|
117
|
+
| Track | Owned by | What it covers | Check / update |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| **Category A** runtime assets | `@jaggerxtrm/specialists` package | specialist JSON, mandatory rules, catalog, nodes, hooks shipped with the package | `sp doctor --check-drift`, `sp prune-stale-defaults --dry-run`, `sp prune-stale-defaults` |
|
|
120
|
+
| **Category B** filesystem assets | xtrm-tools | `.xtrm/skills`, `.claude/skills`, `.pi/skills`, hook snapshots read directly from disk | `xt doctor --cwd <repo> --json`, `xt update --repo <repo> --apply` |
|
|
121
|
+
|
|
122
|
+
`.specialists/user/` is your customization layer. `.specialists/default/` is now only for intentional pins or compatibility snapshots; stale default files are drift debt and `sp prune-stale-defaults` removes them by default. `sp init --sync-defaults` remains as a compatibility path, but it is deprecated because it creates repo-local snapshots that can drift from the package-canonical source.
|
|
123
|
+
|
|
124
|
+
## Core tracked workflow
|
|
56
125
|
|
|
57
126
|
```bash
|
|
58
127
|
bd create "Investigate auth bug" -t bug -p 1 --json
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
128
|
+
bd update <id> --claim --json
|
|
129
|
+
|
|
130
|
+
sp run debugger --bead <id> --context-depth 3
|
|
131
|
+
sp ps
|
|
132
|
+
sp feed <job-id> --follow
|
|
133
|
+
sp result <job-id>
|
|
134
|
+
|
|
135
|
+
# After implementation and reviewer PASS
|
|
136
|
+
sp merge <chain-root-bead> # standalone chain
|
|
137
|
+
sp epic status <epic-id> # multi-chain publication check
|
|
138
|
+
sp epic merge <epic-id> # canonical epic publication
|
|
139
|
+
|
|
140
|
+
bd close <id> --reason "Done" --json
|
|
62
141
|
```
|
|
63
142
|
|
|
64
|
-
|
|
143
|
+
Ad-hoc work is still available, but tracked work should use beads:
|
|
65
144
|
|
|
66
145
|
```bash
|
|
67
|
-
|
|
68
|
-
specialists merge <bead-id> --rebuild # rebuild after merge
|
|
146
|
+
sp run explorer --prompt "Map the CLI architecture"
|
|
69
147
|
```
|
|
70
148
|
|
|
71
|
-
|
|
149
|
+
## Background jobs and monitoring
|
|
72
150
|
|
|
73
|
-
|
|
151
|
+
Normal runtime is DB-first: `.specialists/db/observability.db` stores jobs, events, and results. File mirrors under `.specialists/jobs/` are legacy/operator recovery surfaces.
|
|
74
152
|
|
|
75
|
-
|
|
153
|
+
Useful commands:
|
|
76
154
|
|
|
77
155
|
```bash
|
|
78
|
-
|
|
156
|
+
sp ps # actionable dashboard
|
|
157
|
+
sp ps -f # TTY dashboard follow; pipes emit ANSI-free snapshots
|
|
158
|
+
sp feed <job-id> # full DB-backed event replay
|
|
159
|
+
sp feed -f # follow all active jobs
|
|
160
|
+
sp result <job-id> --wait
|
|
161
|
+
sp steer <job-id> "focus only on X"
|
|
162
|
+
sp resume <job-id> "continue with these findings"
|
|
163
|
+
sp finalize <any-chain-job> # cascade-close waiting keep-alive chain after PASS if needed
|
|
164
|
+
sp clean --reap-orphans --dry-run
|
|
165
|
+
sp clean --ps # hide terminal dashboard history without deleting DB audit rows
|
|
79
166
|
```
|
|
80
167
|
|
|
81
|
-
##
|
|
168
|
+
## Script and service specialists
|
|
82
169
|
|
|
83
|
-
-
|
|
84
|
-
- creates `.specialists/` runtime dirs (`jobs/`, `ready/`)
|
|
85
|
-
- adds `.specialists/` to `.gitignore`
|
|
86
|
-
- injects the canonical Specialists Workflow block into `AGENTS.md`
|
|
87
|
-
- registers the Specialists MCP server at project scope
|
|
88
|
-
|
|
89
|
-
Verify bootstrap state:
|
|
170
|
+
Use `sp run` for interactive agent orchestration. Use the script/service surfaces when you need a synchronous, READ_ONLY, one-shot generation path:
|
|
90
171
|
|
|
91
172
|
```bash
|
|
92
|
-
|
|
93
|
-
|
|
173
|
+
sp script <name> --vars key=value --json
|
|
174
|
+
sp serve --port 8000 --readiness-canary warn
|
|
175
|
+
curl -sS http://localhost:8000/v1/generate \
|
|
176
|
+
-H 'content-type: application/json' \
|
|
177
|
+
-d '{"specialist":"hello","variables":{"name":"world"}}'
|
|
94
178
|
```
|
|
95
179
|
|
|
96
|
-
|
|
180
|
+
`sp serve` is intended as a sidecar for script-class specialists. For container deployments, mount the whole `.specialists/` directory read-write, set `HOME=/pi-home`, and align container UID/GID with the host user. See [docs/specialists-service.md](docs/specialists-service.md), [docs/specialists-service-install.md](docs/specialists-service-install.md), and [docs/deploying-alongside.md](docs/deploying-alongside.md).
|
|
97
181
|
|
|
98
|
-
|
|
182
|
+
## Documentation map
|
|
99
183
|
|
|
100
184
|
| Need | Doc |
|
|
101
185
|
|---|---|
|
|
102
|
-
| Install and
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
| Run a script-class specialist over HTTP (`sp serve`) — overview & contract | [docs/specialists-service.md](docs/specialists-service.md) |
|
|
106
|
-
| Install `sp serve` in another project (sidecar Docker / Podman) | [docs/specialists-service-install.md](docs/specialists-service-install.md) |
|
|
107
|
-
| Build & publish the specialists-service image | [docs/release-image.md](docs/release-image.md) |
|
|
108
|
-
| Release flow (skill + specialist) | [config/skills/releasing/SKILL.md](config/skills/releasing/SKILL.md) |
|
|
109
|
-
| Bead-first workflow and semantics | [docs/workflow.md](docs/workflow.md) |
|
|
186
|
+
| Install, update, and distribution model | [docs/installation.md](docs/installation.md) |
|
|
187
|
+
| Project bootstrap and `sp init` | [docs/bootstrap.md](docs/bootstrap.md) |
|
|
188
|
+
| Bead-first workflow | [docs/workflow.md](docs/workflow.md) |
|
|
110
189
|
| CLI commands and flags | [docs/cli-reference.md](docs/cli-reference.md) |
|
|
111
|
-
| Background jobs
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
190
|
+
| Background jobs / `ps` / `feed` / `result` | [docs/background-jobs.md](docs/background-jobs.md) |
|
|
191
|
+
| Specialist JSON authoring | [docs/authoring.md](docs/authoring.md) |
|
|
192
|
+
| Built-in specialists | [docs/specialists-catalog.md](docs/specialists-catalog.md) |
|
|
193
|
+
| Tool catalog and permission resolver | [docs/manifest.md](docs/manifest.md) |
|
|
194
|
+
| MCP registration and tool surface | [docs/mcp-servers.md](docs/mcp-servers.md), [docs/mcp-tools.md](docs/mcp-tools.md) |
|
|
195
|
+
| Hooks | [docs/hooks.md](docs/hooks.md) |
|
|
196
|
+
| Skills | [docs/skills.md](docs/skills.md) |
|
|
197
|
+
| Worktrees and session close | [docs/worktrees.md](docs/worktrees.md), [docs/worktree.md](docs/worktree.md) |
|
|
198
|
+
| Runtime architecture | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |
|
|
199
|
+
| Pi subprocess isolation / RPC boundary | [docs/pi-session.md](docs/pi-session.md), [docs/pi-rpc-boundary.md](docs/pi-rpc-boundary.md) |
|
|
200
|
+
| NodeSupervisor | [docs/nodes.md](docs/nodes.md) |
|
|
201
|
+
| Service sidecar / HTTP contract | [docs/specialists-service.md](docs/specialists-service.md) |
|
|
202
|
+
| Compose deployment recipe | [docs/deploying-alongside.md](docs/deploying-alongside.md) |
|
|
203
|
+
| Release notes | [CHANGELOG.md](CHANGELOG.md) |
|
|
125
204
|
|
|
126
205
|
## Project structure
|
|
127
206
|
|
|
128
207
|
```text
|
|
129
208
|
config/
|
|
130
|
-
├── specialists/ canonical specialist definitions (.specialist.json)
|
|
131
|
-
├── mandatory-rules/ canonical rule sets injected into specialist prompts
|
|
132
|
-
├──
|
|
209
|
+
├── specialists/ package-canonical specialist definitions (.specialist.json)
|
|
210
|
+
├── mandatory-rules/ package-canonical rule sets injected into specialist prompts
|
|
211
|
+
├── catalog/ package-canonical tool catalog
|
|
212
|
+
├── nodes/ package-canonical node configs
|
|
133
213
|
├── hooks/ bundled hook scripts
|
|
134
|
-
|
|
135
|
-
|
|
214
|
+
└── skills/ repo-local skills shipped by this package
|
|
215
|
+
|
|
136
216
|
.specialists/
|
|
137
|
-
├──
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
└── ready/ runtime — gitignored
|
|
150
|
-
src/ CLI, server, loader, runner, tools
|
|
217
|
+
├── user/ repo-owned specialists and overrides (highest precedence)
|
|
218
|
+
├── default/ optional pins / compatibility snapshots; prune stale files
|
|
219
|
+
├── mandatory-rules/ legacy/repo rule overlay compatibility
|
|
220
|
+
├── db/ runtime SQLite state (gitignored)
|
|
221
|
+
├── jobs/ legacy runtime mirror (gitignored)
|
|
222
|
+
└── ready/ legacy ready markers (gitignored)
|
|
223
|
+
|
|
224
|
+
.xtrm/
|
|
225
|
+
├── skills/ xtrm-managed skill snapshots and active links
|
|
226
|
+
└── hooks/ xtrm-managed hook snapshots
|
|
227
|
+
|
|
228
|
+
src/ CLI, server, loader, runner, supervisor, MCP tool
|
|
151
229
|
```
|
|
152
230
|
|
|
153
|
-
## Core
|
|
231
|
+
## Core rules
|
|
154
232
|
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
- `--
|
|
158
|
-
- `--
|
|
159
|
-
-
|
|
233
|
+
- Use `--bead` for tracked work; use `--prompt` only for quick untracked work.
|
|
234
|
+
- `--context-depth` controls completed dependency context injection; default is 3 for bead runs.
|
|
235
|
+
- `--no-beads` disables tracking bead creation/updates, but it does not disable reading the input bead when `--bead` is provided.
|
|
236
|
+
- Edit-capable specialists run in isolated worktrees. Review/fix passes should use `--job <exec-job>` to reuse the same workspace.
|
|
237
|
+
- Reviewer PASS is the publish gate. Code-sanity/security/test-runner outputs are advisory evidence, not merge approval.
|
|
238
|
+
- Specialists are project-scoped. User-scope specialist discovery is deprecated.
|
|
160
239
|
|
|
161
240
|
## Deprecated commands
|
|
162
241
|
|
|
@@ -164,8 +243,9 @@ These commands are still recognized for migration guidance but are no longer onb
|
|
|
164
243
|
|
|
165
244
|
- `specialists setup`
|
|
166
245
|
- `specialists install`
|
|
246
|
+
- `sp release prepare` / `sp release publish` (deprecated aliases; release flow is skill-driven)
|
|
167
247
|
|
|
168
|
-
Use `
|
|
248
|
+
Use `sp init`, `xt update`, and the release skill flow instead.
|
|
169
249
|
|
|
170
250
|
## Development
|
|
171
251
|
|
|
@@ -173,12 +253,10 @@ Use `specialists init` instead.
|
|
|
173
253
|
bun run build
|
|
174
254
|
bun test # bun vitest run (default)
|
|
175
255
|
bun run test:node # node vitest run (subprocess-safe alternative)
|
|
176
|
-
|
|
177
|
-
|
|
256
|
+
sp help
|
|
257
|
+
sp quickstart
|
|
178
258
|
```
|
|
179
259
|
|
|
180
|
-
`test:node` uses plain `node vitest run` as an alternative to `bun --bun vitest`. Useful for executor/codex subprocess chains that may trigger stall detection during vitest's tinypool worker initialization silence.
|
|
181
|
-
|
|
182
260
|
## License
|
|
183
261
|
|
|
184
|
-
MIT
|
|
262
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -7,7 +7,7 @@ description: >
|
|
|
7
7
|
security checks, multi-step chains, integration-phase reconciliation,
|
|
8
8
|
debugger-restitch on conflicting chains, pre-dispatch conflict-cluster
|
|
9
9
|
mapping, test-failure-map epics, and questions about specialist workflow.
|
|
10
|
-
version: 3.
|
|
10
|
+
version: 3.4
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Using Specialists v3
|
|
@@ -279,24 +279,75 @@ Fix three bad smells fast:
|
|
|
279
279
|
|
|
280
280
|
What differs: orchestrator writes contract before dispatch, so specialist does less guessing and more useful work.
|
|
281
281
|
|
|
282
|
-
## Dependency Linking
|
|
282
|
+
## Dependency Linking And Relationship Vocabulary
|
|
283
283
|
|
|
284
|
-
Link beads with correct edge shape. The edge tells orchestrator what blocks
|
|
284
|
+
Link beads with correct edge shape. The edge tells orchestrator what blocks execution, what only preserves context, which bead verifies another, and which issue has been replaced. Do not overload `blocks` for follow-ups, root-cause links, verification pairs, duplicates, or restitch replacements.
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
- `bd dep
|
|
289
|
-
- `bd
|
|
290
|
-
- `bd
|
|
286
|
+
Core commands:
|
|
287
|
+
|
|
288
|
+
- `bd dep add <issue> <depends-on>`: issue depends on depends-on; depends-on blocks issue. Default type is `blocks`. Use only for hard sequencing. [source: bd dep add --help]
|
|
289
|
+
- `bd dep <blocker> --blocks <blocked>`: reverse phrasing of the same hard sequencing edge. [source: bd dep --help]
|
|
290
|
+
- `bd dep add <issue> <other> --type <type>`: store a typed relationship. Supported types: `blocks`, `tracks`, `related`, `parent-child`, `discovered-from`, `until`, `caused-by`, `validates`, `relates-to`, `supersedes`. [source: bd dep add --help]
|
|
291
|
+
- `bd dep relate <a> <b>` / `bd dep unrelate <a> <b>`: bidirectional non-blocking `relates_to` link. Use for context, not order. [source: bd dep --help]
|
|
292
|
+
- `bd create --parent <epic-id>`: epic-child edge; auto-names child `.1`, `.2`, … and adds parent ownership. Use for chain members that must live under an epic. [source: bd create --help]
|
|
293
|
+
- `bd create --deps discovered-from:<id>` or `bd dep add <new> <source> --type discovered-from`: follow-up work discovered from a source bead.
|
|
294
|
+
- `bd duplicate <new> --of <canonical>`: close duplicate issue and point at canonical. Use when two beads describe the same required work.
|
|
295
|
+
- `bd duplicates` / `bd find-duplicates --status open --method ai --json`: find exact or semantic duplicates before dispatching parallel chains.
|
|
296
|
+
- `bd supersede <old> --with <new>` or `bd dep add <new> <old> --type supersedes`: mark a replacement when a better-scoped fix bead replaces an obsolete/abandoned one.
|
|
297
|
+
- `bd dep cycles`, `bd dep tree <id>`, and `bd graph <id>`: sanity-check the execution graph before merge/publication.
|
|
298
|
+
|
|
299
|
+
Relationship vocabulary for specialist chains:
|
|
300
|
+
|
|
301
|
+
| Relationship | Reach for it when | Example command |
|
|
302
|
+
| --- | --- | --- |
|
|
303
|
+
| `blocks` | Hard must-happen-before sequencing: planner before executor, implementation before reviewer, restitch before publish. | `bd dep add <impl> <plan> --type blocks` |
|
|
304
|
+
| `tracks` | A local bead mirrors upstream or cross-project work whose status matters but is not owned here. | `bd dep add <local> external:xtrm-tools:<capability> --type tracks` |
|
|
305
|
+
| `related` | Loose topical association when no direction or scheduling effect is intended. Prefer `bd dep relate` for bidirectional relation. | `bd dep add <a> <b> --type related` |
|
|
306
|
+
| `parent-child` | Epic owns child chains. Prefer `bd create --parent <epic>` so IDs and parentage stay canonical. | `bd create --parent <epic> --title "Impl auth retry" ...` |
|
|
307
|
+
| `discovered-from` | Reviewer, debugger, explorer, or test-runner surfaces new follow-up work from a run. | `bd dep add <follow-up> <reviewer-bead> --type discovered-from` |
|
|
308
|
+
| `until` | Time-bounded or event-bounded precondition that blocks only until a stated condition lands. | `bd dep add <chain> <precondition> --type until` |
|
|
309
|
+
| `caused-by` | Failure bead points to the root-cause bead/cluster that explains it. Makes test-failure-map epics navigable. | `bd dep add <failing-test> <root-cause> --type caused-by` |
|
|
310
|
+
| `validates` | Reviewer, test-runner, code-sanity, or security-auditor bead verifies an implementation/debugger bead. | `bd dep add <review> <impl> --type validates` |
|
|
311
|
+
| `relates-to` | Bidirectional context edge for conflict clusters, sibling designs, or rebuttal patterns. Prefer dedicated relate command. | `bd dep relate <chain-a> <chain-b>` |
|
|
312
|
+
| `supersedes` | New fix/design/restitch bead replaces an older bead that should no longer be executed or merged. Prefer `bd supersede`. | `bd supersede <old> --with <new>` |
|
|
313
|
+
|
|
314
|
+
Worked high-value patterns:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Reviewer discovers a separate follow-up during review. Do not block the impl.
|
|
318
|
+
bd create --title "Follow up: tighten retry metrics" --type task --priority 3 --description "..."
|
|
319
|
+
bd dep add <follow-up> <review> --type discovered-from
|
|
320
|
+
|
|
321
|
+
# Test-failure-map root cause: many failures point at one underlying issue.
|
|
322
|
+
bd create --title "Root cause: stale fixture factory" --type bug --priority 2 --description "..."
|
|
323
|
+
bd dep add <failing-test-bead> <root-cause> --type caused-by
|
|
324
|
+
|
|
325
|
+
# Verification bead validates implementation. This is not a hard prerequisite edge.
|
|
326
|
+
bd dep add <test-runner-bead> <impl> --type validates
|
|
327
|
+
bd dep add <reviewer-bead> <impl> --type validates
|
|
328
|
+
|
|
329
|
+
# Replacement bead supersedes an abandoned or wrongly scoped implementation.
|
|
330
|
+
bd create --title "Restitch auth retry onto integration state" --type task --priority 2 --description "..."
|
|
331
|
+
bd supersede <old-impl> --with <restitch>
|
|
332
|
+
|
|
333
|
+
# Before merging an epic or integration branch, prove the graph is sane.
|
|
334
|
+
bd dep cycles
|
|
335
|
+
bd graph <epic> --compact
|
|
336
|
+
```
|
|
291
337
|
|
|
292
338
|
Use each form for a different reason:
|
|
293
339
|
|
|
294
|
-
- `
|
|
295
|
-
- `
|
|
296
|
-
-
|
|
297
|
-
- `
|
|
340
|
+
- `blocks` / `--blocks` for must-happen-before dependency only.
|
|
341
|
+
- `validates` for review, test, sanity, and security evidence.
|
|
342
|
+
- `discovered-from` for spawned follow-up beads.
|
|
343
|
+
- `caused-by` for failure-to-root-cause attribution.
|
|
344
|
+
- `relates-to` / `bd dep relate` for soft linkage with no schedule effect.
|
|
345
|
+
- `parent-child` / `--parent` for epic ownership and child naming.
|
|
346
|
+
- `supersedes` / `bd supersede` for replacement work; `duplicate` for same-work issues.
|
|
347
|
+
|
|
348
|
+
Cross-repo consistency: keep this vocabulary aligned with the xtrm-tools triaging skill and sibling triage bead `xtrm-drkk`; both should use the same relationship names when rewiring issue graphs.
|
|
298
349
|
|
|
299
|
-
What differs: orchestrator chooses edge type deliberately, so graph stays correct for chain execution, epic publish, and follow-up traceability.
|
|
350
|
+
What differs: orchestrator chooses edge type deliberately, so graph stays correct for chain execution, epic publish, duplicate cleanup, root-cause navigation, verification evidence, and follow-up traceability.
|
|
300
351
|
|
|
301
352
|
## Bead Contract By Bead Type
|
|
302
353
|
|
|
@@ -537,11 +588,25 @@ Before dispatching N parallel chains, build the file-overlap matrix:
|
|
|
537
588
|
|
|
538
589
|
For each cluster of overlapping chains, choose **one** of:
|
|
539
590
|
|
|
540
|
-
1. **Serial dispatch** — execute chains in dependency order, each waits for previous to land. Slowest but cleanest.
|
|
541
|
-
2. **Unified bead** — collapse all chains into one bead/executor pass. Larger reviewer scope but no merge conflicts.
|
|
542
|
-
3. **Parallel dispatch + debugger restitch at integration** — dispatch in parallel, plan for ~40% conflict rate (empirical), budget debugger-restitch passes during integration.
|
|
591
|
+
1. **Serial dispatch** — execute chains in dependency order, each waits for previous to land. Slowest but cleanest. Encode the order with `blocks`, not notes.
|
|
592
|
+
2. **Unified bead** — collapse all chains into one bead/executor pass. Larger reviewer scope but no merge conflicts. Mark obsolete split beads with `bd supersede <old> --with <unified>`.
|
|
593
|
+
3. **Parallel dispatch + debugger restitch at integration** — dispatch in parallel, plan for ~40% conflict rate (empirical), budget debugger-restitch passes during integration. Link overlapping siblings with `bd dep relate <chain-a> <chain-b>` so the future restitch has visible context without creating fake blockers.
|
|
594
|
+
|
|
595
|
+
Example graph rewiring:
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
# soft conflict-cluster context; does not change schedule
|
|
599
|
+
bd dep relate <chain-a> <chain-b>
|
|
600
|
+
|
|
601
|
+
# serializing because both chains edit src/cli/update.ts
|
|
602
|
+
bd dep add <chain-b> <chain-a> --type blocks
|
|
603
|
+
|
|
604
|
+
# replacing scattered duplicate/split beads with one unified implementation
|
|
605
|
+
bd supersede <old-chain-a> --with <unified-chain>
|
|
606
|
+
bd supersede <old-chain-b> --with <unified-chain>
|
|
607
|
+
```
|
|
543
608
|
|
|
544
|
-
Default heuristic: if 3+ chains touch the same file, **serial-dispatch them**. Conflict-resolution time at integration usually exceeds the time saved by parallel dispatch.
|
|
609
|
+
Default heuristic: if 3+ chains touch the same file, **serial-dispatch them**. Conflict-resolution time at integration usually exceeds the time saved by parallel dispatch. Run `bd find-duplicates --status open --method ai --json` before launching a large wave; merge or supersede duplicate work before specialists spend tokens on it.
|
|
545
610
|
|
|
546
611
|
## Pre-Epic: Test-Failure-Map Pattern
|
|
547
612
|
|
|
@@ -560,11 +625,17 @@ Use when:
|
|
|
560
625
|
- `CONSTRAINTS:` READ_ONLY, no source/test edits, no fix attempts.
|
|
561
626
|
3. **Dispatch test-runner / explorer / debugger** for this bead READ_ONLY (or fill inline by reading the log).
|
|
562
627
|
4. **Build the cluster table**: cluster name | files (counts) | representative error | root-cause hypothesis | likely-owner area | targeted validation command. Save in bead notes.
|
|
563
|
-
5. **
|
|
628
|
+
5. **Wire root-cause relationships** so the graph is navigable:
|
|
629
|
+
```bash
|
|
630
|
+
bd dep add <failure-cluster-bead> <root-cause-bead> --type caused-by
|
|
631
|
+
bd dep add <test-runner-bead> <fix-bead> --type validates
|
|
632
|
+
```
|
|
633
|
+
Use `caused-by` for attribution, not `blocks`; use `validates` for the evidence-producing test bead.
|
|
634
|
+
6. **Plan fix chains** off the cluster table:
|
|
564
635
|
- One chain per cluster, file scopes disjoint where possible.
|
|
565
636
|
- Order by leverage (largest cluster first), then by simplicity.
|
|
566
637
|
- Debugger when root cause unclear; executor when bead constraint is concrete.
|
|
567
|
-
|
|
638
|
+
7. **Save the topology insight as `bd remember`** — patterns about where a codebase's test fragility concentrates are reusable.
|
|
568
639
|
|
|
569
640
|
### Why this beats dispatch-blind
|
|
570
641
|
|
|
@@ -587,26 +658,28 @@ bd update <task> --claim
|
|
|
587
658
|
|
|
588
659
|
# 2. Optional discovery when path is unknown
|
|
589
660
|
bd create --title "Explore auth refresh path" --type task --priority 2 --description "PROBLEM: token refresh retry path is undocumented and likely drifts on failure handling. SUCCESS: evidence-backed plan names exact files, symbols, and risk. SCOPE: src/auth/refresh.ts, src/cli/login.ts, tests/unit/auth/*.test.ts. NON_GOALS: no implementation, no broad audit. CONSTRAINTS: READ_ONLY, cite files/symbols/flows, stay within live repo evidence. VALIDATION: findings cite code path and recommended sequence. OUTPUT: tracked discovery plan with stop condition."
|
|
590
|
-
bd dep add <explore> <task>
|
|
661
|
+
bd dep add <explore> <task> --type discovered-from
|
|
591
662
|
specialists run explorer --bead <explore> --context-depth 3
|
|
592
663
|
specialists result <explore-job>
|
|
593
664
|
|
|
594
665
|
# 3. Implementation
|
|
595
666
|
bd create --title "Implement token refresh retry" --type task --priority 2 --description "PROBLEM: login fails after transient token refresh error because retry path returns before backoff and clear error state. SUCCESS: retry waits once, preserves session on success, and surfaces final failure clearly. SCOPE: src/auth/refresh.ts, src/cli/login.ts, tests/unit/auth/refresh.test.ts. NON_GOALS: no auth redesign, no storage migration, no UI refresh. CONSTRAINTS: preserve existing token format, keep backward-compatible error text, avoid broad retry changes elsewhere. VALIDATION: add regression test for transient failure then success; run targeted auth tests. OUTPUT: changed files, test evidence, residual risks."
|
|
596
|
-
bd dep add <impl> <explore-or-task>
|
|
667
|
+
bd dep add <impl> <explore-or-task> --type blocks
|
|
597
668
|
specialists run executor --bead <impl> --context-depth 3
|
|
598
669
|
specialists result <exec-job>
|
|
599
670
|
|
|
600
671
|
# 4. Advisory passes when diff smells risky
|
|
601
672
|
bd create --title "Sanity check token retry diff" --type task --priority 2 --description "PROBLEM: auth retry diff has control-flow and state-handling smell that could hide bug. SUCCESS: findings identify concrete simplification or confirm clean shape. SCOPE: executor diff in auth refresh and login flow. NON_GOALS: no edits, no merge gate decision. CONSTRAINTS: READ_ONLY, keep feedback cheap, cite exact lines or symbols. VALIDATION: findings name concrete improvement or say OK. OUTPUT: FINDINGS with severity or OK with caveats."
|
|
673
|
+
bd dep add <sanity-bead> <impl> --type validates
|
|
602
674
|
specialists run code-sanity --bead <sanity-bead> --job <exec-job> --context-depth 3
|
|
603
675
|
|
|
604
676
|
bd create --title "Security scan token retry diff" --type task --priority 2 --description "PROBLEM: auth refresh code touches secrets and session handling, so security regression is possible. SUCCESS: findings isolate real risk surface or confirm no obvious issue. SCOPE: executor diff in auth, token storage, and login path. NON_GOALS: no edits, no package updates, no destructive scans, no live exploit tests. CONSTRAINTS: LOW permissions, scan-only, recommendations only. VALIDATION: findings cite auth/secrets/input surface and why it matters. OUTPUT: recommendations for executor to apply in separate bead."
|
|
677
|
+
bd dep add <security-bead> <impl> --type validates
|
|
605
678
|
specialists run security-auditor --bead <security-bead> --job <exec-job> --context-depth 3
|
|
606
679
|
|
|
607
680
|
# 5. Final review
|
|
608
681
|
bd create --title "Review token refresh retry" --type task --priority 2 --description "PROBLEM: verify executor output against auth retry requirements. SUCCESS: PASS only if retry behavior, error handling, and tests satisfy contract. SCOPE: executor job, diff, acceptance criteria, and target auth files. NON_GOALS: do not rewrite unless explicitly asked. CONSTRAINTS: code-review mindset; findings first; verify security and sanity findings were handled. VALIDATION: inspect targeted checks and regression coverage. OUTPUT: PASS/PARTIAL/FAIL with file/line findings."
|
|
609
|
-
bd dep add <review> <impl>
|
|
682
|
+
bd dep add <review> <impl> --type validates
|
|
610
683
|
specialists run reviewer --bead <review> --job <exec-job> --context-depth 3
|
|
611
684
|
specialists result <review-job>
|
|
612
685
|
|
|
@@ -621,7 +694,7 @@ sp merge <impl>
|
|
|
621
694
|
bd close <task> --reason "Reviewer PASS; merged."
|
|
622
695
|
```
|
|
623
696
|
|
|
624
|
-
Edit-capable specialists with `--bead` auto-provision a worktree. `--worktree` is accepted for clarity but usually unnecessary. Use `--job <exec-job>` for reviewer/fix passes that must enter existing executor workspace.
|
|
697
|
+
Edit-capable specialists with `--bead` auto-provision a clean git worktree. This does **not** provision ignored project dependency artifacts (`node_modules/`, `.venv/`, build caches). If validation tools are missing inside that worktree, have the specialist run the repo's standard bootstrap command (`make bootstrap`, `just setup`, `npm ci`, `uv sync`, etc.) or report that bootstrap is required; do not solve it by tracking dependency directories. `--worktree` is accepted for clarity but usually unnecessary. Use `--job <exec-job>` for reviewer/fix passes that must enter existing executor workspace.
|
|
625
698
|
|
|
626
699
|
What differs: orchestrator carries full bead contract inline, so downstream specialists inherit the actual job shape, not a title.
|
|
627
700
|
|
|
@@ -634,8 +707,7 @@ Use epic when multiple implementation chains publish together.
|
|
|
634
707
|
bd create --title "Epic: auth refresh hardening" --type epic --priority 2 --description "PROBLEM: login and refresh flow have retry drift, weak error surfacing, and unclear follow-up ownership. SUCCESS: epic closes with stable retry behavior, tests, docs, and clean publish. SCOPE: src/auth/*, src/cli/login.ts, tests/unit/auth/*, docs/auth-refresh.md. NON_GOALS: no auth provider swap, no storage migration, no unrelated session revamp. CONSTRAINTS: preserve token format, keep login compatible, sequence risky fixes before merge, use child beads for parallelizable slices. VALIDATION: targeted tests, code-sanity or security pass if risk appears, final reviewer PASS. OUTPUT: merged chain set with notes on remaining gaps."
|
|
635
708
|
|
|
636
709
|
# Planner bead
|
|
637
|
-
bd create --title "Plan auth refresh split" --type task --priority 2 --description "PROBLEM: epic needs disjoint chains before executor starts. SUCCESS: child beads, dependency edges, and file ownership split are explicit. SCOPE: auth refresh epic area. NON_GOALS: no code changes. CONSTRAINTS: keep chains disjoint, identify security-sensitive slice, name review order. VALIDATION: plan names beads and edges. OUTPUT: parallel-ready plan with risk notes."
|
|
638
|
-
bd dep add <plan> <epic>
|
|
710
|
+
bd create --parent <epic> --title "Plan auth refresh split" --type task --priority 2 --description "PROBLEM: epic needs disjoint chains before executor starts. SUCCESS: child beads, dependency edges, and file ownership split are explicit. SCOPE: auth refresh epic area. NON_GOALS: no code changes. CONSTRAINTS: keep chains disjoint, identify security-sensitive slice, name review order. VALIDATION: plan names beads and edges. OUTPUT: parallel-ready plan with risk notes."
|
|
639
711
|
specialists run planner --bead <plan> --context-depth 3
|
|
640
712
|
|
|
641
713
|
# Parallel impl beads
|
|
@@ -646,6 +718,8 @@ specialists run executor --bead <impl-a> --context-depth 3
|
|
|
646
718
|
specialists run executor --bead <impl-b> --context-depth 3
|
|
647
719
|
|
|
648
720
|
# Per-chain review
|
|
721
|
+
bd dep add <review-a> <impl-a> --type validates
|
|
722
|
+
bd dep add <review-b> <impl-b> --type validates
|
|
649
723
|
specialists run reviewer --bead <review-a> --job <exec-a-job> --context-depth 3
|
|
650
724
|
specialists run reviewer --bead <review-b> --job <exec-b-job> --context-depth 3
|
|
651
725
|
|
|
@@ -655,6 +729,7 @@ sp finalize <review-a-job>
|
|
|
655
729
|
sp finalize <review-b-job>
|
|
656
730
|
|
|
657
731
|
# Publish
|
|
732
|
+
bd dep cycles # stop if relationship rewiring introduced a cycle
|
|
658
733
|
sp epic status <epic> # verify derived state shows merge_ready
|
|
659
734
|
sp epic merge <epic> # batch publish all chains in dependency order with tsc gate per merge
|
|
660
735
|
```
|
|
@@ -675,7 +750,7 @@ reviewer -> PASS | PARTIAL | FAIL
|
|
|
675
750
|
|
|
676
751
|
- `PASS`: verify expected commit/diff. If reviewer's PASS appeared in its streaming output, auto-finalize already closed the chain — go straight to `sp merge` / `sp epic merge`. If PASS arrived via `sp resume`, run `sp finalize <any-chain-job-id>` first to cascade-close any waiting keep-alive members, then publish.
|
|
677
752
|
- `PARTIAL`: resume same executor/debugger with exact findings, then re-review (`sp resume <reviewer-job>`).
|
|
678
|
-
- `FAIL`: stop and decide whether to replace chain, re-scope bead, or ask operator if judgment is required.
|
|
753
|
+
- `FAIL`: stop and decide whether to replace chain, re-scope bead, or ask operator if judgment is required. If replacing a bad chain with a narrower one, use `bd supersede <failed-impl> --with <replacement>`; if reviewer discovered separate follow-up work, use `bd dep add <follow-up> <reviewer-bead> --type discovered-from`.
|
|
679
754
|
|
|
680
755
|
Prefer resume over new fix executor when original job is waiting and context is healthy:
|
|
681
756
|
|
|
@@ -764,8 +839,8 @@ Several specialists default to over-cautious verdicts when an evidence gate look
|
|
|
764
839
|
### Overthinker
|
|
765
840
|
|
|
766
841
|
- "Hold for operator decision" without specifying what decision is needed → push: "Cite file/line evidence for why this is a product decision rather than a mechanical resolution."
|
|
767
|
-
- "Close as superseded by X" without verification → push: "Read the current state of `<file>` and check whether feature Y from this bead is actually present."
|
|
768
|
-
- "Run separate small beads" or "run one big bead" without rationale → push: "Pick one and explain operationally — cost difference, conflict expectations, reviewer scope."
|
|
842
|
+
- "Close as superseded by X" without verification → push: "Read the current state of `<file>` and check whether feature Y from this bead is actually present." If verified, record it structurally with `bd supersede <old> --with <new>` instead of burying the replacement in notes.
|
|
843
|
+
- "Run separate small beads" or "run one big bead" without rationale → push: "Pick one and explain operationally — cost difference, conflict expectations, reviewer scope." If one big bead wins, mark replaced split beads with `bd supersede`; if the small beads remain parallel siblings, link overlap with `bd dep relate`, not `blocks`.
|
|
769
844
|
|
|
770
845
|
### Reviewer
|
|
771
846
|
|
|
@@ -891,6 +966,7 @@ sp merge <chain-root-bead>
|
|
|
891
966
|
Batch publish all chains in an epic in dependency order with tsc gate between each:
|
|
892
967
|
|
|
893
968
|
```bash
|
|
969
|
+
bd dep cycles
|
|
894
970
|
sp epic status <epic-id>
|
|
895
971
|
sp epic merge <epic-id>
|
|
896
972
|
```
|
|
@@ -922,11 +998,12 @@ Use when `sp merge` / `sp epic merge` is not the right path: chains forked from
|
|
|
922
998
|
3. For each non-overlapping chain (security/critical first, then test-baseline, then features):
|
|
923
999
|
- `git merge --squash <chain-branch>`
|
|
924
1000
|
- Restore noise files (see "Chain noise filter checklist" below)
|
|
925
|
-
- **Advisory passes** before commit: if the staged diff smells overcomplicated/duplicative/type-risky, dispatch `code-sanity --job <last-exec-job-of-chain>`; if it touches auth/secrets/input/agent-config, dispatch `security-auditor --job <last-exec-job-of-chain>`. Apply findings or document why skipped.
|
|
1001
|
+
- **Advisory passes** before commit: if the staged diff smells overcomplicated/duplicative/type-risky, dispatch `code-sanity --job <last-exec-job-of-chain>`; if it touches auth/secrets/input/agent-config, dispatch `security-auditor --job <last-exec-job-of-chain>`. Link those beads with `bd dep add <advisory-bead> <chain-bead> --type validates`. Apply findings or document why skipped.
|
|
926
1002
|
- `git commit -m "<type>(<scope>): <summary> (<bead-id>)"` — one squash commit per chain.
|
|
927
|
-
4. For each overlapping chain, switch to the **debugger-restitch** pattern (next section).
|
|
928
|
-
5.
|
|
929
|
-
6.
|
|
1003
|
+
4. For each overlapping chain, add `bd dep relate <overlap-a> <overlap-b>` if not already linked, then switch to the **debugger-restitch** pattern (next section).
|
|
1004
|
+
5. Before publication, run `bd dep cycles`; fix any accidental cycle before `sp epic merge` or operator FF-merge.
|
|
1005
|
+
6. After all chains land, run E2E smoke phase (below) before declaring done.
|
|
1006
|
+
7. Operator FF-merges integration → main when satisfied.
|
|
930
1007
|
|
|
931
1008
|
### Chain noise filter checklist
|
|
932
1009
|
|
|
@@ -950,7 +1027,7 @@ If a chain commits its own `.beads` symlink (older bd-in-worktree behavior), `rm
|
|
|
950
1027
|
|
|
951
1028
|
When chain X conflicts with already-landed chain Y on shared files, raw `git cherry-pick` will revert Y's work. The debugger-restitch pattern preserves both, but only when the debugger gets an explicit "preserve already-landed work" contract.
|
|
952
1029
|
|
|
953
|
-
1. **Reopen X**: `bd reopen <X> --reason="integration stitch onto post-Y state"`.
|
|
1030
|
+
1. **Reopen X**: `bd reopen <X> --reason="integration stitch onto post-Y state"`. If the old X chain is no longer publishable, create a restitch bead and mark replacement explicitly: `bd supersede <X> --with <X-restitch>`. Link X and Y with `bd dep relate <X-restitch> <Y>` for conflict context; use `caused-by` only when a concrete failure bead is attributable to Y's already-landed change.
|
|
954
1031
|
2. **Strengthen the bead contract** with these fields:
|
|
955
1032
|
- `## CRITICAL CONSTRAINTS:` heading at the top.
|
|
956
1033
|
- "Fork off `integration/<date>-orchestrator`. Verify with `git log integration/...$..HEAD` empty before any commits."
|
|
@@ -969,13 +1046,13 @@ When chain X conflicts with already-landed chain Y on shared files, raw `git che
|
|
|
969
1046
|
git diff integration/<date>...feature/<X>-debugger -- <key-files>
|
|
970
1047
|
```
|
|
971
1048
|
Confirm the debugger's diff is **additive** — no reverts of Y's lines.
|
|
972
|
-
5. **Advisory passes**: before landing the restitch, dispatch `code-sanity --job <debugger-job>` if the restitch added control-flow complexity, and `security-auditor --job <debugger-job>` if it touched a sensitive surface. Restitched diffs are higher-risk than fresh executor diffs because the debugger had to thread around already-landed work.
|
|
1049
|
+
5. **Advisory passes**: before landing the restitch, dispatch `code-sanity --job <debugger-job>` if the restitch added control-flow complexity, and `security-auditor --job <debugger-job>` if it touched a sensitive surface. Link each advisory bead back with `bd dep add <advisory> <X-restitch-or-X> --type validates`. Restitched diffs are higher-risk than fresh executor diffs because the debugger had to thread around already-landed work.
|
|
973
1050
|
6. **Land via FF or cherry-pick the named commit** (NOT the checkpoint commit). Look for the commit with the proper `<type>(<scope>):` message; ignore `checkpoint(debugger):` commits above it.
|
|
974
1051
|
7. **Verify tests** before marking done.
|
|
975
1052
|
|
|
976
1053
|
### Failure mode to watch for
|
|
977
1054
|
|
|
978
|
-
If the debugger forks off the OLD baseline (pre-Y) instead of integration, its commit will revert Y. Symptom: `git diff integration..feature/<X>-debugger -- <Y's-file>` shows DELETIONS of Y's symbols. Fix: resume the debugger with explicit "cd to a fresh worktree forked from `integration/<date>-orchestrator`" instruction. Re-verify with `git log integration..HEAD` empty.
|
|
1055
|
+
If the debugger forks off the OLD baseline (pre-Y) instead of integration, its commit will revert Y. Symptom: `git diff integration..feature/<X>-debugger -- <Y's-file>` shows DELETIONS of Y's symbols. Fix: resume the debugger with explicit "cd to a fresh worktree forked from `integration/<date>-orchestrator`" instruction. Re-verify with `git log integration..HEAD` empty. If the bad restitch became a tracked bead, supersede it with the corrected restitch bead so nobody merges the obsolete chain.
|
|
979
1056
|
|
|
980
1057
|
## E2E Smoke Phase
|
|
981
1058
|
|
|
@@ -1049,6 +1126,7 @@ Then choose one action:
|
|
|
1049
1126
|
| `sp merge` refuses with "non-terminal chain jobs" after reviewer PASS | Auto-finalize did not fire (PASS arrived via `sp resume`, not streaming) | `sp finalize <any-chain-job-id>` — cascades to close every waiting keep-alive member |
|
|
1050
1127
|
| `sp epic merge` says epic is "in terminal state 'failed'" | Prior `sp epic merge` hit a transient error (rebase conflict, dirty worktree) and persisted a soft `failed` marker | Clear the original conflict source, then re-run `sp epic merge` — it retries fresh, only `merged`/`abandoned` truly block |
|
|
1051
1128
|
| `sp epic merge` says "rebase failed: unstaged changes" in a worktree | bd auto-export or other tooling left uncommitted changes inside the worktree | `cd .worktrees/<bead>/<bead>-executor && git stash push -u -m epic-merge-prep`, then re-run from main repo |
|
|
1129
|
+
| Validation fails with `command not found`, `vitest: not found`, missing Python tools, or `ERR_MODULE_NOT_FOUND` in a fresh worktree | Normal git worktree behavior: ignored dependency dirs (`node_modules/`, `.venv/`) are not copied into new worktrees | Run the repo's standard bootstrap inside that worktree (`make bootstrap`, `just setup`, `npm ci`, `uv sync`, etc.) or report bootstrap-required. Do not track dependency artifacts. |
|
|
1052
1130
|
| `sp ps` shows old terminal jobs after a session | Default dashboard keeps unresolved terminal problems visible until acknowledged | `sp clean --ps --dry-run`, then `sp clean --ps` to soft-hide from default ps; use `sp ps --include-cleaned`/`--all` for audit history |
|
|
1053
1131
|
| Reviewer keeps returning PARTIAL on functional contracts already met | Reviewer demanding tool-event evidence — typically obsoleted after the gate relaxation, but if it persists check the executor's `gitnexus_detect_changes` ran and use the rebuttal pattern (see Specialist Rebuttal As Routine) | Rebut with cited evidence; second FAIL = escalate |
|
|
1054
1132
|
| Multiple `sp run` background launches drop silently under shell parallelism | Known launch-ceremony race | Re-check `sp ps` after each dispatch and retry the missing one; serialize when reliability matters |
|
package/dist/asset-contract.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0.0",
|
|
3
|
-
"package_version": "3.15.
|
|
3
|
+
"package_version": "3.15.3",
|
|
4
4
|
"shipped_skills": [
|
|
5
5
|
{
|
|
6
6
|
"path": "config/skills/memory-audit-transaction/SKILL.md",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"path": "config/skills/using-specialists-v3/SKILL.md",
|
|
43
|
-
"sha256": "
|
|
43
|
+
"sha256": "643264862dfa758f85cff41a150be13d6a0c2c8ed42ded6186a3b9b16a87852b"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"path": "config/skills/using-specialists/SKILL.md",
|
package/dist/index.js
CHANGED
|
@@ -7013,6 +7013,9 @@ var require_data = __commonJS((exports, module) => {
|
|
|
7013
7013
|
var require_utils = __commonJS((exports, module) => {
|
|
7014
7014
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
7015
7015
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
7016
|
+
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
7017
|
+
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
7018
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
|
|
7016
7019
|
function stringArrayToHexStripped(input) {
|
|
7017
7020
|
let acc = "";
|
|
7018
7021
|
let code = 0;
|
|
@@ -7206,27 +7209,77 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
7206
7209
|
}
|
|
7207
7210
|
return output.join("");
|
|
7208
7211
|
}
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7212
|
+
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
7213
|
+
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
7214
|
+
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
7215
|
+
function reescapeHostDelimiters(host, isIP) {
|
|
7216
|
+
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
7217
|
+
re.lastIndex = 0;
|
|
7218
|
+
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
7219
|
+
}
|
|
7220
|
+
function normalizePercentEncoding(input, decodeUnreserved = false) {
|
|
7221
|
+
if (input.indexOf("%") === -1) {
|
|
7222
|
+
return input;
|
|
7219
7223
|
}
|
|
7220
|
-
|
|
7221
|
-
|
|
7224
|
+
let output = "";
|
|
7225
|
+
for (let i = 0;i < input.length; i++) {
|
|
7226
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
7227
|
+
const hex = input.slice(i + 1, i + 3);
|
|
7228
|
+
if (isHexPair(hex)) {
|
|
7229
|
+
const normalizedHex = hex.toUpperCase();
|
|
7230
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
7231
|
+
if (decodeUnreserved && isUnreserved(decoded)) {
|
|
7232
|
+
output += decoded;
|
|
7233
|
+
} else {
|
|
7234
|
+
output += "%" + normalizedHex;
|
|
7235
|
+
}
|
|
7236
|
+
i += 2;
|
|
7237
|
+
continue;
|
|
7238
|
+
}
|
|
7239
|
+
}
|
|
7240
|
+
output += input[i];
|
|
7222
7241
|
}
|
|
7223
|
-
|
|
7224
|
-
|
|
7242
|
+
return output;
|
|
7243
|
+
}
|
|
7244
|
+
function normalizePathEncoding(input) {
|
|
7245
|
+
let output = "";
|
|
7246
|
+
for (let i = 0;i < input.length; i++) {
|
|
7247
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
7248
|
+
const hex = input.slice(i + 1, i + 3);
|
|
7249
|
+
if (isHexPair(hex)) {
|
|
7250
|
+
const normalizedHex = hex.toUpperCase();
|
|
7251
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
7252
|
+
if (decoded !== "." && isUnreserved(decoded)) {
|
|
7253
|
+
output += decoded;
|
|
7254
|
+
} else {
|
|
7255
|
+
output += "%" + normalizedHex;
|
|
7256
|
+
}
|
|
7257
|
+
i += 2;
|
|
7258
|
+
continue;
|
|
7259
|
+
}
|
|
7260
|
+
}
|
|
7261
|
+
if (isPathCharacter(input[i])) {
|
|
7262
|
+
output += input[i];
|
|
7263
|
+
} else {
|
|
7264
|
+
output += escape(input[i]);
|
|
7265
|
+
}
|
|
7225
7266
|
}
|
|
7226
|
-
|
|
7227
|
-
|
|
7267
|
+
return output;
|
|
7268
|
+
}
|
|
7269
|
+
function escapePreservingEscapes(input) {
|
|
7270
|
+
let output = "";
|
|
7271
|
+
for (let i = 0;i < input.length; i++) {
|
|
7272
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
7273
|
+
const hex = input.slice(i + 1, i + 3);
|
|
7274
|
+
if (isHexPair(hex)) {
|
|
7275
|
+
output += "%" + hex.toUpperCase();
|
|
7276
|
+
i += 2;
|
|
7277
|
+
continue;
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
output += escape(input[i]);
|
|
7228
7281
|
}
|
|
7229
|
-
return
|
|
7282
|
+
return output;
|
|
7230
7283
|
}
|
|
7231
7284
|
function recomposeAuthority(component) {
|
|
7232
7285
|
const uriTokens = [];
|
|
@@ -7241,7 +7294,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
7241
7294
|
if (ipV6res.isIPV6 === true) {
|
|
7242
7295
|
host = `[${ipV6res.escapedHost}]`;
|
|
7243
7296
|
} else {
|
|
7244
|
-
host =
|
|
7297
|
+
host = reescapeHostDelimiters(host, false);
|
|
7245
7298
|
}
|
|
7246
7299
|
}
|
|
7247
7300
|
uriTokens.push(host);
|
|
@@ -7255,7 +7308,10 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
7255
7308
|
module.exports = {
|
|
7256
7309
|
nonSimpleDomain,
|
|
7257
7310
|
recomposeAuthority,
|
|
7258
|
-
|
|
7311
|
+
reescapeHostDelimiters,
|
|
7312
|
+
normalizePercentEncoding,
|
|
7313
|
+
normalizePathEncoding,
|
|
7314
|
+
escapePreservingEscapes,
|
|
7259
7315
|
removeDotSegments,
|
|
7260
7316
|
isIPv4,
|
|
7261
7317
|
isUUID,
|
|
@@ -7440,11 +7496,11 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
7440
7496
|
|
|
7441
7497
|
// node_modules/fast-uri/index.js
|
|
7442
7498
|
var require_fast_uri = __commonJS((exports, module) => {
|
|
7443
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority,
|
|
7499
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
7444
7500
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
7445
7501
|
function normalize(uri, options) {
|
|
7446
7502
|
if (typeof uri === "string") {
|
|
7447
|
-
uri =
|
|
7503
|
+
uri = normalizeString(uri, options);
|
|
7448
7504
|
} else if (typeof uri === "object") {
|
|
7449
7505
|
uri = parse5(serialize(uri, options), options);
|
|
7450
7506
|
}
|
|
@@ -7510,19 +7566,9 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7510
7566
|
return target;
|
|
7511
7567
|
}
|
|
7512
7568
|
function equal(uriA, uriB, options) {
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
} else if (typeof uriA === "object") {
|
|
7517
|
-
uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
|
|
7518
|
-
}
|
|
7519
|
-
if (typeof uriB === "string") {
|
|
7520
|
-
uriB = unescape(uriB);
|
|
7521
|
-
uriB = serialize(normalizeComponentEncoding(parse5(uriB, options), true), { ...options, skipEscape: true });
|
|
7522
|
-
} else if (typeof uriB === "object") {
|
|
7523
|
-
uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
|
|
7524
|
-
}
|
|
7525
|
-
return uriA.toLowerCase() === uriB.toLowerCase();
|
|
7569
|
+
const normalizedA = normalizeComparableURI(uriA, options);
|
|
7570
|
+
const normalizedB = normalizeComparableURI(uriB, options);
|
|
7571
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA.toLowerCase() === normalizedB.toLowerCase();
|
|
7526
7572
|
}
|
|
7527
7573
|
function serialize(cmpts, opts) {
|
|
7528
7574
|
const component = {
|
|
@@ -7548,12 +7594,12 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7548
7594
|
schemeHandler.serialize(component, options);
|
|
7549
7595
|
if (component.path !== undefined) {
|
|
7550
7596
|
if (!options.skipEscape) {
|
|
7551
|
-
component.path =
|
|
7597
|
+
component.path = escapePreservingEscapes(component.path);
|
|
7552
7598
|
if (component.scheme !== undefined) {
|
|
7553
7599
|
component.path = component.path.split("%3A").join(":");
|
|
7554
7600
|
}
|
|
7555
7601
|
} else {
|
|
7556
|
-
component.path =
|
|
7602
|
+
component.path = normalizePercentEncoding(component.path);
|
|
7557
7603
|
}
|
|
7558
7604
|
}
|
|
7559
7605
|
if (options.reference !== "suffix" && component.scheme) {
|
|
@@ -7588,7 +7634,16 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7588
7634
|
return uriTokens.join("");
|
|
7589
7635
|
}
|
|
7590
7636
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
7591
|
-
function
|
|
7637
|
+
function getParseError(parsed, matches) {
|
|
7638
|
+
if (matches[2] !== undefined && parsed.path && parsed.path[0] !== "/") {
|
|
7639
|
+
return 'URI path must start with "/" when authority is present.';
|
|
7640
|
+
}
|
|
7641
|
+
if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
|
|
7642
|
+
return "URI port is malformed.";
|
|
7643
|
+
}
|
|
7644
|
+
return;
|
|
7645
|
+
}
|
|
7646
|
+
function parseWithStatus(uri, opts) {
|
|
7592
7647
|
const options = Object.assign({}, opts);
|
|
7593
7648
|
const parsed = {
|
|
7594
7649
|
scheme: undefined,
|
|
@@ -7599,6 +7654,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7599
7654
|
query: undefined,
|
|
7600
7655
|
fragment: undefined
|
|
7601
7656
|
};
|
|
7657
|
+
let malformedAuthorityOrPort = false;
|
|
7602
7658
|
let isIP = false;
|
|
7603
7659
|
if (options.reference === "suffix") {
|
|
7604
7660
|
if (options.scheme) {
|
|
@@ -7619,6 +7675,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7619
7675
|
if (isNaN(parsed.port)) {
|
|
7620
7676
|
parsed.port = matches[5];
|
|
7621
7677
|
}
|
|
7678
|
+
const parseError = getParseError(parsed, matches);
|
|
7679
|
+
if (parseError !== undefined) {
|
|
7680
|
+
parsed.error = parsed.error || parseError;
|
|
7681
|
+
malformedAuthorityOrPort = true;
|
|
7682
|
+
}
|
|
7622
7683
|
if (parsed.host) {
|
|
7623
7684
|
const ipv4result = isIPv4(parsed.host);
|
|
7624
7685
|
if (ipv4result === false) {
|
|
@@ -7657,14 +7718,18 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7657
7718
|
parsed.scheme = unescape(parsed.scheme);
|
|
7658
7719
|
}
|
|
7659
7720
|
if (parsed.host !== undefined) {
|
|
7660
|
-
parsed.host = unescape(parsed.host);
|
|
7721
|
+
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
7661
7722
|
}
|
|
7662
7723
|
}
|
|
7663
7724
|
if (parsed.path) {
|
|
7664
|
-
parsed.path =
|
|
7725
|
+
parsed.path = normalizePathEncoding(parsed.path);
|
|
7665
7726
|
}
|
|
7666
7727
|
if (parsed.fragment) {
|
|
7667
|
-
|
|
7728
|
+
try {
|
|
7729
|
+
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
7730
|
+
} catch {
|
|
7731
|
+
parsed.error = parsed.error || "URI malformed";
|
|
7732
|
+
}
|
|
7668
7733
|
}
|
|
7669
7734
|
}
|
|
7670
7735
|
if (schemeHandler && schemeHandler.parse) {
|
|
@@ -7673,7 +7738,29 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
7673
7738
|
} else {
|
|
7674
7739
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
7675
7740
|
}
|
|
7676
|
-
return parsed;
|
|
7741
|
+
return { parsed, malformedAuthorityOrPort };
|
|
7742
|
+
}
|
|
7743
|
+
function parse5(uri, opts) {
|
|
7744
|
+
return parseWithStatus(uri, opts).parsed;
|
|
7745
|
+
}
|
|
7746
|
+
function normalizeString(uri, opts) {
|
|
7747
|
+
return normalizeStringWithStatus(uri, opts).normalized;
|
|
7748
|
+
}
|
|
7749
|
+
function normalizeStringWithStatus(uri, opts) {
|
|
7750
|
+
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
7751
|
+
return {
|
|
7752
|
+
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
7753
|
+
malformedAuthorityOrPort
|
|
7754
|
+
};
|
|
7755
|
+
}
|
|
7756
|
+
function normalizeComparableURI(uri, opts) {
|
|
7757
|
+
if (typeof uri === "string") {
|
|
7758
|
+
const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
|
|
7759
|
+
return malformedAuthorityOrPort ? undefined : normalized;
|
|
7760
|
+
}
|
|
7761
|
+
if (typeof uri === "object") {
|
|
7762
|
+
return serialize(uri, opts);
|
|
7763
|
+
}
|
|
7677
7764
|
}
|
|
7678
7765
|
var fastUri = {
|
|
7679
7766
|
SCHEMES,
|
|
@@ -7808,7 +7895,7 @@ var require_core = __commonJS((exports) => {
|
|
|
7808
7895
|
constructor(opts = {}) {
|
|
7809
7896
|
this.schemas = {};
|
|
7810
7897
|
this.refs = {};
|
|
7811
|
-
this.formats =
|
|
7898
|
+
this.formats = Object.create(null);
|
|
7812
7899
|
this._compilations = new Set;
|
|
7813
7900
|
this._loading = {};
|
|
7814
7901
|
this._cache = new Map;
|
|
@@ -15332,8 +15419,10 @@ ${cb}` : comment;
|
|
|
15332
15419
|
}
|
|
15333
15420
|
}
|
|
15334
15421
|
if (afterDoc) {
|
|
15335
|
-
|
|
15336
|
-
|
|
15422
|
+
for (let i = 0;i < this.errors.length; ++i)
|
|
15423
|
+
doc2.errors.push(this.errors[i]);
|
|
15424
|
+
for (let i = 0;i < this.warnings.length; ++i)
|
|
15425
|
+
doc2.warnings.push(this.warnings[i]);
|
|
15337
15426
|
} else {
|
|
15338
15427
|
doc2.errors = this.errors;
|
|
15339
15428
|
doc2.warnings = this.warnings;
|
|
@@ -16045,7 +16134,7 @@ var require_lexer = __commonJS((exports) => {
|
|
|
16045
16134
|
const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
|
|
16046
16135
|
this.indentNext = this.indentValue + 1;
|
|
16047
16136
|
this.indentValue += n;
|
|
16048
|
-
return
|
|
16137
|
+
return "block-start";
|
|
16049
16138
|
}
|
|
16050
16139
|
return "doc";
|
|
16051
16140
|
}
|
|
@@ -16352,26 +16441,37 @@ var require_lexer = __commonJS((exports) => {
|
|
|
16352
16441
|
return 0;
|
|
16353
16442
|
}
|
|
16354
16443
|
*pushIndicators() {
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
|
|
16364
|
-
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16368
|
-
|
|
16369
|
-
|
|
16370
|
-
|
|
16444
|
+
let n = 0;
|
|
16445
|
+
loop:
|
|
16446
|
+
while (true) {
|
|
16447
|
+
switch (this.charAt(0)) {
|
|
16448
|
+
case "!":
|
|
16449
|
+
n += yield* this.pushTag();
|
|
16450
|
+
n += yield* this.pushSpaces(true);
|
|
16451
|
+
continue loop;
|
|
16452
|
+
case "&":
|
|
16453
|
+
n += yield* this.pushUntil(isNotAnchorChar);
|
|
16454
|
+
n += yield* this.pushSpaces(true);
|
|
16455
|
+
continue loop;
|
|
16456
|
+
case "-":
|
|
16457
|
+
case "?":
|
|
16458
|
+
case ":": {
|
|
16459
|
+
const inFlow = this.flowLevel > 0;
|
|
16460
|
+
const ch1 = this.charAt(1);
|
|
16461
|
+
if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
|
|
16462
|
+
if (!inFlow)
|
|
16463
|
+
this.indentNext = this.indentValue + 1;
|
|
16464
|
+
else if (this.flowKey)
|
|
16465
|
+
this.flowKey = false;
|
|
16466
|
+
n += yield* this.pushCount(1);
|
|
16467
|
+
n += yield* this.pushSpaces(true);
|
|
16468
|
+
continue loop;
|
|
16469
|
+
}
|
|
16470
|
+
}
|
|
16371
16471
|
}
|
|
16472
|
+
break loop;
|
|
16372
16473
|
}
|
|
16373
|
-
|
|
16374
|
-
return 0;
|
|
16474
|
+
return n;
|
|
16375
16475
|
}
|
|
16376
16476
|
*pushTag() {
|
|
16377
16477
|
if (this.charAt(1) === "<") {
|
|
@@ -16525,6 +16625,13 @@ var require_parser = __commonJS((exports) => {
|
|
|
16525
16625
|
while (prev[++i]?.type === "space") {}
|
|
16526
16626
|
return prev.splice(i, prev.length);
|
|
16527
16627
|
}
|
|
16628
|
+
function arrayPushArray(target, source) {
|
|
16629
|
+
if (source.length < 1e5)
|
|
16630
|
+
Array.prototype.push.apply(target, source);
|
|
16631
|
+
else
|
|
16632
|
+
for (let i = 0;i < source.length; ++i)
|
|
16633
|
+
target.push(source[i]);
|
|
16634
|
+
}
|
|
16528
16635
|
function fixFlowSeqItems(fc) {
|
|
16529
16636
|
if (fc.start.type === "flow-seq-start") {
|
|
16530
16637
|
for (const it of fc.items) {
|
|
@@ -16534,11 +16641,11 @@ var require_parser = __commonJS((exports) => {
|
|
|
16534
16641
|
delete it.key;
|
|
16535
16642
|
if (isFlowToken(it.value)) {
|
|
16536
16643
|
if (it.value.end)
|
|
16537
|
-
|
|
16644
|
+
arrayPushArray(it.value.end, it.sep);
|
|
16538
16645
|
else
|
|
16539
16646
|
it.value.end = it.sep;
|
|
16540
16647
|
} else
|
|
16541
|
-
|
|
16648
|
+
arrayPushArray(it.start, it.sep);
|
|
16542
16649
|
delete it.sep;
|
|
16543
16650
|
}
|
|
16544
16651
|
}
|
|
@@ -16878,7 +16985,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
16878
16985
|
const prev = map2.items[map2.items.length - 2];
|
|
16879
16986
|
const end = prev?.value?.end;
|
|
16880
16987
|
if (Array.isArray(end)) {
|
|
16881
|
-
|
|
16988
|
+
arrayPushArray(end, it.start);
|
|
16882
16989
|
end.push(this.sourceToken);
|
|
16883
16990
|
map2.items.pop();
|
|
16884
16991
|
return;
|
|
@@ -17066,7 +17173,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
17066
17173
|
const prev = seq.items[seq.items.length - 2];
|
|
17067
17174
|
const end = prev?.value?.end;
|
|
17068
17175
|
if (Array.isArray(end)) {
|
|
17069
|
-
|
|
17176
|
+
arrayPushArray(end, it.start);
|
|
17070
17177
|
end.push(this.sourceToken);
|
|
17071
17178
|
seq.items.pop();
|
|
17072
17179
|
return;
|
|
@@ -31951,7 +32058,7 @@ async function run14() {
|
|
|
31951
32058
|
const launchStartedAt = Date.now();
|
|
31952
32059
|
const innerArgs = process.argv.slice(2).filter((a) => a !== "--background");
|
|
31953
32060
|
const cmd = `${process.execPath} ${process.argv[1]} ${innerArgs.map(shellQuote2).join(" ")}`;
|
|
31954
|
-
const tmuxCmd = `/bin/bash -
|
|
32061
|
+
const tmuxCmd = `/bin/bash -c ${shellQuote2(`cd ${shellQuote2(cwd)} && exec ${cmd}`)}`;
|
|
31955
32062
|
let childPid;
|
|
31956
32063
|
let childExitCode;
|
|
31957
32064
|
let childExitPromise;
|
package/dist/lib.js
CHANGED
|
@@ -4855,8 +4855,10 @@ ${cb}` : comment;
|
|
|
4855
4855
|
}
|
|
4856
4856
|
}
|
|
4857
4857
|
if (afterDoc) {
|
|
4858
|
-
|
|
4859
|
-
|
|
4858
|
+
for (let i = 0;i < this.errors.length; ++i)
|
|
4859
|
+
doc.errors.push(this.errors[i]);
|
|
4860
|
+
for (let i = 0;i < this.warnings.length; ++i)
|
|
4861
|
+
doc.warnings.push(this.warnings[i]);
|
|
4860
4862
|
} else {
|
|
4861
4863
|
doc.errors = this.errors;
|
|
4862
4864
|
doc.warnings = this.warnings;
|
|
@@ -5568,7 +5570,7 @@ var require_lexer = __commonJS((exports) => {
|
|
|
5568
5570
|
const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
|
|
5569
5571
|
this.indentNext = this.indentValue + 1;
|
|
5570
5572
|
this.indentValue += n;
|
|
5571
|
-
return
|
|
5573
|
+
return "block-start";
|
|
5572
5574
|
}
|
|
5573
5575
|
return "doc";
|
|
5574
5576
|
}
|
|
@@ -5875,26 +5877,37 @@ var require_lexer = __commonJS((exports) => {
|
|
|
5875
5877
|
return 0;
|
|
5876
5878
|
}
|
|
5877
5879
|
*pushIndicators() {
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5880
|
+
let n = 0;
|
|
5881
|
+
loop:
|
|
5882
|
+
while (true) {
|
|
5883
|
+
switch (this.charAt(0)) {
|
|
5884
|
+
case "!":
|
|
5885
|
+
n += yield* this.pushTag();
|
|
5886
|
+
n += yield* this.pushSpaces(true);
|
|
5887
|
+
continue loop;
|
|
5888
|
+
case "&":
|
|
5889
|
+
n += yield* this.pushUntil(isNotAnchorChar);
|
|
5890
|
+
n += yield* this.pushSpaces(true);
|
|
5891
|
+
continue loop;
|
|
5892
|
+
case "-":
|
|
5893
|
+
case "?":
|
|
5894
|
+
case ":": {
|
|
5895
|
+
const inFlow = this.flowLevel > 0;
|
|
5896
|
+
const ch1 = this.charAt(1);
|
|
5897
|
+
if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
|
|
5898
|
+
if (!inFlow)
|
|
5899
|
+
this.indentNext = this.indentValue + 1;
|
|
5900
|
+
else if (this.flowKey)
|
|
5901
|
+
this.flowKey = false;
|
|
5902
|
+
n += yield* this.pushCount(1);
|
|
5903
|
+
n += yield* this.pushSpaces(true);
|
|
5904
|
+
continue loop;
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5894
5907
|
}
|
|
5908
|
+
break loop;
|
|
5895
5909
|
}
|
|
5896
|
-
|
|
5897
|
-
return 0;
|
|
5910
|
+
return n;
|
|
5898
5911
|
}
|
|
5899
5912
|
*pushTag() {
|
|
5900
5913
|
if (this.charAt(1) === "<") {
|
|
@@ -6048,6 +6061,13 @@ var require_parser = __commonJS((exports) => {
|
|
|
6048
6061
|
while (prev[++i]?.type === "space") {}
|
|
6049
6062
|
return prev.splice(i, prev.length);
|
|
6050
6063
|
}
|
|
6064
|
+
function arrayPushArray(target, source) {
|
|
6065
|
+
if (source.length < 1e5)
|
|
6066
|
+
Array.prototype.push.apply(target, source);
|
|
6067
|
+
else
|
|
6068
|
+
for (let i = 0;i < source.length; ++i)
|
|
6069
|
+
target.push(source[i]);
|
|
6070
|
+
}
|
|
6051
6071
|
function fixFlowSeqItems(fc) {
|
|
6052
6072
|
if (fc.start.type === "flow-seq-start") {
|
|
6053
6073
|
for (const it of fc.items) {
|
|
@@ -6057,11 +6077,11 @@ var require_parser = __commonJS((exports) => {
|
|
|
6057
6077
|
delete it.key;
|
|
6058
6078
|
if (isFlowToken(it.value)) {
|
|
6059
6079
|
if (it.value.end)
|
|
6060
|
-
|
|
6080
|
+
arrayPushArray(it.value.end, it.sep);
|
|
6061
6081
|
else
|
|
6062
6082
|
it.value.end = it.sep;
|
|
6063
6083
|
} else
|
|
6064
|
-
|
|
6084
|
+
arrayPushArray(it.start, it.sep);
|
|
6065
6085
|
delete it.sep;
|
|
6066
6086
|
}
|
|
6067
6087
|
}
|
|
@@ -6401,7 +6421,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
6401
6421
|
const prev = map.items[map.items.length - 2];
|
|
6402
6422
|
const end = prev?.value?.end;
|
|
6403
6423
|
if (Array.isArray(end)) {
|
|
6404
|
-
|
|
6424
|
+
arrayPushArray(end, it.start);
|
|
6405
6425
|
end.push(this.sourceToken);
|
|
6406
6426
|
map.items.pop();
|
|
6407
6427
|
return;
|
|
@@ -6589,7 +6609,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
6589
6609
|
const prev = seq.items[seq.items.length - 2];
|
|
6590
6610
|
const end = prev?.value?.end;
|
|
6591
6611
|
if (Array.isArray(end)) {
|
|
6592
|
-
|
|
6612
|
+
arrayPushArray(end, it.start);
|
|
6593
6613
|
end.push(this.sourceToken);
|
|
6594
6614
|
seq.items.pop();
|
|
6595
6615
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/run.ts"],"names":[],"mappings":"AA6gBA,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA+FrG;AAGD,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/run.ts"],"names":[],"mappings":"AA6gBA,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA+FrG;AAGD,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAsXzC"}
|
|
@@ -44,7 +44,7 @@ export declare function evaluateReadiness(opts: ReadinessCheckOptions): Promise<
|
|
|
44
44
|
}>;
|
|
45
45
|
export declare function checkPiHelpForFlags(flags?: string[]): ReadinessReason | undefined;
|
|
46
46
|
export declare function startServe(argv?: string[]): Promise<{
|
|
47
|
-
server: import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
47
|
+
server: import("node:http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
48
48
|
args: ServeArgs;
|
|
49
49
|
db: import("../specialist/observability-sqlite.js").ObservabilitySqliteClient | null;
|
|
50
50
|
readinessState: ReadinessState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaggerxtrm/specialists",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.3",
|
|
4
4
|
"description": "OmniSpecialist — 7-tool MCP orchestration layer powered by the Specialist System. Discover and execute .specialist.yaml files across project/user/system scopes via pi.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/types/lib.d.ts",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
77
|
-
"yaml": "2.
|
|
77
|
+
"yaml": "2.9.0",
|
|
78
78
|
"zod": "^3.25.76",
|
|
79
79
|
"zod-to-json-schema": "^3.24.6"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@types/bun": "1.3.
|
|
83
|
-
"@types/node": "^
|
|
82
|
+
"@types/bun": "1.3.14",
|
|
83
|
+
"@types/node": "^25.8.0",
|
|
84
84
|
"@vitest/coverage-v8": "^4.1.6",
|
|
85
85
|
"tsx": "^4.20.6",
|
|
86
86
|
"typescript": "^5.0.0",
|
|
@@ -90,8 +90,10 @@
|
|
|
90
90
|
"bun": ">=1.0.0"
|
|
91
91
|
},
|
|
92
92
|
"overrides": {
|
|
93
|
+
"@hono/node-server": "^1.19.13",
|
|
93
94
|
"fast-uri": "^3.1.2",
|
|
95
|
+
"hono": "^4.12.18",
|
|
94
96
|
"ip-address": "^10.2.0",
|
|
95
|
-
"
|
|
97
|
+
"path-to-regexp": "^8.4.0"
|
|
96
98
|
}
|
|
97
99
|
}
|