agent-templates 0.1.0 → 0.2.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/ADOPTING.md +57 -57
- package/CLAUDE.md +128 -125
- package/LICENSE +21 -21
- package/README.md +32 -32
- package/package.json +32 -32
- package/patterns/three-agent-architect-builder-reviewer/README.md +161 -153
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/architect.md +31 -31
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/builder.md +25 -25
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/reviewer.md +33 -33
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/agents/triage.md +31 -31
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/breakdown-prd.md +18 -18
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/nightly-issues.md +14 -14
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/review-ticket.md +14 -14
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/start-all.md +17 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/start-milestone.md +15 -15
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/verify-delivery.md +20 -20
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/hooks/guard-main-session-writes.mjs +53 -53
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/scripts/milestone-dag.mjs +94 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/scripts/publish-tickets.mjs +263 -263
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/settings.json +15 -15
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/workflows/nightly-issues.js +139 -139
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/workflows/run-milestone.js +223 -223
- package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/workflows/start-all.js +118 -0
- package/patterns/three-agent-architect-builder-reviewer/scaffold/INSTALL.md +65 -65
- package/patterns/three-agent-architect-builder-reviewer/scaffold/claude-md-snippet.md +38 -37
- package/scripts/adopt.mjs +187 -177
- package/scripts/build-site.mjs +264 -264
- package/scripts/cli.mjs +52 -52
- package/templates/pattern-README.template.md +65 -65
- package/templates/ticket.template.md +104 -104
- package/templates/tracker/github/ISSUE_TEMPLATE/bug-report.md +28 -28
- package/templates/tracker/github/ISSUE_TEMPLATE/decision-record.md +25 -25
- package/templates/tracker/github/ISSUE_TEMPLATE/task.md +36 -36
- package/templates/tracker/github/PULL_REQUEST_TEMPLATE.md +54 -54
- package/templates/tracker/gitlab/issue_templates/bug-report.md +23 -23
- package/templates/tracker/gitlab/issue_templates/decision-record.md +20 -20
- package/templates/tracker/gitlab/issue_templates/task.md +31 -31
- package/templates/tracker/gitlab/merge_request_templates/default.md +55 -55
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: reviewer
|
|
3
|
-
description: Reviewer stage of the three-agent pattern. Independent judge in a FRESH context — never the Builder's session, deliberately a different model tier from the Builder so the two do not share blind spots. Clears the work or bounces it back with findings.
|
|
4
|
-
model: claude-fable-5
|
|
5
|
-
effort: max
|
|
6
|
-
tools: Read, Glob, Grep, Bash
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
<!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-17.
|
|
10
|
-
Do not change them here first — update the pattern entry in agent-templates, then sync. -->
|
|
11
|
-
|
|
12
|
-
You are the **Reviewer** — the last quality gate before merge, independent of the Builder.
|
|
13
|
-
|
|
14
|
-
Context rule: you must be running in a **fresh context**. Your input is only: the ticket, the plan (`docs/plans/<ticket-id>.md`), and the Builder's diff (branch or PR ref). If you have been handed the Builder's conversation or its self-assessment, stop and report the pattern violation instead of reviewing.
|
|
15
|
-
|
|
16
|
-
Review the diff against the ticket and the plan, in priority order:
|
|
17
|
-
|
|
18
|
-
1. **Edge cases** — inputs and states the happy path ignores.
|
|
19
|
-
2. **Concurrency** — races, ordering assumptions, shared-state mutation.
|
|
20
|
-
3. **Security-sensitive paths** — authz checks, input validation, secrets handling, injection.
|
|
21
|
-
4. **Plan conformance** — undeclared deviations from the plan are findings.
|
|
22
|
-
|
|
23
|
-
Method:
|
|
24
|
-
|
|
25
|
-
- Run the FULL suite yourself via Bash — unit, integration, and E2E where present, not only the tests the diff touches. Never trust reported results.
|
|
26
|
-
- Be adversarial: try to refute the claim that the ticket is done. Default to BOUNCE when uncertain.
|
|
27
|
-
|
|
28
|
-
Verdict (exactly one):
|
|
29
|
-
|
|
30
|
-
- **CLEAR** — with a short note of what was checked.
|
|
31
|
-
- **BOUNCE** — with numbered findings: `file:line` · concrete failure scenario · severity. Findings go back to the Builder.
|
|
32
|
-
|
|
33
|
-
Never: fix the code yourself; approve out of politeness; re-clear without new commits to review.
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Reviewer stage of the three-agent pattern. Independent judge in a FRESH context — never the Builder's session, deliberately a different model tier from the Builder so the two do not share blind spots. Clears the work or bounces it back with findings.
|
|
4
|
+
model: claude-fable-5
|
|
5
|
+
effort: max
|
|
6
|
+
tools: Read, Glob, Grep, Bash
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Model/effort pinned per pattern three-agent-architect-builder-reviewer, as of 2026-07-17.
|
|
10
|
+
Do not change them here first — update the pattern entry in agent-templates, then sync. -->
|
|
11
|
+
|
|
12
|
+
You are the **Reviewer** — the last quality gate before merge, independent of the Builder.
|
|
13
|
+
|
|
14
|
+
Context rule: you must be running in a **fresh context**. Your input is only: the ticket, the plan (`docs/plans/<ticket-id>.md`), and the Builder's diff (branch or PR ref). If you have been handed the Builder's conversation or its self-assessment, stop and report the pattern violation instead of reviewing.
|
|
15
|
+
|
|
16
|
+
Review the diff against the ticket and the plan, in priority order:
|
|
17
|
+
|
|
18
|
+
1. **Edge cases** — inputs and states the happy path ignores.
|
|
19
|
+
2. **Concurrency** — races, ordering assumptions, shared-state mutation.
|
|
20
|
+
3. **Security-sensitive paths** — authz checks, input validation, secrets handling, injection.
|
|
21
|
+
4. **Plan conformance** — undeclared deviations from the plan are findings.
|
|
22
|
+
|
|
23
|
+
Method:
|
|
24
|
+
|
|
25
|
+
- Run the FULL suite yourself via Bash — unit, integration, and E2E where present, not only the tests the diff touches. Never trust reported results.
|
|
26
|
+
- Be adversarial: try to refute the claim that the ticket is done. Default to BOUNCE when uncertain.
|
|
27
|
+
|
|
28
|
+
Verdict (exactly one):
|
|
29
|
+
|
|
30
|
+
- **CLEAR** — with a short note of what was checked.
|
|
31
|
+
- **BOUNCE** — with numbered findings: `file:line` · concrete failure scenario · severity. Findings go back to the Builder.
|
|
32
|
+
|
|
33
|
+
Never: fix the code yourself; approve out of politeness; re-clear without new commits to review.
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: triage
|
|
3
|
-
description: Nightly triage stage. Classifies an open tracker issue as fixable / invalid / needs-human; for fixable ones synthesizes a cold-startable pipeline ticket file from the issue. Never fixes code, never touches the tracker.
|
|
4
|
-
model: claude-sonnet-5
|
|
5
|
-
effort: xhigh
|
|
6
|
-
tools: Read, Glob, Grep, Bash, Write
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
<!-- Model/effort: profile inherited from the Architect row of the pattern README §3 —
|
|
10
|
-
classification + ticket synthesis is planning-shaped work; no separate benchmark
|
|
11
|
-
basis. [team-policy], as of 2026-07-17. Update via the pattern entry, then sync. -->
|
|
12
|
-
|
|
13
|
-
You are the **Triage** stage of the nightly issue sweep.
|
|
14
|
-
|
|
15
|
-
Input: one tracker issue (number, title, body, labels).
|
|
16
|
-
|
|
17
|
-
Classify it as exactly one of:
|
|
18
|
-
|
|
19
|
-
- **fixable** — a real defect or small task the pipeline can complete autonomously: a clear symptom or goal, bounded scope, and you can trace it to specific code by exploring now.
|
|
20
|
-
- **invalid** — not a real issue: works as intended, duplicate, or out of scope. State why, with evidence (file refs, the behavior you verified).
|
|
21
|
-
- **needs-human** — real, but not autonomous-safe: needs product judgment, a hard-to-reverse choice, is too large for one overnight ticket, or you cannot locate the code.
|
|
22
|
-
|
|
23
|
-
For **fixable** only: write a ticket file at `docs/prd/99-nightly/tickets/ISS-<number>-<slug>.md` following `templates/ticket.template.md` (`id: ISS-<number>`, `module: 99-nightly`, honest `size`). Inline everything the pipeline needs — quote the relevant issue text, name the files you traced — per the cold-start rule. The acceptance checklist must be classified, mechanical wherever possible, and MUST turn the reported symptom into a test.
|
|
24
|
-
|
|
25
|
-
Rules:
|
|
26
|
-
|
|
27
|
-
- Read the code to verify claims before classifying — never classify from the issue text alone.
|
|
28
|
-
- Never modify code. Never close, label, or comment on issues — tracker writes belong to the report step.
|
|
29
|
-
- When torn between fixable and needs-human, choose **needs-human**: a wrong autonomous fix at night is worse than a skipped issue.
|
|
30
|
-
|
|
31
|
-
Return: `classification`, `reason` (with evidence), and `ticketPath` (fixable only).
|
|
1
|
+
---
|
|
2
|
+
name: triage
|
|
3
|
+
description: Nightly triage stage. Classifies an open tracker issue as fixable / invalid / needs-human; for fixable ones synthesizes a cold-startable pipeline ticket file from the issue. Never fixes code, never touches the tracker.
|
|
4
|
+
model: claude-sonnet-5
|
|
5
|
+
effort: xhigh
|
|
6
|
+
tools: Read, Glob, Grep, Bash, Write
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Model/effort: profile inherited from the Architect row of the pattern README §3 —
|
|
10
|
+
classification + ticket synthesis is planning-shaped work; no separate benchmark
|
|
11
|
+
basis. [team-policy], as of 2026-07-17. Update via the pattern entry, then sync. -->
|
|
12
|
+
|
|
13
|
+
You are the **Triage** stage of the nightly issue sweep.
|
|
14
|
+
|
|
15
|
+
Input: one tracker issue (number, title, body, labels).
|
|
16
|
+
|
|
17
|
+
Classify it as exactly one of:
|
|
18
|
+
|
|
19
|
+
- **fixable** — a real defect or small task the pipeline can complete autonomously: a clear symptom or goal, bounded scope, and you can trace it to specific code by exploring now.
|
|
20
|
+
- **invalid** — not a real issue: works as intended, duplicate, or out of scope. State why, with evidence (file refs, the behavior you verified).
|
|
21
|
+
- **needs-human** — real, but not autonomous-safe: needs product judgment, a hard-to-reverse choice, is too large for one overnight ticket, or you cannot locate the code.
|
|
22
|
+
|
|
23
|
+
For **fixable** only: write a ticket file at `docs/prd/99-nightly/tickets/ISS-<number>-<slug>.md` following `templates/ticket.template.md` (`id: ISS-<number>`, `module: 99-nightly`, honest `size`). Inline everything the pipeline needs — quote the relevant issue text, name the files you traced — per the cold-start rule. The acceptance checklist must be classified, mechanical wherever possible, and MUST turn the reported symptom into a test.
|
|
24
|
+
|
|
25
|
+
Rules:
|
|
26
|
+
|
|
27
|
+
- Read the code to verify claims before classifying — never classify from the issue text alone.
|
|
28
|
+
- Never modify code. Never close, label, or comment on issues — tracker writes belong to the report step.
|
|
29
|
+
- When torn between fixable and needs-human, choose **needs-human**: a wrong autonomous fix at night is worse than a skipped issue.
|
|
30
|
+
|
|
31
|
+
Return: `classification`, `reason` (with evidence), and `ticketPath` (fixable only).
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/breakdown-prd.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Decompose docs/PRD.md into sub-PRDs + template-compliant tickets (three-agent pattern, pre-Gate-1 planning)
|
|
3
|
-
argument-hint: [focus notes, e.g. module-count hint or what to defer]
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Launch the **architect** subagent to decompose the master PRD. Optional focus notes from the human: `$ARGUMENTS`
|
|
7
|
-
|
|
8
|
-
Input: `docs/PRD.md` (hard requirement — STOP with a clear message if absent) plus any existing `docs/adr/` entries.
|
|
9
|
-
|
|
10
|
-
Output (planning artifacts only — the architect writes no production code):
|
|
11
|
-
|
|
12
|
-
1. `docs/prd/breakdown-plan.md` — the module split, cut on **file-ownership boundaries** (disjoint file-scopes are what make parallel lanes safe later; shared contracts/schemas go into a foundation module built first), the global file-scope allocation table, and the ticket dependency DAG (mirrors each ticket's `blocked_by`/`blocks`).
|
|
13
|
-
2. Per module `NN-<name>`: `docs/prd/NN-<name>/README.md` — the sub-PRD: problem, scope/non-goals, decisions (each with a basis), rejected alternatives, open questions (each with an owner), work-breakdown table (ticket · size · lane · file-scope · depends-on), acceptance, changelog.
|
|
14
|
-
3. `docs/prd/NN-<name>/tickets/<ID>-<slug>.md` — every ticket follows `templates/ticket.template.md` **fully**: traceability header, "Why `<agent>`" basis, `lane`/`blocked_by`/`blocks` frontmatter, per-item Non-goal owners, file-scope + does-not-touch + serial-safety, code-level deliverables, classified acceptance (tag vocabulary from this repo's CLAUDE.md), test plan, feedback obligation. Every ticket must be cold-startable.
|
|
15
|
-
|
|
16
|
-
When the architect returns: present the breakdown summary (modules, ticket count, DAG, open questions) and **STOP**. This output is the input to Gate 1 — the human's review plus `/start-milestone` is the sign-off. Never begin implementation from this command.
|
|
17
|
-
|
|
18
|
-
Hard rule: this stage runs in the **architect** subagent, never inline in this session. If the subagent cannot be launched or fails, report that and stop — do not absorb its role.
|
|
1
|
+
---
|
|
2
|
+
description: Decompose docs/PRD.md into sub-PRDs + template-compliant tickets (three-agent pattern, pre-Gate-1 planning)
|
|
3
|
+
argument-hint: [focus notes, e.g. module-count hint or what to defer]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Launch the **architect** subagent to decompose the master PRD. Optional focus notes from the human: `$ARGUMENTS`
|
|
7
|
+
|
|
8
|
+
Input: `docs/PRD.md` (hard requirement — STOP with a clear message if absent) plus any existing `docs/adr/` entries.
|
|
9
|
+
|
|
10
|
+
Output (planning artifacts only — the architect writes no production code):
|
|
11
|
+
|
|
12
|
+
1. `docs/prd/breakdown-plan.md` — the module split, cut on **file-ownership boundaries** (disjoint file-scopes are what make parallel lanes safe later; shared contracts/schemas go into a foundation module built first), the global file-scope allocation table, and the ticket dependency DAG (mirrors each ticket's `blocked_by`/`blocks`).
|
|
13
|
+
2. Per module `NN-<name>`: `docs/prd/NN-<name>/README.md` — the sub-PRD: problem, scope/non-goals, decisions (each with a basis), rejected alternatives, open questions (each with an owner), work-breakdown table (ticket · size · lane · file-scope · depends-on), acceptance, changelog.
|
|
14
|
+
3. `docs/prd/NN-<name>/tickets/<ID>-<slug>.md` — every ticket follows `templates/ticket.template.md` **fully**: traceability header, "Why `<agent>`" basis, `lane`/`blocked_by`/`blocks` frontmatter, per-item Non-goal owners, file-scope + does-not-touch + serial-safety, code-level deliverables, classified acceptance (tag vocabulary from this repo's CLAUDE.md), test plan, feedback obligation. Every ticket must be cold-startable.
|
|
15
|
+
|
|
16
|
+
When the architect returns: present the breakdown summary (modules, ticket count, DAG, open questions) and **STOP**. This output is the input to Gate 1 — the human's review plus `/start-milestone` is the sign-off. Never begin implementation from this command.
|
|
17
|
+
|
|
18
|
+
Hard rule: this stage runs in the **architect** subagent, never inline in this session. If the subagent cannot be launched or fails, report that and stop — do not absorb its role.
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/nightly-issues.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Nightly issue sweep — triage open issues, auto-fix the fixable ones through the three-agent pipeline, post the morning report (designed for headless `claude -p "/nightly-issues"`)
|
|
3
|
-
argument-hint: [max-issues]
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Arguments: `$ARGUMENTS` — optional first argument caps how many issues to process tonight (default 5).
|
|
7
|
-
|
|
8
|
-
Execute in order:
|
|
9
|
-
|
|
10
|
-
1. **Collect.** List open issues with the platform CLI (`gh issue list --state open --json number,title,body,labels,createdAt,url` / glab equivalent). Exclude issues labeled `nightly:escalated`, `triage:invalid`, or `needs-human`, and any issue titled `Nightly report ...`. For each remaining issue set `isNew` = created within the last 24 hours. Compute `reportDate` = today's local date (YYYY-MM-DD).
|
|
11
|
-
2. **Launch the sweep.** Call the **Workflow** tool with `name: "nightly-issues"` and `args: { issues, maxIssues, defaultBranch, platform, reportDate }`. This command's instruction is your authorization to use the Workflow tool. The workflow triages (read-only), runs fixable issues through the run-milestone pipeline autonomously, and posts all tracker writes in one report step.
|
|
12
|
-
3. **Final output** (this is the headless run's stdout): the report issue URL, then one line per processed issue — `#N · <classification or pipeline status> · <one-line reason>` — plus how many eligible issues were left for the next night.
|
|
13
|
-
|
|
14
|
-
Operator notes: scheduling, permissions, and the morning-email mechanics are documented in the scaffold's INSTALL.md § Nightly sweep. You are an observer while the workflow runs — no stage work, no file edits, no tracker writes outside the workflow.
|
|
1
|
+
---
|
|
2
|
+
description: Nightly issue sweep — triage open issues, auto-fix the fixable ones through the three-agent pipeline, post the morning report (designed for headless `claude -p "/nightly-issues"`)
|
|
3
|
+
argument-hint: [max-issues]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Arguments: `$ARGUMENTS` — optional first argument caps how many issues to process tonight (default 5).
|
|
7
|
+
|
|
8
|
+
Execute in order:
|
|
9
|
+
|
|
10
|
+
1. **Collect.** List open issues with the platform CLI (`gh issue list --state open --json number,title,body,labels,createdAt,url` / glab equivalent). Exclude issues labeled `nightly:escalated`, `triage:invalid`, or `needs-human`, and any issue titled `Nightly report ...`. For each remaining issue set `isNew` = created within the last 24 hours. Compute `reportDate` = today's local date (YYYY-MM-DD).
|
|
11
|
+
2. **Launch the sweep.** Call the **Workflow** tool with `name: "nightly-issues"` and `args: { issues, maxIssues, defaultBranch, platform, reportDate }`. This command's instruction is your authorization to use the Workflow tool. The workflow triages (read-only), runs fixable issues through the run-milestone pipeline autonomously, and posts all tracker writes in one report step.
|
|
12
|
+
3. **Final output** (this is the headless run's stdout): the report issue URL, then one line per processed issue — `#N · <classification or pipeline status> · <one-line reason>` — plus how many eligible issues were left for the next night.
|
|
13
|
+
|
|
14
|
+
Operator notes: scheduling, permissions, and the morning-email mechanics are documented in the scaffold's INSTALL.md § Nightly sweep. You are an observer while the workflow runs — no stage work, no file edits, no tracker writes outside the workflow.
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/review-ticket.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Run the Reviewer stage on a built ticket (three-agent pattern) — requires a fresh context
|
|
3
|
-
argument-hint: <ticket-id> [branch-or-PR-ref]
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Arguments: `$ARGUMENTS` — the first is the ticket id (TICKET below); the optional second is the diff reference (branch or PR; default: the ticket's `ticket/<id>` branch).
|
|
7
|
-
|
|
8
|
-
Contamination check first: if this session contains the Builder's implementation conversation for TICKET, STOP and tell the user to run `/review-ticket` from a fresh session. (A reviewer subagent launched from a session that only orchestrated — passing artifacts, never transcripts — is acceptable: Mode A in the scaffold's INSTALL.md.)
|
|
9
|
-
|
|
10
|
-
Launch the **reviewer** subagent for TICKET. Give it ONLY: the ticket path, the plan path (`docs/plans/<ticket-id>.md`), and the diff reference. Never include the Builder's transcript or self-assessment.
|
|
11
|
-
|
|
12
|
-
Relay the verdict verbatim — CLEAR, or BOUNCE with its numbered findings. On BOUNCE, findings go back to the Builder; after 2 bounce cycles, escalate to a human instead of looping.
|
|
13
|
-
|
|
14
|
-
Hard rule: this stage runs in the **reviewer** subagent, never inline in this session. If the subagent cannot be launched or fails, report that and stop — do not absorb its role. After a merge, `/verify-delivery` still runs — a CLEAR verdict does not close the ticket by itself.
|
|
1
|
+
---
|
|
2
|
+
description: Run the Reviewer stage on a built ticket (three-agent pattern) — requires a fresh context
|
|
3
|
+
argument-hint: <ticket-id> [branch-or-PR-ref]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Arguments: `$ARGUMENTS` — the first is the ticket id (TICKET below); the optional second is the diff reference (branch or PR; default: the ticket's `ticket/<id>` branch).
|
|
7
|
+
|
|
8
|
+
Contamination check first: if this session contains the Builder's implementation conversation for TICKET, STOP and tell the user to run `/review-ticket` from a fresh session. (A reviewer subagent launched from a session that only orchestrated — passing artifacts, never transcripts — is acceptable: Mode A in the scaffold's INSTALL.md.)
|
|
9
|
+
|
|
10
|
+
Launch the **reviewer** subagent for TICKET. Give it ONLY: the ticket path, the plan path (`docs/plans/<ticket-id>.md`), and the diff reference. Never include the Builder's transcript or self-assessment.
|
|
11
|
+
|
|
12
|
+
Relay the verdict verbatim — CLEAR, or BOUNCE with its numbered findings. On BOUNCE, findings go back to the Builder; after 2 bounce cycles, escalate to a human instead of looping.
|
|
13
|
+
|
|
14
|
+
Hard rule: this stage runs in the **reviewer** subagent, never inline in this session. If the subagent cannot be launched or fails, report that and stop — do not absorb its role. After a merge, `/verify-delivery` still runs — a CLEAR verdict does not close the ticket by itself.
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/start-all.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Whole-PRD Gate 1 — compute the module DAG, publish every module's tickets, run all modules through the pipeline in dependency order (three-agent pattern)
|
|
3
|
+
argument-hint: [supervised|autonomous]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Arguments: `$ARGUMENTS` — optional mode override (else the repo's declared Operating mode in CLAUDE.md).
|
|
7
|
+
|
|
8
|
+
Typing this command is the human Gate 1 sign-off **for the whole PRD** — every module, in dependency order. Prefer `/start-milestone` per module when you still want module-boundary checkpoints. Execute in order:
|
|
9
|
+
|
|
10
|
+
1. **Compute the plan.** Run `node .claude/scripts/milestone-dag.mjs` and show its output (module order, per-module dependencies). STOP on any error — a dangling `blocked_by` or a cycle is a spec defect for the Architect/human, not something to patch here.
|
|
11
|
+
2. **Publish all tickets.** For each module in DAG order: `node .claude/scripts/publish-tickets.mjs docs/prd/<module>` (dry-run, then `--create`; STOP on `error` entries). Then, per module, **filter out tickets whose issues are already closed** (closed = delivered by an earlier run — this makes `/start-all` re-runs resume: fully-closed modules pass an empty ticket list and are marked already-complete).
|
|
12
|
+
3. **Launch the driver.** Call the **Workflow** tool with `name: "start-all"` and `args: { modules: [{name, dependsOn, tickets}] in DAG order, mode, defaultBranch, platform }`. This command's instruction is your authorization to use the Workflow tool. Failure policy is enforced in the workflow: failed modules block their dependents; independent branches continue in `autonomous`; anything short of a CLEAR stops everything in `supervised`.
|
|
13
|
+
4. **Relay the final report verbatim** — per module: `completed` / `already-complete` / `paused-for-merge` (supervised: tell the human to merge, then re-run this command) / `failed` (with the failing ticket + stage) / `skipped-dependency` / `not-started`. Escalations inside a module carry through from run-milestone unchanged.
|
|
14
|
+
|
|
15
|
+
While the workflow runs you are an observer. Do not do stage work in parallel, do not "help" a slow stage, do not edit files.
|
|
16
|
+
|
|
17
|
+
Hard rule: DAG computation and publishing are script steps; module sequencing is the workflow's job. Never absorb either role by improvising order or tracker writes yourself.
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/start-milestone.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Gate 1 start signal — publish the module's tickets as tracker issues, then run the milestone pipeline (three-agent pattern)
|
|
3
|
-
argument-hint: <module dir, e.g. docs/prd/01-foo> [supervised|autonomous]
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Arguments: `$ARGUMENTS` — the first is the module directory (MODULE below); the optional second overrides the repo's declared Operating mode (CLAUDE.md).
|
|
7
|
-
|
|
8
|
-
Typing this command **is** the human Gate 1 sign-off: the sub-PRD and tickets are final, and tracker issue **creation** is authorized by this sign-off. Execute in order:
|
|
9
|
-
|
|
10
|
-
1. **Verify Gate 1 inputs.** `MODULE/README.md` (the sub-PRD) exists and `MODULE/tickets/*.md` is non-empty; every ticket has the required frontmatter (see `templates/ticket.template.md`). Anything missing → STOP and list exactly what is missing. Do not fix it yourself — that is Architect-stage work.
|
|
11
|
-
2. **Publish tickets as tracker issues.** Run `node .claude/scripts/publish-tickets.mjs MODULE` (dry-run) and show the mapping. If the summary contains `error` entries → STOP and report them. Otherwise re-run with `--create` (idempotent — the `[<id>]` title prefix dedupes, so re-running is safe), and again STOP on any `error` entries.
|
|
12
|
-
3. **Launch the pipeline.** Parse the final `PUBLISH-SUMMARY-JSON` line into `tickets: [{id, path, issue}]`. **Filter out tickets whose issue is already closed** (check via `gh`/`glab` — closed means delivered by an earlier run; this filter is what makes re-runs after supervised pauses or crashes safe). Determine the Operating mode, then call the **Workflow** tool with `name: "run-milestone"` and `args: { tickets, mode, defaultBranch, platform }`. This command's instruction is your authorization to use the Workflow tool.
|
|
13
|
-
4. **Relay the final report verbatim** — per ticket: `delivered` · `awaiting-human-merge` · `escalated` (stage `review`, `reviewer-failed`, or `bounce-fix-build`) · `failed` · `delivery-incomplete`, plus `notStarted` when the run stopped early. Escalated and failed items go to the human; do not fix them inline (the write guard will hold you to that). In `supervised` mode the run stops after each CLEAR verdict — tell the human to merge, then re-run this command to continue.
|
|
14
|
-
|
|
15
|
-
While the workflow runs you are an observer. Do not do stage work in parallel, do not "help" a slow stage, do not edit files.
|
|
1
|
+
---
|
|
2
|
+
description: Gate 1 start signal — publish the module's tickets as tracker issues, then run the milestone pipeline (three-agent pattern)
|
|
3
|
+
argument-hint: <module dir, e.g. docs/prd/01-foo> [supervised|autonomous]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Arguments: `$ARGUMENTS` — the first is the module directory (MODULE below); the optional second overrides the repo's declared Operating mode (CLAUDE.md).
|
|
7
|
+
|
|
8
|
+
Typing this command **is** the human Gate 1 sign-off: the sub-PRD and tickets are final, and tracker issue **creation** is authorized by this sign-off. Execute in order:
|
|
9
|
+
|
|
10
|
+
1. **Verify Gate 1 inputs.** `MODULE/README.md` (the sub-PRD) exists and `MODULE/tickets/*.md` is non-empty; every ticket has the required frontmatter (see `templates/ticket.template.md`). Anything missing → STOP and list exactly what is missing. Do not fix it yourself — that is Architect-stage work.
|
|
11
|
+
2. **Publish tickets as tracker issues.** Run `node .claude/scripts/publish-tickets.mjs MODULE` (dry-run) and show the mapping. If the summary contains `error` entries → STOP and report them. Otherwise re-run with `--create` (idempotent — the `[<id>]` title prefix dedupes, so re-running is safe), and again STOP on any `error` entries.
|
|
12
|
+
3. **Launch the pipeline.** Parse the final `PUBLISH-SUMMARY-JSON` line into `tickets: [{id, path, issue}]`. **Filter out tickets whose issue is already closed** (check via `gh`/`glab` — closed means delivered by an earlier run; this filter is what makes re-runs after supervised pauses or crashes safe). Determine the Operating mode, then call the **Workflow** tool with `name: "run-milestone"` and `args: { tickets, mode, defaultBranch, platform }`. This command's instruction is your authorization to use the Workflow tool.
|
|
13
|
+
4. **Relay the final report verbatim** — per ticket: `delivered` · `awaiting-human-merge` · `escalated` (stage `review`, `reviewer-failed`, or `bounce-fix-build`) · `failed` · `delivery-incomplete`, plus `notStarted` when the run stopped early. Escalated and failed items go to the human; do not fix them inline (the write guard will hold you to that). In `supervised` mode the run stops after each CLEAR verdict — tell the human to merge, then re-run this command to continue.
|
|
14
|
+
|
|
15
|
+
While the workflow runs you are an observer. Do not do stage work in parallel, do not "help" a slow stage, do not edit files.
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/commands/verify-delivery.md
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Post-merge Definition-of-Done check for a ticket (three-agent pattern) — verifies delivery instead of assuming it
|
|
3
|
-
argument-hint: <ticket-id>
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Verify — do not assume — that ticket $ARGUMENTS is actually delivered. Check every item yourself this session and print a pass/fail table:
|
|
7
|
-
|
|
8
|
-
1. **Plan** exists at `docs/plans/$ARGUMENTS.md`.
|
|
9
|
-
2. **Reviewer verdict** is CLEAR, attached to the MR/PR.
|
|
10
|
-
3. **Tests green on the merged default branch** — run the suite yourself this session; never accept reported results.
|
|
11
|
-
4. **MR/PR merged** into the **default branch** (not a side branch).
|
|
12
|
-
5. **Tracker issue closed** — check via `glab issue view` / `gh issue view`. Auto-close via `Closes #N` fires only under specific conditions (GitLab: default-branch merge with the closing pattern in the MR description) — never trust it blindly; this exact gap has shipped before (MRs merged, issues left open).
|
|
13
|
-
6. **Writeback** — any Deviations noted by the Builder are reflected back into the ticket/sub-PRD.
|
|
14
|
-
|
|
15
|
-
Report every failed item plainly. If the MR is merged but the issue is still open, the repair is the exact close command (`glab issue close <N>` / `gh issue close <N>`) — behavior depends on the repo's declared operating mode (CLAUDE.md, "Operating mode"):
|
|
16
|
-
|
|
17
|
-
- `supervised`: show the command and run it only after explicit human OK.
|
|
18
|
-
- `autonomous`: run the repair, report what was repaired, and escalate to a human only if the repair fails or the gap is not mechanically repairable.
|
|
19
|
-
|
|
20
|
-
Never mark an item passed that you did not check this session.
|
|
1
|
+
---
|
|
2
|
+
description: Post-merge Definition-of-Done check for a ticket (three-agent pattern) — verifies delivery instead of assuming it
|
|
3
|
+
argument-hint: <ticket-id>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Verify — do not assume — that ticket $ARGUMENTS is actually delivered. Check every item yourself this session and print a pass/fail table:
|
|
7
|
+
|
|
8
|
+
1. **Plan** exists at `docs/plans/$ARGUMENTS.md`.
|
|
9
|
+
2. **Reviewer verdict** is CLEAR, attached to the MR/PR.
|
|
10
|
+
3. **Tests green on the merged default branch** — run the suite yourself this session; never accept reported results.
|
|
11
|
+
4. **MR/PR merged** into the **default branch** (not a side branch).
|
|
12
|
+
5. **Tracker issue closed** — check via `glab issue view` / `gh issue view`. Auto-close via `Closes #N` fires only under specific conditions (GitLab: default-branch merge with the closing pattern in the MR description) — never trust it blindly; this exact gap has shipped before (MRs merged, issues left open).
|
|
13
|
+
6. **Writeback** — any Deviations noted by the Builder are reflected back into the ticket/sub-PRD.
|
|
14
|
+
|
|
15
|
+
Report every failed item plainly. If the MR is merged but the issue is still open, the repair is the exact close command (`glab issue close <N>` / `gh issue close <N>`) — behavior depends on the repo's declared operating mode (CLAUDE.md, "Operating mode"):
|
|
16
|
+
|
|
17
|
+
- `supervised`: show the command and run it only after explicit human OK.
|
|
18
|
+
- `autonomous`: run the repair, report what was repaired, and escalate to a human only if the repair fails or the gap is not mechanically repairable.
|
|
19
|
+
|
|
20
|
+
Never mark an item passed that you did not check this session.
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Three-agent pattern guard: the ORCHESTRATOR (main session) never writes.
|
|
3
|
-
//
|
|
4
|
-
// PreToolUse hook on Edit|Write|MultiEdit|NotebookEdit (wired in .claude/settings.json).
|
|
5
|
-
// Per https://code.claude.com/docs/en/hooks.md (verified 2026-07-17): hooks fire for
|
|
6
|
-
// subagent tool calls too, and the input carries `agent_id`/`agent_type` ONLY when the
|
|
7
|
-
// call comes from a subagent — their absence identifies the main session.
|
|
8
|
-
//
|
|
9
|
-
// Behavior:
|
|
10
|
-
// - subagent call (architect writes the plan, builder writes code) -> no objection
|
|
11
|
-
// - main-session call -> deny, with the dispatch instruction fed back to the model
|
|
12
|
-
// - override switch for a human-approved out-of-pipeline edit: create the file
|
|
13
|
-
// .claude/allow-main-writes (and delete it afterwards to re-arm the guard)
|
|
14
|
-
//
|
|
15
|
-
// Only the main session is constrained here; each subagent is governed by its own
|
|
16
|
-
// tools/disallowedTools frontmatter (e.g. the reviewer has no Write/Edit at all).
|
|
17
|
-
|
|
18
|
-
import { existsSync } from "node:fs";
|
|
19
|
-
|
|
20
|
-
const chunks = [];
|
|
21
|
-
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
22
|
-
|
|
23
|
-
let input = {};
|
|
24
|
-
try {
|
|
25
|
-
input = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
26
|
-
} catch {
|
|
27
|
-
process.exit(0); // unparsable input: stay out of the way rather than block blindly
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const isSubagent = typeof input.agent_id === "string" && input.agent_id.length > 0;
|
|
31
|
-
const overrideSwitch = new URL("../allow-main-writes", import.meta.url);
|
|
32
|
-
|
|
33
|
-
if (isSubagent || existsSync(overrideSwitch)) {
|
|
34
|
-
process.exit(0); // no objection; normal permission flow applies
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const target =
|
|
38
|
-
input.tool_input?.file_path ?? input.tool_input?.notebook_path ?? "(unknown target)";
|
|
39
|
-
|
|
40
|
-
console.log(
|
|
41
|
-
JSON.stringify({
|
|
42
|
-
hookSpecificOutput: {
|
|
43
|
-
hookEventName: "PreToolUse",
|
|
44
|
-
permissionDecision: "deny",
|
|
45
|
-
permissionDecisionReason:
|
|
46
|
-
`Three-agent pattern: the main session orchestrates only and never writes ` +
|
|
47
|
-
`(blocked ${input.tool_name} on ${target}). Dispatch the work to its stage instead: ` +
|
|
48
|
-
`/plan-ticket (architect) or /build-ticket (builder). For a human-approved ` +
|
|
49
|
-
`out-of-pipeline edit, create .claude/allow-main-writes and retry — then delete it.`,
|
|
50
|
-
},
|
|
51
|
-
})
|
|
52
|
-
);
|
|
53
|
-
process.exit(0);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Three-agent pattern guard: the ORCHESTRATOR (main session) never writes.
|
|
3
|
+
//
|
|
4
|
+
// PreToolUse hook on Edit|Write|MultiEdit|NotebookEdit (wired in .claude/settings.json).
|
|
5
|
+
// Per https://code.claude.com/docs/en/hooks.md (verified 2026-07-17): hooks fire for
|
|
6
|
+
// subagent tool calls too, and the input carries `agent_id`/`agent_type` ONLY when the
|
|
7
|
+
// call comes from a subagent — their absence identifies the main session.
|
|
8
|
+
//
|
|
9
|
+
// Behavior:
|
|
10
|
+
// - subagent call (architect writes the plan, builder writes code) -> no objection
|
|
11
|
+
// - main-session call -> deny, with the dispatch instruction fed back to the model
|
|
12
|
+
// - override switch for a human-approved out-of-pipeline edit: create the file
|
|
13
|
+
// .claude/allow-main-writes (and delete it afterwards to re-arm the guard)
|
|
14
|
+
//
|
|
15
|
+
// Only the main session is constrained here; each subagent is governed by its own
|
|
16
|
+
// tools/disallowedTools frontmatter (e.g. the reviewer has no Write/Edit at all).
|
|
17
|
+
|
|
18
|
+
import { existsSync } from "node:fs";
|
|
19
|
+
|
|
20
|
+
const chunks = [];
|
|
21
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
22
|
+
|
|
23
|
+
let input = {};
|
|
24
|
+
try {
|
|
25
|
+
input = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
26
|
+
} catch {
|
|
27
|
+
process.exit(0); // unparsable input: stay out of the way rather than block blindly
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const isSubagent = typeof input.agent_id === "string" && input.agent_id.length > 0;
|
|
31
|
+
const overrideSwitch = new URL("../allow-main-writes", import.meta.url);
|
|
32
|
+
|
|
33
|
+
if (isSubagent || existsSync(overrideSwitch)) {
|
|
34
|
+
process.exit(0); // no objection; normal permission flow applies
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const target =
|
|
38
|
+
input.tool_input?.file_path ?? input.tool_input?.notebook_path ?? "(unknown target)";
|
|
39
|
+
|
|
40
|
+
console.log(
|
|
41
|
+
JSON.stringify({
|
|
42
|
+
hookSpecificOutput: {
|
|
43
|
+
hookEventName: "PreToolUse",
|
|
44
|
+
permissionDecision: "deny",
|
|
45
|
+
permissionDecisionReason:
|
|
46
|
+
`Three-agent pattern: the main session orchestrates only and never writes ` +
|
|
47
|
+
`(blocked ${input.tool_name} on ${target}). Dispatch the work to its stage instead: ` +
|
|
48
|
+
`/plan-ticket (architect) or /build-ticket (builder). For a human-approved ` +
|
|
49
|
+
`out-of-pipeline edit, create .claude/allow-main-writes and retry — then delete it.`,
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
process.exit(0);
|
package/patterns/three-agent-architect-builder-reviewer/scaffold/.claude/scripts/milestone-dag.mjs
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// milestone-dag.mjs — deterministic module-DAG computation for /start-all.
|
|
3
|
+
// Ground truth is ticket frontmatter (`blocked_by`), never prose: module A depends on
|
|
4
|
+
// module B when any ticket in A is blocked_by a ticket living in B.
|
|
5
|
+
//
|
|
6
|
+
// Usage: node .claude/scripts/milestone-dag.mjs [prd-root] (default: docs/prd)
|
|
7
|
+
// Output: human-readable plan + a final machine-readable line:
|
|
8
|
+
// DAG-JSON: {"order":[...],"modules":{"<name>":{"tickets":[ids],"dependsOn":[names]}}}
|
|
9
|
+
// Exit 1 on: missing root, a blocked_by referencing an unknown ticket id (zero-silence:
|
|
10
|
+
// a dangling dependency is a spec error, not a warning), or a dependency cycle.
|
|
11
|
+
|
|
12
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'
|
|
13
|
+
import { join } from 'node:path'
|
|
14
|
+
|
|
15
|
+
const root = process.argv[2] || 'docs/prd'
|
|
16
|
+
if (!existsSync(root)) {
|
|
17
|
+
console.error(`no such prd root: ${root}`)
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const fmOf = (text) => (text.replace(/^/, '').match(/^---\r?\n([\s\S]*?)\r?\n---/) || [])[1] || ''
|
|
22
|
+
const field = (fm, name) => ((fm.match(new RegExp(`^${name}\\s*:\\s*(.+)$`, 'm')) || [])[1] || '').trim()
|
|
23
|
+
const listField = (fm, name) =>
|
|
24
|
+
field(fm, name)
|
|
25
|
+
.replace(/^\[/, '')
|
|
26
|
+
.replace(/\]$/, '')
|
|
27
|
+
.split(',')
|
|
28
|
+
.map((s) => s.trim())
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
|
|
31
|
+
const modules = {} // name -> { tickets: [{id, blockedBy}], dependsOn:Set }
|
|
32
|
+
const ticketModule = {} // ticket id -> module name
|
|
33
|
+
const errors = []
|
|
34
|
+
|
|
35
|
+
for (const d of readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort()) {
|
|
36
|
+
const tdir = join(root, d, 'tickets')
|
|
37
|
+
let ok = false
|
|
38
|
+
try { ok = statSync(tdir).isDirectory() } catch {}
|
|
39
|
+
if (!ok) continue
|
|
40
|
+
const tickets = []
|
|
41
|
+
for (const f of readdirSync(tdir).filter((n) => n.endsWith('.md')).sort()) {
|
|
42
|
+
const fm = fmOf(readFileSync(join(tdir, f), 'utf8'))
|
|
43
|
+
const id = field(fm, 'id')
|
|
44
|
+
if (!id) { errors.push(`${join(tdir, f)}: missing frontmatter id`); continue }
|
|
45
|
+
if (ticketModule[id]) { errors.push(`duplicate ticket id ${id} (${ticketModule[id]} and ${d})`); continue }
|
|
46
|
+
ticketModule[id] = d
|
|
47
|
+
tickets.push({ id, blockedBy: listField(fm, 'blocked_by') })
|
|
48
|
+
}
|
|
49
|
+
if (tickets.length) modules[d] = { tickets, dependsOn: new Set() }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!Object.keys(modules).length) {
|
|
53
|
+
console.error(`no modules with tickets under ${root}`)
|
|
54
|
+
process.exit(1)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const [name, mod] of Object.entries(modules)) {
|
|
58
|
+
for (const t of mod.tickets) {
|
|
59
|
+
for (const dep of t.blockedBy) {
|
|
60
|
+
const owner = ticketModule[dep]
|
|
61
|
+
if (!owner) { errors.push(`${name}/${t.id}: blocked_by references unknown ticket '${dep}'`); continue }
|
|
62
|
+
if (owner !== name) mod.dependsOn.add(owner)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (errors.length) {
|
|
68
|
+
for (const e of errors) console.error(`x ${e}`)
|
|
69
|
+
process.exit(1)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Kahn topological sort; deterministic tiebreak by module name (numeric prefixes sort naturally)
|
|
73
|
+
const order = []
|
|
74
|
+
const remaining = new Set(Object.keys(modules))
|
|
75
|
+
while (remaining.size) {
|
|
76
|
+
const ready = [...remaining].filter((m) => [...modules[m].dependsOn].every((d) => !remaining.has(d))).sort()
|
|
77
|
+
if (!ready.length) {
|
|
78
|
+
console.error(`x dependency cycle among: ${[...remaining].sort().join(', ')}`)
|
|
79
|
+
process.exit(1)
|
|
80
|
+
}
|
|
81
|
+
const next = ready[0]
|
|
82
|
+
order.push(next)
|
|
83
|
+
remaining.delete(next)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const m of order) {
|
|
87
|
+
const deps = [...modules[m].dependsOn].sort()
|
|
88
|
+
console.log(`${m} (${modules[m].tickets.length} ticket(s))${deps.length ? ' <- depends on: ' + deps.join(', ') : ''}`)
|
|
89
|
+
}
|
|
90
|
+
const json = {
|
|
91
|
+
order,
|
|
92
|
+
modules: Object.fromEntries(order.map((m) => [m, { tickets: modules[m].tickets.map((t) => t.id), dependsOn: [...modules[m].dependsOn].sort() }])),
|
|
93
|
+
}
|
|
94
|
+
console.log('DAG-JSON: ' + JSON.stringify(json))
|