feat(skills): /new-project 4-phase pipeline

Hub-and-spoke orchestrator for RULE 0.12 at project scale. SKILL.md
indexes 4 phase files: intake, fork-skeleton, parallel-exec, merge-
ceremony.

Flow:
  Phase 1 — 1 free-text line (GOAL) + 1 batch of 5 AskUserQuestion
            (type, theory, fanout, main-agent, DB mode).
  Phase 2 — project/<slug> branch, kei-ledger fork root, theoretical
            sub-agent spawn confirmation click.
  Phase 3 — poll kei-ledger list --status running, aggregate
            progress.json, steering click (continue / add / kill /
            merge / pause).
  Phase 4 — kei-ledger validate per bundle, per-branch merge verdict
            click (merge --no-ff / squash / reject / defer), final
            integration + NO-DOWNGRADE close click if any rejected /
            deferred.

>=6 AskUserQuestion calls minimum (1 batch Phase 1 + 1 Phase 2 + 1
Phase 3 + >=2 per-branch Phase 4 + 1 close).

Constructor Pattern: SKILL.md 109 LOC, phase files 80-108 LOC each —
all under 150 LOC.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Parfii-bot 2026-04-21 20:52:49 +08:00
parent cc8d1868be
commit 4178147b0f
5 changed files with 483 additions and 0 deletions

109
skills/new-project/SKILL.md Normal file
View file

@ -0,0 +1,109 @@
---
name: new-project
description: 4-phase pipeline for bootstrapping a new multi-agent project — intake, fork skeleton (branch + ledger row + sub-agent spawn), parallel execution with progress aggregation, and per-branch merge ceremony. Implements RULE 0.12 (agent git-model) at project scale. Hub-and-spoke — each phase lives in its own file and is executed in order.
argument-hint: <project name or one-line goal>
---
# New-Project — 4-Phase Pipeline (index)
You are bootstrapping a **new project** — research, code, theoretical, or
hybrid — that will run as a **main agent plus N parallel sub-agents** with
full git-model compliance (branch + 6-file artefact bundle + ledger row +
merge ceremony). This skill is the orchestrator wrapper; each phase lives
in its own file.
This skill does NOT itself write production code. It routes to
`compose-solution` (for each sub-task that needs a kit artefact) and to
`new-agent` (for each new specialist spawn) and records every fork in the
`kei-ledger` SQLite SSoT. Final merge decisions are user clicks.
---
## Pipeline overview (4 phases + final report)
| Phase | File | Purpose | Free-text? | AskUserQuestion |
|---|---|---|---|---|
| 1 | [phase-1-intake.md](phase-1-intake.md) | Project-shape intake (type / theory / parallelism / main-agent / DB) | 1 line (`GOAL`) | 1× batch of 5 questions |
| 2 | [phase-2-fork-skeleton.md](phase-2-fork-skeleton.md) | Create `project/<slug>` branch, ledger entry, theoretical sub-agent spawn | no | 1× (sub-agent kind confirm) |
| 3 | [phase-3-parallel-exec.md](phase-3-parallel-exec.md) | Poll `kei-ledger list --status running`, aggregate `progress.json` | no | 1× (continue / pause / add agent) |
| 4 | [phase-4-merge-ceremony.md](phase-4-merge-ceremony.md) | Per-branch merge decision — squash / no-ff / reject / defer | no | ≥ 1× per branch (multi-select) |
Minimum AskUserQuestion count across a full session: **≥ 6** — one batch
of five questions in Phase 1, one per spawn confirmation in Phase 2, one
polling click in Phase 3, and one per sub-branch in Phase 4 (≥ 2 branches
assumed). This is the pure-click contract: only the goal statement is
free-text.
---
## Variables the pipeline produces
| Name | Set in | Meaning |
|---|---|---|
| `GOAL` | Phase 1a | One-line project description |
| `PROJECT_TYPE` | Phase 1b | new-code / research / theoretical / hybrid / documentation |
| `THEORY_PART` | Phase 1b | none / math-derivation / prior-art / architecture-spec / paradigm-analysis |
| `FANOUT` | Phase 1b | single / up-to-3 / up-to-5 / up-to-10 |
| `MAIN_AGENT` | Phase 1b | meta-orchestrator / spawn specialist / compose-solution decides |
| `DB_MODE` | Phase 1b | file-only / sqlite-ledger / external-tool |
| `PROJECT_SLUG` | Phase 2a | kebab-case slug derived from `GOAL` |
| `PROJECT_BRANCH` | Phase 2a | `project/<slug>` |
| `LEDGER_ID` | Phase 2b | agent id issued via `kei-ledger fork` |
| `SUB_AGENTS` | Phase 2c | list of `{id, branch, kind}` spawned |
| `PROGRESS` | Phase 3 | per-sub-agent `{status, pct, last_summary}` aggregated |
| `MERGE_PLAN` | Phase 4 | per-branch verdict (merge / squash / reject / defer) |
---
## Final report (emit after Phase 4)
```
=== NEW-PROJECT REPORT ===
Goal: <first 80 chars of GOAL>...
Project slug: <PROJECT_SLUG>
Project branch: <PROJECT_BRANCH>
Ledger root id: <LEDGER_ID>
Sub-agents: <N spawned, M done, K failed>
Merge verdicts: <a merged / b squashed / c rejected / d deferred>
Artefact bundle: <per sub-agent 6/6 present / missing list>
Next action: <push / open PR / rerun failed / review deferred>
```
---
## Rules (apply throughout — enforced at every phase)
- **Pure-click contract.** Only `GOAL` (Phase 1a) is typed. Every other
decision is an `AskUserQuestion` call.
- **NO DOWNGRADE (RULE -1).** Any phase that fails returns 2-3 constructive
paths, never "can't be done". E.g. Phase 2 branch-conflict → (A) rename
slug, (B) force new branch off HEAD, (C) abort — user clicks.
- **NO HALLUCINATION (RULE 0.4).** Every sub-agent kind referenced MUST
exist in `_manifests/` or be scheduled for creation via `new-agent`
before Phase 3 polling.
- **Plan Mode First (RULE 0.5).** This skill IS the plan; each phase file
has its own verify-criterion. No Edit/Write to production scope before
the corresponding phase's confirm click.
- **Constructor Pattern (RULE ZERO).** `SKILL.md` < 200 LOC, phase files
< 150 LOC each.
- **RULE 0.12 compliance.** Every sub-agent spawn MUST:
1. Create `project/<slug>/agent-<id>` branch OR worktree
2. `kei-ledger fork <id> <branch> --parent <project-branch> --spec-sha <sha>`
3. Produce 6-file bundle in `.claude/agents/<id>/`: spec.md, plan.md,
progress.json, chatlog.md, handoffs.md, review.md
4. `kei-ledger done <id>` OR `kei-ledger fail <id>` on completion
5. `kei-ledger validate` before merge ceremony
- **Surgical scope.** new-project writes only to: ledger DB, `.claude/agents/<id>/`
bundles it orchestrates, and a project manifest file it creates under
`_manifests/project-<slug>.toml` if Phase 1b `MAIN_AGENT != "compose-solution decides"`.
---
## References
- [phase-1-intake.md](phase-1-intake.md) · [phase-2-fork-skeleton.md](phase-2-fork-skeleton.md) · [phase-3-parallel-exec.md](phase-3-parallel-exec.md) · [phase-4-merge-ceremony.md](phase-4-merge-ceremony.md)
- `skills/compose-solution/SKILL.md` — per-sub-task kit-artefact composer
- `skills/new-agent/SKILL.md` — 8-phase specialist manifest wizard
- `_primitives/_rust/kei-ledger/` — SQLite ledger CLI (`kei-ledger init / fork / done / fail / list / tree / validate`)
- `hooks/agent-fork-logger.sh` — PreToolUse:Agent advisory logger (auto-fork row)
- `~/.claude/rules/agent-git-model.md` — RULE 0.12 full text (fork / sub-fork / completion / merge ceremony)

View file

@ -0,0 +1,92 @@
# Phase 1 — Intake
One free-text line + one click batch of 5 questions. Only Phase 1a is typed.
## 1a — Ask for the project goal
Emit a regular message (NOT AskUserQuestion):
> Describe the project in one line: what do you want to produce / prove /
> ship, at what scope (feature / service / paper / proof)? Reply in one
> message. The main agent and sub-agents will read this verbatim.
Store the reply as `GOAL`. Derive `PROJECT_SLUG = kebab-case(first 4-6
meaningful words of GOAL)`, ≤ 40 chars, ASCII only.
## 1b — Shape click (AskUserQuestion, ONE batch of 5)
```json
{
"questions": [
{
"question": "Project type?",
"header": "Type",
"multiSelect": false,
"options": [
{"label": "new code", "description": "Greenfield implementation — ship a running artefact"},
{"label": "research", "description": "Empirical investigation — experiments + results doc"},
{"label": "theoretical", "description": "Math / physics / algorithmic derivation — proofs + chatlog"},
{"label": "hybrid", "description": "Code + theory in parallel — both tracks merged at end"},
{"label": "documentation", "description": "Docs-only project — no new runtime code"}
]
},
{
"question": "Theoretical component shape?",
"header": "Theory",
"multiSelect": false,
"options": [
{"label": "none", "description": "Pure-implementation project"},
{"label": "math derivation", "description": "Lemma → theorem chain, reviewed by physics-deriver"},
{"label": "prior-art research", "description": "Literature + existing-project sweep before any write"},
{"label": "architecture spec", "description": "Design document + interface contracts before code"},
{"label": "paradigm analysis", "description": "Observable classification + falsifier design (RULE 0.6)"}
]
},
{
"question": "Parallel sub-agent budget?",
"header": "Fanout",
"multiSelect": false,
"options": [
{"label": "single", "description": "Main agent only — sequential work, no sub-forks"},
{"label": "up to 3", "description": "Small fleet — typical feature work"},
{"label": "up to 5", "description": "Medium fleet — multi-track research or cross-cutting refactor"},
{"label": "up to 10", "description": "Wide fanout — parallel experiments / audits / prior-art sweeps"}
]
},
{
"question": "Main-agent role?",
"header": "Main",
"multiSelect": false,
"options": [
{"label": "meta-orchestrator", "description": "Generic orchestrator that only fans out and merges"},
{"label": "spawn specialist", "description": "Create a new dedicated agent via /new-agent before Phase 2"},
{"label": "compose-solution decides", "description": "Hand off project shape to /compose-solution for auto-routing"}
]
},
{
"question": "DB / ledger mirror?",
"header": "DB",
"multiSelect": false,
"options": [
{"label": "file-only", "description": "No SQLite — write bundle files only; skip kei-ledger"},
{"label": "SQLite ledger", "description": "Use kei-ledger (default — RULE 0.12 compliant)"},
{"label": "external tool", "description": "Mirror to another tracker (Jira / Linear / Forgejo issues)"}
]
}
]
}
```
Store answers as `PROJECT_TYPE`, `THEORY_PART`, `FANOUT`, `MAIN_AGENT`,
`DB_MODE`.
## Verify-criterion
- `GOAL` non-empty.
- `PROJECT_SLUG` matches `^[a-z0-9][a-z0-9-]{2,39}$`.
- All 5 click answers are exactly one of the labels above.
- If `MAIN_AGENT == "spawn specialist"` — Phase 2 begins with a handoff to
`/new-agent` before any ledger fork.
- If `DB_MODE == "file-only"` — Phase 2 skips the `kei-ledger fork` call
but STILL writes the 6-file bundle. Report this deviation in the final
report so the user sees the ledger SSoT was bypassed by explicit choice.

View file

@ -0,0 +1,94 @@
# Phase 2 — Fork Skeleton
Create the project branch, the root ledger entry, and the first
theoretical sub-agent spawn(s) per Phase 1's `THEORY_PART` choice.
## 2a — Project branch
Resolve `PROJECT_BRANCH = project/<PROJECT_SLUG>`.
Run (via Bash tool):
```sh
git fetch origin main
git checkout -b "$PROJECT_BRANCH" origin/main
```
Failure modes — emit a NO-DOWNGRADE recovery AskUserQuestion:
```json
{
"questions": [
{
"question": "Branch creation failed — how to proceed?",
"header": "Recovery",
"multiSelect": false,
"options": [
{"label": "rename slug", "description": "Use a suffix (-v2, -alt) and retry"},
{"label": "reuse existing branch", "description": "Check out the existing branch and append this work"},
{"label": "abort project", "description": "Stop before touching the ledger"}
]
}
]
}
```
## 2b — Ledger root entry
Skip when `DB_MODE == "file-only"`. Otherwise:
```sh
spec_sha=$(printf '%s' "$GOAL" | shasum -a 256 | cut -c1-16)
LEDGER_ID="project-${PROJECT_SLUG}-$(date +%s)"
kei-ledger init
kei-ledger fork "$LEDGER_ID" "$PROJECT_BRANCH" \
--parent main \
--spec-sha "$spec_sha"
```
Also write the root bundle under
`.claude/agents/$LEDGER_ID/{spec.md, plan.md, progress.json, chatlog.md, handoffs.md, review.md}`.
`spec.md` = `GOAL` + 5 Phase-1 answers; others start empty / scaffolded.
## 2c — Theoretical sub-agent spawn (AskUserQuestion, ONE)
Branch on `THEORY_PART`. Emit this confirmation click:
```json
{
"questions": [
{
"question": "Confirm theoretical sub-agent fan-out (derived from Phase 1)?",
"header": "Spawn",
"multiSelect": true,
"options": [
{"label": "physics-deriver", "description": "Math derivation agent (only if THEORY_PART = math derivation)"},
{"label": "research sweep", "description": "Prior-art research sub-agent (only if THEORY_PART = prior-art research)"},
{"label": "architect", "description": "Architecture spec agent (only if THEORY_PART = architecture spec)"},
{"label": "paradigm-classifier", "description": "Observable classification per RULE 0.6 (only if THEORY_PART = paradigm analysis)"},
{"label": "skip theory", "description": "No theoretical sub-agent — straight to implementation fan-out"}
]
}
]
}
```
For each selected label (except `skip theory`):
1. Derive `agent_id = <kind>-<ts>`, `agent_branch = project/$PROJECT_SLUG/agent-$agent_id`
2. `git worktree add .claude/worktrees/$agent_id -b $agent_branch` (when fanout > single)
3. `kei-ledger fork "$agent_id" "$agent_branch" --parent "$PROJECT_BRANCH" --spec-sha "$spec_sha"` (skip if file-only)
4. Invoke the Agent tool with the matching `subagent_type` and
`isolation: "worktree"` (the `agent-fork-logger.sh` hook will emit a
second fork row — OK, ledger de-duplicates by primary key and the hook
attempt returns nonzero silently)
5. Append `{id, branch, kind}` to `SUB_AGENTS`
## Verify-criterion
- `git branch --show-current` returns `$PROJECT_BRANCH`.
- `kei-ledger list --status running` returns ≥ 1 row whose id == `LEDGER_ID`
(unless `DB_MODE == "file-only"`).
- Every entry in `SUB_AGENTS` has a corresponding `kei-ledger list` row
with `parent_branch == $PROJECT_BRANCH`.
- If any spawn failed: emit NO-DOWNGRADE recovery click (retry / skip / abort).

View file

@ -0,0 +1,80 @@
# Phase 3 — Parallel Execution
Poll the ledger, aggregate progress, let the user steer the fleet mid-run.
## 3a — Aggregate current state
Every ~60s (or whenever the user asks "status"):
```sh
kei-ledger list --status running
kei-ledger list --status done
kei-ledger list --status failed
```
For each row, attempt to read
`.claude/agents/<id>/progress.json` (written by the child every ≥ 30s per
`feedback_agent_observability`). Shape:
```json
{
"pct": 0..100,
"last_step": "short free text",
"wall_time_s": int,
"last_updated": iso8601
}
```
Aggregate into `PROGRESS = {id: {status, pct, last_summary, stale_s}}`.
`stale_s = now - last_updated`. Flag `stale_s > 300` as "possibly hung".
Render one-line-per-agent table:
```
<id> <status> <pct>% <last_step> stale=<s>s
```
## 3b — Steering click (AskUserQuestion, ONE)
After displaying the table:
```json
{
"questions": [
{
"question": "Fleet state — how to proceed?",
"header": "Steer",
"multiSelect": false,
"options": [
{"label": "continue polling", "description": "Wait and re-poll — default if > 0 agents are running"},
{"label": "add sub-agent", "description": "Spawn another sub-agent — returns to Phase 2c"},
{"label": "kill stale", "description": "Call kei-ledger fail on agents with stale_s > 300"},
{"label": "proceed to merge", "description": "All required agents done — jump to Phase 4"},
{"label": "pause and review", "description": "Stop polling — user reviews manually, re-enter later"}
]
}
]
}
```
Route:
- `continue polling` → re-run 3a after a user-initiated "status" request
(do NOT busy-loop on a timer — let the user drive polling cadence)
- `add sub-agent` → jump to Phase 2c, add new row, return to Phase 3
- `kill stale` → for each `stale_s > 300` running row: `kei-ledger fail <id> --reason "stale > 300s, killed by orchestrator"`
- `proceed to merge` → Phase 4 (verify no `running` rows remain first)
- `pause and review` → emit final report with current state, user re-enters
the skill later (ledger survives)
## Verify-criterion
- Ledger-polling code actually called `kei-ledger list` at least once per
Phase-3 entry (unless `DB_MODE == "file-only"` — in which case the
orchestrator reads each `progress.json` directly).
- Every running sub-agent either has a fresh `progress.json`
(`stale_s < 300`) or has been flagged as "possibly hung" in the
displayed table.
- If `proceed to merge` is clicked while `kei-ledger list --status running`
is non-empty — block the transition and re-ask with the list shown.
- NO-DOWNGRADE: if every child has failed, DO NOT close the project silently.
Emit a 3-path recovery click (retry failed / re-fanout / abort with audit).

View file

@ -0,0 +1,108 @@
# Phase 4 — Merge Ceremony
Per-branch verdict, ledger bookkeeping, integration into the project
branch. One AskUserQuestion **per sub-agent branch** (therefore the
skill's AskUserQuestion floor rises with fanout).
## 4a — Validate bundles first
For every `SUB_AGENTS[i]` where status ∈ {done, failed}:
```sh
kei-ledger validate "$agent_branch"
```
This verifies all 6 required artefacts exist under
`.claude/agents/<id>/`: spec.md, plan.md, progress.json, chatlog.md,
handoffs.md, review.md.
If any agent is MISSING artefacts — mark its verdict as "reject-bundle"
and skip the per-branch click below. The final report lists them.
## 4b — Per-branch merge click (AskUserQuestion, ONE per branch)
For each sub-agent whose bundle is complete, emit:
```json
{
"questions": [
{
"question": "Merge verdict for <agent_id> on <agent_branch> (status=<s>, summary=<first 60 chars>)?",
"header": "Verdict",
"multiSelect": false,
"options": [
{"label": "merge --no-ff", "description": "Preserve the sub-branch history — default for substantive work"},
{"label": "squash", "description": "Collapse into one commit on project branch — for small / fixup work"},
{"label": "reject", "description": "Do not merge — kei-ledger rejected; branch stays for audit"},
{"label": "defer", "description": "Leave for later — no merge, no rejection; re-enter skill next session"}
]
}
]
}
```
Execute per click:
- `merge --no-ff`
```sh
git checkout "$PROJECT_BRANCH"
git merge --no-ff "$agent_branch" -m "merge($agent_id): $summary"
kei-ledger merged "$agent_id"
```
- `squash`
```sh
git checkout "$PROJECT_BRANCH"
git merge --squash "$agent_branch"
git commit -m "feat($agent_id): $summary (squashed)"
kei-ledger merged "$agent_id"
```
- `reject`
```sh
kei-ledger fail "$agent_id" --reason "rejected at merge ceremony"
# Update status table — ledger has no explicit 'rejected' from 'done',
# so we log rejection via a `fail` with reason; the row stays as audit
# evidence. (If the agent was already in 'failed' — leave as is.)
```
- `defer` → no git action, no ledger state change; record in `MERGE_PLAN`
as deferred so the final report reminds the user.
## 4c — Final integration checkpoint
After every sub-branch has a verdict:
```sh
git checkout "$PROJECT_BRANCH"
git log --oneline -20
kei-ledger tree "$LEDGER_ID"
```
Emit a final NO-DOWNGRADE click if any sub-branch was rejected or
deferred — never silently close the project:
```json
{
"questions": [
{
"question": "Project state has <N> rejected + <M> deferred branches. Next step?",
"header": "Close",
"multiSelect": false,
"options": [
{"label": "open PR as-is", "description": "Push project branch, open PR — rejected work is audit-logged only"},
{"label": "retry rejected", "description": "Return to Phase 2c with the rejected sub-agents as fresh spawns"},
{"label": "close and re-enter later", "description": "Leave project branch local; re-enter skill next session"}
]
}
]
}
```
## Verify-criterion
- `kei-ledger list --status running` returns zero rows whose
`parent_branch == $PROJECT_BRANCH`.
- Every `SUB_AGENTS[i]` has exactly one entry in `MERGE_PLAN` — one of
`merge`, `squash`, `reject`, `defer`, `reject-bundle`.
- For every `merge` / `squash` verdict, `kei-ledger list --status merged`
contains a matching row.
- Final report cites each verdict explicitly and does NOT gloss over
rejected / deferred branches.