@friedbotstudio/create-baseline 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -10
- package/bin/cli.js +19 -13
- package/obj/template/.claude/commands/init-project-doctor.md +74 -0
- package/obj/template/.claude/hooks/lib/resume_writer.py +14 -1
- package/obj/template/.claude/hooks/memory_session_start.sh +24 -0
- package/obj/template/.claude/hooks/track_guard.sh +11 -1
- package/obj/template/.claude/manifest.json +31 -99
- package/obj/template/.claude/schemas/workflow-track.v1.json +64 -0
- package/obj/template/.claude/skills/audit-baseline/audit.sh +2 -2
- package/obj/template/.claude/skills/chore/SKILL.md +2 -2
- package/obj/template/.claude/skills/harness/SKILL.md +15 -6
- package/obj/template/.claude/skills/intake/SKILL.md +1 -1
- package/obj/template/.claude/skills/swarm-plan/SKILL.md +2 -0
- package/obj/template/.claude/skills/tdd/SKILL.md +2 -2
- package/obj/template/.claude/skills/triage/SKILL.md +29 -6
- package/obj/template/.claude/skills/triage/seed-tasklist.mjs +107 -0
- package/obj/template/.claude/skills/upgrade-project/SKILL.md +18 -7
- package/obj/template/.claude/workflows.jsonl +6 -0
- package/obj/template/CLAUDE.md +8 -14
- package/obj/template/docs/init/seed.md +148 -3
- package/package.json +1 -1
- package/src/.claude/workflows.template.jsonl +6 -0
- package/src/CLAUDE.template.md +8 -14
- package/src/cli/install.js +5 -1
- package/src/cli/merge.js +42 -5
- package/src/cli/track-tasklist-materializer.js +223 -0
- package/src/cli/tui/upgrade.js +30 -41
- package/src/cli/upgrade-tiers.js +42 -4
- package/src/cli/workflow-migrator.js +40 -0
- package/src/cli/workflows-validator-invariants.js +417 -0
- package/src/cli/workflows-validator-predicates.js +19 -0
- package/src/cli/workflows-validator.js +156 -0
- package/src/seed.template.md +148 -3
- package/obj/template/.claude/skills/google-analytics/SKILL.md +0 -129
- package/obj/template/.claude/skills/google-analytics/references/audiences.md +0 -389
- package/obj/template/.claude/skills/google-analytics/references/bigquery.md +0 -470
- package/obj/template/.claude/skills/google-analytics/references/custom-dimensions.md +0 -355
- package/obj/template/.claude/skills/google-analytics/references/custom-events.md +0 -383
- package/obj/template/.claude/skills/google-analytics/references/data-management.md +0 -416
- package/obj/template/.claude/skills/google-analytics/references/debugview.md +0 -364
- package/obj/template/.claude/skills/google-analytics/references/events-fundamentals.md +0 -398
- package/obj/template/.claude/skills/google-analytics/references/gtag.md +0 -502
- package/obj/template/.claude/skills/google-analytics/references/gtm-integration.md +0 -483
- package/obj/template/.claude/skills/google-analytics/references/measurement-protocol.md +0 -519
- package/obj/template/.claude/skills/google-analytics/references/privacy.md +0 -441
- package/obj/template/.claude/skills/google-analytics/references/recommended-events.md +0 -464
- package/obj/template/.claude/skills/google-analytics/references/reporting.md +0 -397
- package/obj/template/.claude/skills/google-analytics/references/setup.md +0 -344
- package/obj/template/.claude/skills/google-analytics/references/user-tracking.md +0 -417
- package/obj/template/.claude/skills/optimize-seo/SKILL.md +0 -313
- package/obj/template/.claude/skills/optimize-seo/scripts/pagespeed.mjs +0 -197
- package/obj/template/.claude/skills/pagespeed-insights/LICENSE.md +0 -37
- package/obj/template/.claude/skills/pagespeed-insights/SKILL.md +0 -446
- package/obj/template/.claude/skills/pagespeed-insights/reference.md +0 -50
- package/src/cli/diff-render.js +0 -54
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ A discipline layer for Claude Code. Hooks at every tool boundary, a workflow tha
|
|
|
41
41
|
|
|
42
42
|
## What this is
|
|
43
43
|
|
|
44
|
-
The Claude Code Baseline is a repository overlay shipped via `npx @friedbotstudio/create-baseline ./target`. It installs **22 hooks** at Claude's tool boundaries, **38 skills** organised into ten categories, **1 subagent** for parallel work in isolated worktrees,
|
|
44
|
+
The Claude Code Baseline is a repository overlay shipped via `npx @friedbotstudio/create-baseline ./target`. It installs **22 hooks** at Claude's tool boundaries, **38 skills** organised into ten categories, **1 subagent** for parallel work in isolated worktrees, **4 canonical workflow tracks** declared in `.claude/workflows.jsonl` (where `intake-full` runs 11 nodes from intake to commit), and **3 user-typed consent gates** that Claude cannot forge.
|
|
45
45
|
|
|
46
46
|
Every soft engineering rule a team usually repeats every session — *don't push, don't `--amend`, don't self-approve specs, don't skip phases, don't mock internal modules* — becomes a structural guarantee because the hooks run **outside Claude's tool boundary**. Claude cannot disable a hook with a flag, cannot write a consent marker, cannot reorder the phases without an explicit exception that triage records on disk.
|
|
47
47
|
|
|
@@ -62,9 +62,9 @@ A team that installs the baseline stops typing *"don't push, don't `--amend`, do
|
|
|
62
62
|
| What | Count | Where it lives |
|
|
63
63
|
|---|---:|---|
|
|
64
64
|
| **Hooks** at PreToolUse / PostToolUse / SessionStart / Stop / PreCompact / UserPromptSubmit | 22 | `.claude/hooks/` |
|
|
65
|
-
| **Skills** across artifact drafting, workflow phases, phase workers, spec helpers, orchestration, memory, audit, alternate tracks,
|
|
65
|
+
| **Skills** across artifact drafting, workflow phases, phase workers, spec helpers, orchestration, memory, audit, alternate tracks, shared globals, and maintenance | 38 | `.claude/skills/` |
|
|
66
66
|
| **Subagent** — `swarm-worker`, executes pre-decided recipes inside isolated git worktrees | 1 | `.claude/agents/` |
|
|
67
|
-
| **Workflow
|
|
67
|
+
| **Workflow tracks** declared in `.claude/workflows.jsonl`. Canonical set: `intake-full` (11 nodes), `spec-entry`, `tdd-quickfix`, `chore`. Two sub-tracks (`swarm-implementation`, `tdd-worker-chain`) are referenced by selector nodes inside the canonical set. | 4 selectable + 2 sub | `.claude/workflows.jsonl`, enforced by `track_guard` |
|
|
68
68
|
| **Consent gates** — `/approve-spec`, `/approve-swarm`, `/grant-commit`. User-typed; structurally un-invokable by Claude | 3 | `consent_gate_grant` UserPromptSubmit hook |
|
|
69
69
|
| **MCP servers** declared in `.mcp.json` — `context7` (third-party API docs), `plantuml` (diagram render), `playwright` (cross-engine smoke) | 3 | `.mcp.json` |
|
|
70
70
|
|
|
@@ -92,15 +92,19 @@ npx @friedbotstudio/create-baseline ./your-project
|
|
|
92
92
|
npx @friedbotstudio/create-baseline ./your-project
|
|
93
93
|
|
|
94
94
|
# Force-overwrite an existing install (interactive — type 'overwrite')
|
|
95
|
-
npx @friedbotstudio/create-baseline ./your-project --
|
|
95
|
+
npx @friedbotstudio/create-baseline ./your-project --force
|
|
96
96
|
|
|
97
97
|
# Upgrade an existing install against a newer baseline version.
|
|
98
|
-
# In a TTY, each customised file
|
|
99
|
-
# prompt
|
|
98
|
+
# In a TTY, each tier-1 customised file prompts: keep-mine / take-theirs / merge / abort
|
|
99
|
+
# prompt; tier-2 files auto-merge via `git merge-file --diff3`; tier-3 files
|
|
100
|
+
# stage for the /upgrade-project Claude Code skill to reconcile. In CI / piped
|
|
101
|
+
# stdout, every per-file action is reported with a user-facing label:
|
|
100
102
|
# - adds new baseline files
|
|
101
103
|
# - refreshes baseline files the user has not touched
|
|
102
|
-
# -
|
|
103
|
-
# - removes baseline files
|
|
104
|
+
# - keeps customised files (exit 3 if any preserved)
|
|
105
|
+
# - removes baseline files removed upstream that the user had not touched
|
|
106
|
+
# - exit 4 if a mechanical merge produced conflict markers
|
|
107
|
+
# - exit 5 if any tier-3 file was staged for /upgrade-project
|
|
104
108
|
npx @friedbotstudio/create-baseline upgrade ./your-project
|
|
105
109
|
|
|
106
110
|
# Preview without writing anything
|
|
@@ -158,7 +162,7 @@ The three workflow-phase consent gates pause the workflow until you type the cor
|
|
|
158
162
|
|
|
159
163
|
- **`/approve-spec <slug>`** — after the spec phase, before any code is written
|
|
160
164
|
- **`/approve-swarm <slug>`** — after `/swarm-plan`, before parallel dispatch
|
|
161
|
-
- **`/grant-commit`** — after `/archive`, before the commit lands
|
|
165
|
+
- **`/grant-commit`** — after `/archive` and `/memory-flush`, before the commit lands
|
|
162
166
|
|
|
163
167
|
A fourth consent gate sits outside the phase pipeline:
|
|
164
168
|
|
|
@@ -172,7 +176,7 @@ The 22 hooks declared in `.claude/settings.json` fire at every Claude tool bound
|
|
|
172
176
|
|
|
173
177
|
The architectural rule is simple: **decisions live in main context; subagents only execute pre-decided recipes**. The baseline ships exactly one subagent — `swarm-worker` — and its only sanctioned use is parallel dispatch of fully-specified recipes inside isolated git worktrees during `/swarm-dispatch`. Every other capability that might have been a subagent (code authoring, scenario design, scouting, security review, prose writing, UI design) lives instead as a **skill** that runs in main context with full conversation visibility.
|
|
174
178
|
|
|
175
|
-
|
|
179
|
+
Tracks declared in `.claude/workflows.jsonl` are enforced at the write boundary by `track_guard`. Node ordering inside each track is binding; the only mechanism to bypass a node is the `exceptions` array in `.claude/state/workflow.json`, written by `/triage` at workflow creation time. The `chore` track is a stripped-down ordering of the same gates, with the test-first nodes removed because nothing needs testing first. Projects declare their own tracks (or add nodes to the canonical ones) by editing their `.claude/workflows.jsonl`. Article IV's invariants (I1..I11) bind every track regardless of who wrote it; a track that omits `/grant-commit` before a `commit` node, or whose dependency graph contains a cycle, is rejected at triage time with a named error.
|
|
176
180
|
|
|
177
181
|
The constitution at `CLAUDE.md` is the source of truth for in-session behaviour; `docs/init/seed.md` is the source of truth for the baseline's shape. When the constitution and the implementation conflict, the constitution governs and the implementation gets corrected. When `seed.md` and the constitution conflict, `seed.md` governs and you stop and surface the drift before acting.
|
|
178
182
|
|
package/bin/cli.js
CHANGED
|
@@ -8,8 +8,8 @@ import { existsSync } from 'node:fs';
|
|
|
8
8
|
import * as io from '../src/cli/io.js';
|
|
9
9
|
import { scanSentinels } from '../src/cli/conflict.js';
|
|
10
10
|
import { freshInstall, forceInstall, COPY_EXCLUDE } from '../src/cli/install.js';
|
|
11
|
-
import { threeWayMerge } from '../src/cli/merge.js';
|
|
12
|
-
import { loadManifest, buildManifestFromDir } from '../src/cli/manifest.js';
|
|
11
|
+
import { threeWayMerge, ACTION_LABELS, ACTION_LABEL_WIDTH } from '../src/cli/merge.js';
|
|
12
|
+
import { loadManifest, buildManifestFromDir, MANIFEST_VERSION } from '../src/cli/manifest.js';
|
|
13
13
|
import { fetchPlantumlIfMissing, FETCH_OUTCOMES } from '../src/cli/plantuml.js';
|
|
14
14
|
import { runDoctor, formatReport } from '../src/cli/doctor.js';
|
|
15
15
|
|
|
@@ -33,7 +33,9 @@ Upgrade:
|
|
|
33
33
|
Replaces the prior --merge flag. Reads <target>/.claude/.baseline-manifest.json
|
|
34
34
|
and runs a three-tier merge against the shipped template:
|
|
35
35
|
- tier 1 (binary prompt): customized files prompt "Keep your version / Use
|
|
36
|
-
new baseline /
|
|
36
|
+
new baseline / Merge / Abort" in TTY mode. "Merge" stages incoming bytes
|
|
37
|
+
under .claude/state/upgrade/<ts>/ for /upgrade-project to reconcile in
|
|
38
|
+
Claude Code (exit 5); "Keep your version" exits 3 on any skipped.
|
|
37
39
|
- tier 2 (mechanical): files routed through git merge-file --diff3 with
|
|
38
40
|
BASE recovered from .claude/.baseline-prior/ cache or npm fallback;
|
|
39
41
|
clean merges land silently, conflicts surface with markers (exit 4).
|
|
@@ -66,11 +68,13 @@ Misc:
|
|
|
66
68
|
--version Print version.
|
|
67
69
|
|
|
68
70
|
Exit codes:
|
|
69
|
-
0 success
|
|
71
|
+
0 success (or clean doctor)
|
|
70
72
|
1 user abort, conflict-without-force, doctor reports missing files, or upgrade aborted
|
|
71
|
-
2
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
2 bad command line, prompted input needed but no terminal, doctor finds no manifest,
|
|
74
|
+
or deprecated --merge passed
|
|
75
|
+
3 upgrade kept your customized files (or preserved files removed upstream)
|
|
76
|
+
4 --require-plantuml jar fetch failed, OR mechanical merge produced conflicts to resolve
|
|
77
|
+
5 semantic merge staged for /upgrade-project to reconcile in Claude Code
|
|
74
78
|
`;
|
|
75
79
|
|
|
76
80
|
const OPTIONS = {
|
|
@@ -203,8 +207,9 @@ async function runPlainInstall(target, values, templateDir) {
|
|
|
203
207
|
if (!dryRun) {
|
|
204
208
|
const plantumlExit = await fetchPlantumlPlain(target, values);
|
|
205
209
|
if (plantumlExit !== 0) return plantumlExit;
|
|
206
|
-
|
|
207
|
-
io.log(`
|
|
210
|
+
const version = await readPackageVersion();
|
|
211
|
+
io.log(`Baseline installed at ${target} (manifest v${MANIFEST_VERSION}).`);
|
|
212
|
+
io.log(`For reproducible installs, pin the exact version: @friedbotstudio/create-baseline@${version}`);
|
|
208
213
|
}
|
|
209
214
|
return 0;
|
|
210
215
|
}
|
|
@@ -232,11 +237,11 @@ async function dispatchUpgrade(target, values, templateDir) {
|
|
|
232
237
|
await usageError(`No baseline manifest at ${manifestPath}. Run a fresh install first.`);
|
|
233
238
|
return 2;
|
|
234
239
|
}
|
|
235
|
-
const { findPendingStage } = await import('../src/cli/upgrade-tiers.js');
|
|
240
|
+
const { findPendingStage, formatStageTimestamp } = await import('../src/cli/upgrade-tiers.js');
|
|
236
241
|
const pending = await findPendingStage(target);
|
|
237
242
|
if (pending) {
|
|
238
243
|
const fileLines = pending.files.map((f) => ` - ${f}`).join('\n');
|
|
239
|
-
io.log(`
|
|
244
|
+
io.log(`A previous upgrade staged ${pending.files.length} file(s) for Claude Code review (staged ${formatStageTimestamp(pending.stage_ts)}):\n${fileLines}\nOpen Claude Code and run /upgrade-project to reconcile.`);
|
|
240
245
|
return 5;
|
|
241
246
|
}
|
|
242
247
|
if (process.stdout.isTTY) {
|
|
@@ -260,7 +265,8 @@ async function runPlainUpgrade(target, values, templateDir, manifestPath) {
|
|
|
260
265
|
}
|
|
261
266
|
const report = await threeWayMerge(templateDir, target, oldManifest, newManifest);
|
|
262
267
|
for (const action of report.actions) {
|
|
263
|
-
|
|
268
|
+
const label = ACTION_LABELS[action.kind] ?? action.kind;
|
|
269
|
+
io.log(`${label.padEnd(ACTION_LABEL_WIDTH)} ${action.path}`);
|
|
264
270
|
}
|
|
265
271
|
return report.exitCode;
|
|
266
272
|
}
|
|
@@ -353,7 +359,7 @@ async function main(argv) {
|
|
|
353
359
|
}
|
|
354
360
|
|
|
355
361
|
if (values['no-plantuml'] && values['require-plantuml']) {
|
|
356
|
-
await usageError('--no-plantuml and --require-plantuml
|
|
362
|
+
await usageError('--no-plantuml and --require-plantuml conflict; pick one or omit both.');
|
|
357
363
|
return 2;
|
|
358
364
|
}
|
|
359
365
|
if (positionals.length === 0) {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Detect and repair baseline drift — missing or invalid `.claude/workflows.jsonl`, schema violations, four-way Article IV / §18 mirror drift, and (advisory) shipped-tooling files placed outside `.claude/` against the convention codified at seed.md §3. Interactive: presents each detected violation via AskUserQuestion and applies the named fix on confirmation.
|
|
3
|
+
argument-hint: ""
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, AskUserQuestion, Glob, Grep
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# `/init-project doctor` — baseline drift detector + repairer
|
|
9
|
+
|
|
10
|
+
User-only command. Run after a `create-baseline upgrade` cycle, after manually editing `workflows.jsonl`, or any time the baseline feels out of sync. Different from `create-baseline doctor` (the npm CLI manifest-drift checker) — this is a project-internal interactive repair tool.
|
|
11
|
+
|
|
12
|
+
## Step 1 — Pre-flight
|
|
13
|
+
|
|
14
|
+
- Print: "`/init-project doctor` — checking baseline integrity. Each detected violation is presented separately; you confirm each fix via AskUserQuestion."
|
|
15
|
+
- Verify the project is configured: `.claude/project.json → configured == true`. If false, halt with: "Run `/init-project` first; the project is in agnostic mode."
|
|
16
|
+
- Verify `python3` and `node` available; halt with one-line missing-dep message if not.
|
|
17
|
+
|
|
18
|
+
## Step 2 — Check `.claude/workflows.jsonl` presence
|
|
19
|
+
|
|
20
|
+
- If `.claude/workflows.jsonl` is missing on disk:
|
|
21
|
+
- AskUserQuestion: "`.claude/workflows.jsonl` missing. Restore from pristine template (`src/.claude/workflows.template.jsonl`)?"
|
|
22
|
+
- Options: `Restore` | `Skip` | `Show diff`
|
|
23
|
+
- On `Restore`: `cp src/.claude/workflows.template.jsonl .claude/workflows.jsonl`. Log to `.claude/state/init/doctor-<timestamp>.log`.
|
|
24
|
+
- On `Skip`: note in report; proceed.
|
|
25
|
+
|
|
26
|
+
## Step 3 — Check `.claude/schemas/` presence
|
|
27
|
+
|
|
28
|
+
- If `.claude/schemas/workflow-track.v1.json` is missing:
|
|
29
|
+
- AskUserQuestion: "`.claude/schemas/workflow-track.v1.json` missing. Restore from `src/.claude/schemas/`?"
|
|
30
|
+
- Apply on `Restore` (recursive cp).
|
|
31
|
+
|
|
32
|
+
## Step 4 — Validate workflows.jsonl against §18 schema + invariants
|
|
33
|
+
|
|
34
|
+
- Run `node .claude/skills/triage/seed-tasklist.mjs --validate-only`. The helper exits 0 on success or non-zero with a named-error report on failure.
|
|
35
|
+
- On validation failure, parse the helper's stderr for each error. For each:
|
|
36
|
+
- AskUserQuestion: "Violation: `<kind>` in track `<id>`: `<message>`. Options: `Show context`, `Skip` (mark as known), `Edit manually` (open file at line)."
|
|
37
|
+
- The doctor does NOT auto-fix schema/invariant violations — manual user judgment is required. Surface the violation context (track + node ids) and pause.
|
|
38
|
+
|
|
39
|
+
## Step 5 — Four-way mirror check (Article IV / §18)
|
|
40
|
+
|
|
41
|
+
Extract the §18 sections from `docs/init/seed.md` and `src/seed.template.md`. Extract Article IV sections from `CLAUDE.md` and `src/CLAUDE.template.md`. Byte-compare each pair.
|
|
42
|
+
|
|
43
|
+
- On §18 mirror drift:
|
|
44
|
+
- AskUserQuestion: "`docs/init/seed.md §18` differs from `src/seed.template.md §18`. Options: `Re-mirror docs→src`, `Re-mirror src→docs`, `Show diff`, `Skip`."
|
|
45
|
+
- Apply the chosen overwrite.
|
|
46
|
+
|
|
47
|
+
- Same pattern for Article IV mirror.
|
|
48
|
+
|
|
49
|
+
## Step 6 — `.claude/` tooling convention check (advisory)
|
|
50
|
+
|
|
51
|
+
Per seed.md §3 + `conventions.md → user-shipped-tooling-lives-in-claude-directory`, user-shipped baseline tooling lives under `.claude/`. The only project-root exceptions are `CLAUDE.md` and `.mcp.json`.
|
|
52
|
+
|
|
53
|
+
- Scan for shipped tooling at the project root that should live under `.claude/`. Heuristic: files matching `*.skill.md`, `*.workflow.json`, `*.hook.sh`, `*.command.md` at the project root.
|
|
54
|
+
- For each match:
|
|
55
|
+
- AskUserQuestion: "Convention violation: `<path>` at project root. Suggested target: `.claude/<subdir>/<filename>`. Move?"
|
|
56
|
+
- The doctor offers the move; the user confirms.
|
|
57
|
+
|
|
58
|
+
## Step 7 — Report + log
|
|
59
|
+
|
|
60
|
+
- Print a summary table:
|
|
61
|
+
- Checks run: N
|
|
62
|
+
- Fixes applied: M
|
|
63
|
+
- Skipped (user declined or manual fix required): K
|
|
64
|
+
- Remaining manual: L
|
|
65
|
+
- Write the full session record to `.claude/state/init/doctor-<UTC-timestamp>.log` (one line per check + action).
|
|
66
|
+
- If any check returned a manual-fix path (e.g., schema violation in workflows.jsonl), exit with code 1 so caller workflows treat the result as "drift remains". Otherwise exit 0.
|
|
67
|
+
|
|
68
|
+
## Constraints
|
|
69
|
+
|
|
70
|
+
- **Read-only by default; writes only on user confirmation.** Every Edit/Write happens after an AskUserQuestion `Apply` response. No silent fixes.
|
|
71
|
+
- **No commits.** The doctor's fixes land on the working tree. The user commits via the normal `/grant-commit` + `/commit` flow.
|
|
72
|
+
- **No new dependencies.** Validation reuses `src/cli/workflows-validator.js` via the triage helper.
|
|
73
|
+
- **Schema/invariant violations require manual fixes.** Auto-fixing structurally violates the user's intent (the violation might be intentional during development). Doctor surfaces; user fixes.
|
|
74
|
+
- **Mirror drift CAN be auto-fixed** (one-direction overwrite on confirmation). The reverse direction (which file is canonical?) is the user's call.
|
|
@@ -191,7 +191,20 @@ def compose_snapshot(transcript: Path, project_dir: Path, trigger: str) -> str:
|
|
|
191
191
|
workflow = _read_workflow(project_dir)
|
|
192
192
|
|
|
193
193
|
slug = workflow.get("slug") or "(none)"
|
|
194
|
-
|
|
194
|
+
# Post-§18: workflow.json carries `track_id`; legacy pre-§18 files carry
|
|
195
|
+
# `entry_phase`. Accept both. Map reverses
|
|
196
|
+
# `src/cli/workflow-migrator.js → ENTRY_PHASE_TO_TRACK_ID`.
|
|
197
|
+
_TRACK_ID_TO_ENTRY_PHASE = {
|
|
198
|
+
"intake-full": "intake",
|
|
199
|
+
"spec-entry": "spec",
|
|
200
|
+
"tdd-quickfix": "tdd",
|
|
201
|
+
"chore": "chore",
|
|
202
|
+
}
|
|
203
|
+
entry_phase = (
|
|
204
|
+
workflow.get("entry_phase")
|
|
205
|
+
or _TRACK_ID_TO_ENTRY_PHASE.get(workflow.get("track_id"))
|
|
206
|
+
or "(unknown)"
|
|
207
|
+
)
|
|
195
208
|
completed = workflow.get("completed") or []
|
|
196
209
|
exceptions = workflow.get("exceptions") or []
|
|
197
210
|
phases = workflow.get("phases") or []
|
|
@@ -189,6 +189,30 @@ if pending_count > 0 and not active_workflow:
|
|
|
189
189
|
'run `/memory-flush` to clear before starting new work.'
|
|
190
190
|
)
|
|
191
191
|
|
|
192
|
+
# Pending upgrade stages (tier1-merge-option AC-004 + AC-008). Scans
|
|
193
|
+
# .claude/state/upgrade/*/manifest.json for entries with status: PENDING.
|
|
194
|
+
# Fires regardless of active_workflow (design pick 2C): stages are stable
|
|
195
|
+
# infrastructure debt, distinct from memory-candidate debt above.
|
|
196
|
+
upgrade_pending = 0
|
|
197
|
+
upgrade_root = root / '.claude/state/upgrade'
|
|
198
|
+
if upgrade_root.is_dir():
|
|
199
|
+
for stage_manifest in upgrade_root.glob('*/manifest.json'):
|
|
200
|
+
try:
|
|
201
|
+
with open(stage_manifest) as f:
|
|
202
|
+
stage = json.load(f)
|
|
203
|
+
except Exception:
|
|
204
|
+
continue
|
|
205
|
+
for entry in stage.get('files', []):
|
|
206
|
+
if entry.get('status') == 'PENDING':
|
|
207
|
+
upgrade_pending += 1
|
|
208
|
+
|
|
209
|
+
if upgrade_pending > 0:
|
|
210
|
+
noun = 'file' if upgrade_pending == 1 else 'files'
|
|
211
|
+
lines.append(
|
|
212
|
+
f'**{upgrade_pending} {noun} staged for /upgrade-project to reconcile** — '
|
|
213
|
+
'run `/upgrade-project` when ready.'
|
|
214
|
+
)
|
|
215
|
+
|
|
192
216
|
lines.append('')
|
|
193
217
|
lines.append(
|
|
194
218
|
'Files are read on demand by the relevant skill (scout reads landmarks, research reads libraries, etc.). '
|
|
@@ -54,7 +54,17 @@ except Exception:
|
|
|
54
54
|
phases = pj.get("workflow", {}).get("phases") or []
|
|
55
55
|
artifacts = pj.get("workflow", {}).get("artifacts") or {}
|
|
56
56
|
exceptions = set(ws.get("exceptions") or [])
|
|
57
|
-
|
|
57
|
+
# Post-§18: workflow.json carries `track_id`; legacy pre-§18 files carry
|
|
58
|
+
# `entry_phase`. Accept both. The canonical map below mirrors
|
|
59
|
+
# `src/cli/workflow-migrator.js → ENTRY_PHASE_TO_TRACK_ID` in reverse so
|
|
60
|
+
# track_guard's phase-ordering enforcement keeps working on both shapes.
|
|
61
|
+
_TRACK_ID_TO_ENTRY_PHASE = {
|
|
62
|
+
"intake-full": "intake",
|
|
63
|
+
"spec-entry": "spec",
|
|
64
|
+
"tdd-quickfix": "tdd",
|
|
65
|
+
"chore": "chore",
|
|
66
|
+
}
|
|
67
|
+
entry = ws.get("entry_phase") or _TRACK_ID_TO_ENTRY_PHASE.get(ws.get("track_id"))
|
|
58
68
|
|
|
59
69
|
# Find which phase this file belongs to.
|
|
60
70
|
file_phase = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
|
-
"generated_at": "2026-05-
|
|
3
|
+
"generated_at": "2026-05-22T13:30:10.925Z",
|
|
4
4
|
"files": {
|
|
5
5
|
".claude/agents/swarm-worker.md": {
|
|
6
6
|
"sha256": "1735a220f268c9765cb22e0567b728803f2edd7776cbde51dd017a9f062ae41f",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"sha256": "770e8bc3bf1097ecdf92b86dcf6e0cf7ef3a3251b73bf35cc0385f2e2d552319",
|
|
31
31
|
"tier": "MECHANICAL"
|
|
32
32
|
},
|
|
33
|
+
".claude/commands/init-project-doctor.md": {
|
|
34
|
+
"sha256": "c71bcc88aaf77095dd87ffc88a1f79ad731607623240cfb9125bf8b074425897",
|
|
35
|
+
"tier": "MECHANICAL"
|
|
36
|
+
},
|
|
33
37
|
".claude/commands/init-project.md": {
|
|
34
38
|
"sha256": "222f02f65ea639c904c43114642f11422a56d8dab8c1c2786b5876e17d3b0155",
|
|
35
39
|
"tier": "MECHANICAL"
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
"tier": "MECHANICAL"
|
|
68
72
|
},
|
|
69
73
|
".claude/hooks/lib/resume_writer.py": {
|
|
70
|
-
"sha256": "
|
|
74
|
+
"sha256": "2811861400c3afbfcb57df6c0889676abda0716e5acf35a2b0ba9410d44d6d45",
|
|
71
75
|
"tier": "MECHANICAL"
|
|
72
76
|
},
|
|
73
77
|
".claude/hooks/lint_runner.sh": {
|
|
@@ -79,7 +83,7 @@
|
|
|
79
83
|
"tier": "MECHANICAL"
|
|
80
84
|
},
|
|
81
85
|
".claude/hooks/memory_session_start.sh": {
|
|
82
|
-
"sha256": "
|
|
86
|
+
"sha256": "ec03026919c3cfeb0bdb8e46d8ace19b23d93b5b21f1ebdb4f579e9c52293ac9",
|
|
83
87
|
"tier": "MECHANICAL"
|
|
84
88
|
},
|
|
85
89
|
".claude/hooks/memory_stop.sh": {
|
|
@@ -151,7 +155,7 @@
|
|
|
151
155
|
"tier": "MECHANICAL"
|
|
152
156
|
},
|
|
153
157
|
".claude/hooks/track_guard.sh": {
|
|
154
|
-
"sha256": "
|
|
158
|
+
"sha256": "403f7cb1f29cbb7fb25ce96c5ea93a31f597fbc11ba7cfa2e313804110f44e75",
|
|
155
159
|
"tier": "MECHANICAL"
|
|
156
160
|
},
|
|
157
161
|
".claude/hooks/verify_pass_guard.sh": {
|
|
@@ -202,6 +206,10 @@
|
|
|
202
206
|
"sha256": "a81f9c1341a15831fe8dd558e376dfe38d5fd938aac6291a4c59529637a8d2c7",
|
|
203
207
|
"tier": "NEVER_TOUCH"
|
|
204
208
|
},
|
|
209
|
+
".claude/schemas/workflow-track.v1.json": {
|
|
210
|
+
"sha256": "d012a5eaea66b6172f05a1f9ed22ee14436e900372ed2653124e4a9ff1ef26e1",
|
|
211
|
+
"tier": "NEVER_TOUCH"
|
|
212
|
+
},
|
|
205
213
|
".claude/settings.json": {
|
|
206
214
|
"sha256": "feb7d2c004b6c12cef6410d54db8ad0abc818b2aa16b1942cfdb72808c21b30d",
|
|
207
215
|
"tier": "BINARY_PROMPT"
|
|
@@ -219,7 +227,7 @@
|
|
|
219
227
|
"tier": "MECHANICAL"
|
|
220
228
|
},
|
|
221
229
|
".claude/skills/audit-baseline/audit.sh": {
|
|
222
|
-
"sha256": "
|
|
230
|
+
"sha256": "6d799ea8b567ecf91757fa142f72795b1da0b4d8443e54b4d233dad5b98b5dab",
|
|
223
231
|
"tier": "MECHANICAL"
|
|
224
232
|
},
|
|
225
233
|
".claude/skills/audit-baseline/tests/fixtures/_pending_opener_only.md": {
|
|
@@ -307,7 +315,7 @@
|
|
|
307
315
|
"tier": "MECHANICAL"
|
|
308
316
|
},
|
|
309
317
|
".claude/skills/chore/SKILL.md": {
|
|
310
|
-
"sha256": "
|
|
318
|
+
"sha256": "88b2b8b29f0ab6ab4ad41fa823d3bd5a4d3f863b81e607ac69abbbd298eb6766",
|
|
311
319
|
"tier": "MECHANICAL"
|
|
312
320
|
},
|
|
313
321
|
".claude/skills/claude-automation-recommender/LICENSE": {
|
|
@@ -414,72 +422,8 @@
|
|
|
414
422
|
"sha256": "456160c1a3398cfece91b6696d0c7f1fcb1196ea5e101acb9a0e3050f2462a5d",
|
|
415
423
|
"tier": "MECHANICAL"
|
|
416
424
|
},
|
|
417
|
-
".claude/skills/google-analytics/SKILL.md": {
|
|
418
|
-
"sha256": "f5d8c52c103e4e1bdbb6bfdda962aad198064ced701c20df753d77ba4603547c",
|
|
419
|
-
"tier": "MECHANICAL"
|
|
420
|
-
},
|
|
421
|
-
".claude/skills/google-analytics/references/audiences.md": {
|
|
422
|
-
"sha256": "cdae62b0f40e82a60f96a6bd0e77798c6118beaebe812961e8c9d4c3242b227f",
|
|
423
|
-
"tier": "MECHANICAL"
|
|
424
|
-
},
|
|
425
|
-
".claude/skills/google-analytics/references/bigquery.md": {
|
|
426
|
-
"sha256": "fadc3efdd200a0bc43df4b698d46bc93e82111d8553b363d1e49ceb15bcdffce",
|
|
427
|
-
"tier": "MECHANICAL"
|
|
428
|
-
},
|
|
429
|
-
".claude/skills/google-analytics/references/custom-dimensions.md": {
|
|
430
|
-
"sha256": "ac9e88c69fd8eb2a0bf1ae8f3daac42c6d92caa338ce2fa77a50bf2fe947dbc4",
|
|
431
|
-
"tier": "MECHANICAL"
|
|
432
|
-
},
|
|
433
|
-
".claude/skills/google-analytics/references/custom-events.md": {
|
|
434
|
-
"sha256": "442ce8c1e7d89cb2206a85b02b287748e3e226d67cab571bc6f2a3ea520bc434",
|
|
435
|
-
"tier": "MECHANICAL"
|
|
436
|
-
},
|
|
437
|
-
".claude/skills/google-analytics/references/data-management.md": {
|
|
438
|
-
"sha256": "1f9e80e0855937dc082d63535188fc1e7547273e626d0a3ef03c0487b42045bb",
|
|
439
|
-
"tier": "MECHANICAL"
|
|
440
|
-
},
|
|
441
|
-
".claude/skills/google-analytics/references/debugview.md": {
|
|
442
|
-
"sha256": "f2b050db37b7927de99b0196deb7cb94d8ecb1a6668c9e08bec4f57816646e90",
|
|
443
|
-
"tier": "MECHANICAL"
|
|
444
|
-
},
|
|
445
|
-
".claude/skills/google-analytics/references/events-fundamentals.md": {
|
|
446
|
-
"sha256": "acdeb349be2f468ba634d686691aeda0ce932db93b4872b9cd35685dcd3f31cf",
|
|
447
|
-
"tier": "MECHANICAL"
|
|
448
|
-
},
|
|
449
|
-
".claude/skills/google-analytics/references/gtag.md": {
|
|
450
|
-
"sha256": "bef0556071bc645656d0634c26c3bad20d39517cb14689bb11e9d9bedf4f6ab8",
|
|
451
|
-
"tier": "MECHANICAL"
|
|
452
|
-
},
|
|
453
|
-
".claude/skills/google-analytics/references/gtm-integration.md": {
|
|
454
|
-
"sha256": "3c95c7b64fbbd688907cd558c3c4d265b99c7178284b97e376334d802d11c860",
|
|
455
|
-
"tier": "MECHANICAL"
|
|
456
|
-
},
|
|
457
|
-
".claude/skills/google-analytics/references/measurement-protocol.md": {
|
|
458
|
-
"sha256": "a5b644a5ca586173e399c229a47aad571991389232320a0f9e6baf1d4be619fb",
|
|
459
|
-
"tier": "MECHANICAL"
|
|
460
|
-
},
|
|
461
|
-
".claude/skills/google-analytics/references/privacy.md": {
|
|
462
|
-
"sha256": "09e2db4ce4d990f4f1ff51c0e3bca08a364cba711f83f48103f69f9db427fa18",
|
|
463
|
-
"tier": "MECHANICAL"
|
|
464
|
-
},
|
|
465
|
-
".claude/skills/google-analytics/references/recommended-events.md": {
|
|
466
|
-
"sha256": "0dccd2084060bfb3fd28476b9c0c9a6e2b8f51ce57ecf4fc32d7f82a8964b1b4",
|
|
467
|
-
"tier": "MECHANICAL"
|
|
468
|
-
},
|
|
469
|
-
".claude/skills/google-analytics/references/reporting.md": {
|
|
470
|
-
"sha256": "37cb7cfd1dd547e86a41664ffe13893ef138194a2288d1a2c43c9195e8ec609f",
|
|
471
|
-
"tier": "MECHANICAL"
|
|
472
|
-
},
|
|
473
|
-
".claude/skills/google-analytics/references/setup.md": {
|
|
474
|
-
"sha256": "26743b72341a5658e73c1f070b924de0f11b1681af06164cb13c19f2047a1087",
|
|
475
|
-
"tier": "MECHANICAL"
|
|
476
|
-
},
|
|
477
|
-
".claude/skills/google-analytics/references/user-tracking.md": {
|
|
478
|
-
"sha256": "5a945df2a575291c6b35d24830b497915c82a843a93ee133577f1deda93f6d75",
|
|
479
|
-
"tier": "MECHANICAL"
|
|
480
|
-
},
|
|
481
425
|
".claude/skills/harness/SKILL.md": {
|
|
482
|
-
"sha256": "
|
|
426
|
+
"sha256": "9ddcc243fc72c48c205dc688094d6305f7969969b4b0f899bab428e1abdb1ce3",
|
|
483
427
|
"tier": "MECHANICAL"
|
|
484
428
|
},
|
|
485
429
|
".claude/skills/humanizer/LICENSE": {
|
|
@@ -723,7 +667,7 @@
|
|
|
723
667
|
"tier": "MECHANICAL"
|
|
724
668
|
},
|
|
725
669
|
".claude/skills/intake/SKILL.md": {
|
|
726
|
-
"sha256": "
|
|
670
|
+
"sha256": "7f73e8ee3f3a5bc6e7e29f814e4820a09f2c12644d54ae45314dc733f188aab2",
|
|
727
671
|
"tier": "MECHANICAL"
|
|
728
672
|
},
|
|
729
673
|
".claude/skills/intake/template.md": {
|
|
@@ -746,26 +690,6 @@
|
|
|
746
690
|
"sha256": "5eec4486cfda45d2ce5987d6286bf61b96f816ebdd9041bc9ba0207cf00abd4b",
|
|
747
691
|
"tier": "MECHANICAL"
|
|
748
692
|
},
|
|
749
|
-
".claude/skills/optimize-seo/SKILL.md": {
|
|
750
|
-
"sha256": "b389dc604346220d5a0a59c8f41c058c192c58a35bbff831fbc4c7f9e8c1b386",
|
|
751
|
-
"tier": "MECHANICAL"
|
|
752
|
-
},
|
|
753
|
-
".claude/skills/optimize-seo/scripts/pagespeed.mjs": {
|
|
754
|
-
"sha256": "8bef62078833139f9175c175339d1fc0eb635a5eeaa2a3100543928ef91869e4",
|
|
755
|
-
"tier": "MECHANICAL"
|
|
756
|
-
},
|
|
757
|
-
".claude/skills/pagespeed-insights/LICENSE.md": {
|
|
758
|
-
"sha256": "10ee2ded8c2ae373a65aacfa51f2bf540d5f20d418fc7a5595a5ccb06cde2738",
|
|
759
|
-
"tier": "MECHANICAL"
|
|
760
|
-
},
|
|
761
|
-
".claude/skills/pagespeed-insights/SKILL.md": {
|
|
762
|
-
"sha256": "ab53af083929fbb28af0ad2c9ee1fcc51dec63c642ebc237c475b3ea9bde7c59",
|
|
763
|
-
"tier": "MECHANICAL"
|
|
764
|
-
},
|
|
765
|
-
".claude/skills/pagespeed-insights/reference.md": {
|
|
766
|
-
"sha256": "afa03220b772ea8d6393f7366bbd6d90200c0b56585ccb2bb714e622af07345f",
|
|
767
|
-
"tier": "MECHANICAL"
|
|
768
|
-
},
|
|
769
693
|
".claude/skills/prose/SKILL.md": {
|
|
770
694
|
"sha256": "7cfc7d4fd34d7256367eedf17c5f5b5cdb67baec72033f905dcfb715366a1849",
|
|
771
695
|
"tier": "MECHANICAL"
|
|
@@ -839,7 +763,7 @@
|
|
|
839
763
|
"tier": "MECHANICAL"
|
|
840
764
|
},
|
|
841
765
|
".claude/skills/swarm-plan/SKILL.md": {
|
|
842
|
-
"sha256": "
|
|
766
|
+
"sha256": "cf0f60a10377e5913e327190c67ea7bf6ce978356c81b0572a3bd0078ffbe81e",
|
|
843
767
|
"tier": "MECHANICAL"
|
|
844
768
|
},
|
|
845
769
|
".claude/skills/swarm-plan/validate.sh": {
|
|
@@ -847,7 +771,7 @@
|
|
|
847
771
|
"tier": "MECHANICAL"
|
|
848
772
|
},
|
|
849
773
|
".claude/skills/tdd/SKILL.md": {
|
|
850
|
-
"sha256": "
|
|
774
|
+
"sha256": "717ef6297934be3a1c2efb5fd6beb434dbca9eeeb4356ae7ada85c80555fde01",
|
|
851
775
|
"tier": "MECHANICAL"
|
|
852
776
|
},
|
|
853
777
|
".claude/skills/tdd/drift_check.py": {
|
|
@@ -891,27 +815,35 @@
|
|
|
891
815
|
"tier": "MECHANICAL"
|
|
892
816
|
},
|
|
893
817
|
".claude/skills/triage/SKILL.md": {
|
|
894
|
-
"sha256": "
|
|
818
|
+
"sha256": "6a5790c692ee03975a50956b2b1e0da7447f00c15378a0f0e69332403906e9b7",
|
|
819
|
+
"tier": "MECHANICAL"
|
|
820
|
+
},
|
|
821
|
+
".claude/skills/triage/seed-tasklist.mjs": {
|
|
822
|
+
"sha256": "0459f1862f5c4cf500d5cf2b66dbcfa3874843306c10f5f915b0670999b0753b",
|
|
895
823
|
"tier": "MECHANICAL"
|
|
896
824
|
},
|
|
897
825
|
".claude/skills/upgrade-project/SKILL.md": {
|
|
898
|
-
"sha256": "
|
|
826
|
+
"sha256": "a8d31370b626bb2c5fb733cf3b1e210f66ade1de84007ad0b3a46e31d115687a",
|
|
899
827
|
"tier": "MECHANICAL"
|
|
900
828
|
},
|
|
901
829
|
".claude/skills/verify/SKILL.md": {
|
|
902
830
|
"sha256": "fcddba67cf7f3623fc8f8ae142303b16b9db0c9fc1652bc920e16c56fe4c7864",
|
|
903
831
|
"tier": "MECHANICAL"
|
|
904
832
|
},
|
|
833
|
+
".claude/workflows.jsonl": {
|
|
834
|
+
"sha256": "e6a9bd01388b34a15758c8956df5986c917508d65bacef49a444079112da4090",
|
|
835
|
+
"tier": "NEVER_TOUCH"
|
|
836
|
+
},
|
|
905
837
|
".mcp.json": {
|
|
906
838
|
"sha256": "8ebb7966045486187bbdf9bac643e690c4fbc7a9a70a8345e3665ba72fa19b96",
|
|
907
839
|
"tier": "SPECIAL_MERGE"
|
|
908
840
|
},
|
|
909
841
|
"CLAUDE.md": {
|
|
910
|
-
"sha256": "
|
|
842
|
+
"sha256": "03023db4f879d3ee4ce37c8824676bab2cc999d4dd4d011bfdbe997f52c5f915",
|
|
911
843
|
"tier": "SEMANTIC"
|
|
912
844
|
},
|
|
913
845
|
"docs/init/seed.md": {
|
|
914
|
-
"sha256": "
|
|
846
|
+
"sha256": "7c64057392b39289edf123e3395b67b8605c28b9ab35c102c9469f6974047c78",
|
|
915
847
|
"tier": "SEMANTIC"
|
|
916
848
|
}
|
|
917
849
|
},
|
|
@@ -957,5 +889,5 @@
|
|
|
957
889
|
"verify": "baseline"
|
|
958
890
|
}
|
|
959
891
|
},
|
|
960
|
-
"build_id": "gha-
|
|
892
|
+
"build_id": "gha-26290648827"
|
|
961
893
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "./workflow-track.v1.json",
|
|
4
|
+
"title": "Workflow Track v1",
|
|
5
|
+
"description": "One Track record per line in .claude/workflows.jsonl. The Article IV invariants I1..I11 are enforced at runtime by src/cli/workflows-validator.js, NOT by JSON Schema alone — schema validation is structural; invariant validation is semantic. See docs/init/seed.md §17 for the full semantic contract.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["$schema", "track_id", "name", "description", "selectable", "selector_hints", "preconditions", "invariants", "nodes"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "type": "string" },
|
|
11
|
+
"track_id": { "type": "string", "minLength": 1 },
|
|
12
|
+
"name": { "type": "string", "minLength": 1 },
|
|
13
|
+
"description": { "type": "string" },
|
|
14
|
+
"selectable": { "type": "boolean" },
|
|
15
|
+
"selector_hints": { "type": "array", "items": { "type": "string" } },
|
|
16
|
+
"preconditions": { "type": "array", "items": { "$ref": "#/$defs/Predicate" } },
|
|
17
|
+
"invariants": { "type": "array", "items": { "enum": ["commits", "requires_spec", "requires_swarm", "chore", "git_only"] } },
|
|
18
|
+
"nodes": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/Node" } }
|
|
19
|
+
},
|
|
20
|
+
"$defs": {
|
|
21
|
+
"Predicate": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"required": ["name"],
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"properties": {
|
|
26
|
+
"name": { "enum": ["requires_git", "requires_user_override", "requires_min_components", "requires_phase_completed", "requires_skill_present"] },
|
|
27
|
+
"argument": { "type": "string" }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"Node": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"required": ["id", "type", "depends_on", "blocks", "can_parallel", "needs_user"],
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"properties": {
|
|
35
|
+
"id": { "type": "string", "minLength": 1 },
|
|
36
|
+
"type": { "enum": ["task", "selector"] },
|
|
37
|
+
"skill": { "type": "string" },
|
|
38
|
+
"sub_track": { "type": "string" },
|
|
39
|
+
"alternates": { "type": "array", "items": { "$ref": "#/$defs/Alternate" } },
|
|
40
|
+
"input": { "type": "string" },
|
|
41
|
+
"invocation_prompt": { "type": "string" },
|
|
42
|
+
"output": { "type": "string" },
|
|
43
|
+
"output_formatter_prompt": { "type": "string" },
|
|
44
|
+
"depends_on": { "type": "array", "items": { "type": "string" } },
|
|
45
|
+
"blocks": { "type": "array", "items": { "type": "string" } },
|
|
46
|
+
"can_parallel": { "type": "boolean" },
|
|
47
|
+
"needs_user": { "type": "boolean" },
|
|
48
|
+
"activeForm": { "type": "string" },
|
|
49
|
+
"metadata": { "type": "object" }
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"Alternate": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"required": ["preconditions"],
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"properties": {
|
|
57
|
+
"skill": { "type": "string" },
|
|
58
|
+
"sub_track": { "type": "string" },
|
|
59
|
+
"preconditions": { "type": "array", "items": { "$ref": "#/$defs/Predicate" } },
|
|
60
|
+
"description": { "type": "string" }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -80,7 +80,7 @@ def read_skill_owner(slug):
|
|
|
80
80
|
m = re.search(r'^owner:\s*(\S+)\s*$', fm.group(1), re.MULTILINE)
|
|
81
81
|
return m.group(1) if m else None
|
|
82
82
|
|
|
83
|
-
EXPECTED_COMMANDS = {"approve-spec", "approve-swarm", "grant-commit", "grant-push", "init-project"}
|
|
83
|
+
EXPECTED_COMMANDS = {"approve-spec", "approve-swarm", "grant-commit", "grant-push", "init-project", "init-project-doctor"}
|
|
84
84
|
|
|
85
85
|
EXPECTED_MEMORY_FILES = {
|
|
86
86
|
# Canonical files (seven)
|
|
@@ -186,7 +186,7 @@ skills_claimed = find_count(
|
|
|
186
186
|
r"\b(\d+|twenty-(?:four|five|six|seven|eight|nine)|"
|
|
187
187
|
r"thirty|thirty-(?:one|two|three|four|five|six|seven|eight|nine)|forty)\s+skills?\b")
|
|
188
188
|
gates_claimed = find_count(r"\b(\d+|three)\s+consent\s+gates?\b")
|
|
189
|
-
cmds_claimed = 5 if re.search(r"four\s+consent\s+gates?\s*\+\s*one\s+bootstrap", seed, re.IGNORECASE) else None
|
|
189
|
+
cmds_claimed = 6 if re.search(r"four\s+consent\s+gates?\s*\+\s*one\s+bootstrap\s*\+\s*one\s+doctor", seed, re.IGNORECASE) else (5 if re.search(r"four\s+consent\s+gates?\s*\+\s*one\s+bootstrap", seed, re.IGNORECASE) else None)
|
|
190
190
|
|
|
191
191
|
def check_count(label, claimed, actual):
|
|
192
192
|
if claimed is None:
|