@cleocode/skills 2026.5.83 → 2026.5.84

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/skills",
3
- "version": "2026.5.83",
3
+ "version": "2026.5.84",
4
4
  "description": "CLEO skill definitions - bundled with CLEO monorepo",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Lifecycle-protocol reconcile gate (T9672).
3
+ *
4
+ * Asserts the SET equality:
5
+ *
6
+ * SET( cleo lifecycle stages )
7
+ * ==
8
+ * SET( manifest.dispatch_matrix.by_protocol keys )
9
+ * − { "artifact-publish", "provenance", "agent-protocol" } # cross-cutting
10
+ *
11
+ * No normalization, no dashed-alias allowance. This is the strict gate that
12
+ * lands together with the manifest rename `architecture-decision` →
13
+ * `architecture_decision` so that a future drift fails CI.
14
+ *
15
+ * @task T9672
16
+ * @epic T9568
17
+ */
18
+
19
+ import { readFileSync } from 'node:fs';
20
+ import { dirname, resolve } from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+ import { describe, expect, it } from 'vitest';
23
+
24
+ const thisDir = dirname(fileURLToPath(import.meta.url));
25
+ const manifestPath = resolve(thisDir, '../../manifest.json');
26
+
27
+ interface Manifest {
28
+ dispatch_matrix: {
29
+ by_protocol: Record<string, string>;
30
+ by_keyword: Record<string, string>;
31
+ };
32
+ }
33
+
34
+ const manifest: Manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
35
+
36
+ /**
37
+ * The canonical 10 LOOM lifecycle stages emitted by `cleo lifecycle --help`.
38
+ * Underscored form is authoritative — see `packages/core/src/lifecycle/`.
39
+ */
40
+ const LIFECYCLE_STAGES = [
41
+ 'research',
42
+ 'consensus',
43
+ 'architecture_decision',
44
+ 'specification',
45
+ 'decomposition',
46
+ 'implementation',
47
+ 'validation',
48
+ 'testing',
49
+ 'release',
50
+ 'contribution',
51
+ ] as const;
52
+
53
+ /**
54
+ * Cross-cutting protocols that live in `dispatch_matrix.by_protocol` but are
55
+ * not LOOM lifecycle stages.
56
+ */
57
+ const CROSS_CUTTING_PROTOCOLS = new Set([
58
+ 'artifact-publish',
59
+ 'provenance',
60
+ 'agent-protocol',
61
+ ]);
62
+
63
+ describe('lifecycle ↔ protocol reconcile (T9672)', () => {
64
+ const byProtocolKeys = new Set(Object.keys(manifest.dispatch_matrix.by_protocol));
65
+ const stageOnlyKeys = new Set(
66
+ [...byProtocolKeys].filter((k) => !CROSS_CUTTING_PROTOCOLS.has(k)),
67
+ );
68
+ const expected = new Set<string>(LIFECYCLE_STAGES);
69
+
70
+ it('every cleo lifecycle stage is present as a strict (underscored) key in dispatch_matrix.by_protocol', () => {
71
+ for (const stage of LIFECYCLE_STAGES) {
72
+ expect(
73
+ byProtocolKeys.has(stage),
74
+ `lifecycle stage "${stage}" missing from dispatch_matrix.by_protocol — keys: ${[...byProtocolKeys].sort().join(', ')}`,
75
+ ).toBe(true);
76
+ }
77
+ });
78
+
79
+ it('dispatch_matrix.by_protocol contains no surplus stage-like keys', () => {
80
+ for (const key of stageOnlyKeys) {
81
+ expect(
82
+ expected.has(key),
83
+ `dispatch_matrix.by_protocol has key "${key}" which is not a cleo lifecycle stage and not a known cross-cutting protocol`,
84
+ ).toBe(true);
85
+ }
86
+ });
87
+
88
+ it('the dashed legacy form "architecture-decision" is NOT a dispatch_matrix.by_protocol key', () => {
89
+ expect(byProtocolKeys.has('architecture-decision')).toBe(false);
90
+ });
91
+
92
+ it('the dashed legacy form "architecture-decision" IS preserved as a keyword alias', () => {
93
+ const keywordKeys = Object.keys(manifest.dispatch_matrix.by_keyword);
94
+ const adrLine = keywordKeys.find((k) => k.includes('adr') && k.includes('formalize'));
95
+ expect(
96
+ adrLine,
97
+ `expected the ct-adr-recorder keyword dispatch line to exist; keys: ${keywordKeys.join(', ')}`,
98
+ ).toBeDefined();
99
+ expect(
100
+ (adrLine ?? '').includes('architecture-decision'),
101
+ `architecture-decision keyword alias must be retained in ${adrLine}`,
102
+ ).toBe(true);
103
+ });
104
+
105
+ it('the underscored canonical form "architecture_decision" maps to ct-adr-recorder', () => {
106
+ expect(manifest.dispatch_matrix.by_protocol.architecture_decision).toBe('ct-adr-recorder');
107
+ });
108
+
109
+ it('the by_protocol stage-only key set is exactly equal to the lifecycle stage set', () => {
110
+ expect([...stageOnlyKeys].sort()).toEqual([...expected].sort());
111
+ });
112
+ });
@@ -0,0 +1,163 @@
1
+ /**
2
+ * ADR-link gate for LOOM-stage skills (T9665).
3
+ *
4
+ * Enforces two invariants on every canonical LOOM-stage skill in
5
+ * `packages/skills/skills/manifest.json`:
6
+ *
7
+ * 1. The skill entry declares a non-empty `adrRefs[]` array of ADR IDs.
8
+ * 2. Every ADR id in the array resolves to a real file under `.cleo/adrs/`.
9
+ *
10
+ * The mapping of (stage -> required adrRefs minimum) is the authoritative
11
+ * source-of-truth defined in `docs/skills/loom-coverage-matrix.md` under
12
+ * the "ADR Bindings Section". When that doc updates, this test updates.
13
+ *
14
+ * @task T9665
15
+ * @epic T9568
16
+ */
17
+
18
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
19
+ import { dirname, resolve } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { describe, expect, it } from 'vitest';
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Setup
25
+ // ---------------------------------------------------------------------------
26
+
27
+ const thisDir = dirname(fileURLToPath(import.meta.url));
28
+ const manifestPath = resolve(thisDir, '../../manifest.json');
29
+ const adrDir = resolve(thisDir, '../../../../../.cleo/adrs');
30
+
31
+ interface SkillEntry {
32
+ name: string;
33
+ loomStage?: string;
34
+ adrRefs?: string[];
35
+ [key: string]: unknown;
36
+ }
37
+
38
+ interface Manifest {
39
+ skills: SkillEntry[];
40
+ }
41
+
42
+ const manifest: Manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
43
+
44
+ /**
45
+ * The canonical 10 LOOM lifecycle stages — underscored form is authoritative.
46
+ * Must match `cleo lifecycle --help` output.
47
+ */
48
+ const CANONICAL_LOOM_STAGES = [
49
+ 'research',
50
+ 'consensus',
51
+ 'architecture_decision',
52
+ 'specification',
53
+ 'decomposition',
54
+ 'implementation',
55
+ 'validation',
56
+ 'testing',
57
+ 'release',
58
+ 'contribution',
59
+ ] as const;
60
+
61
+ /**
62
+ * Required ADR-id minimums per stage. The matrix doc may extend each entry;
63
+ * this gate only enforces the floor.
64
+ */
65
+ const REQUIRED_ADR_REFS: Record<(typeof CANONICAL_LOOM_STAGES)[number], string[]> = {
66
+ research: ['ADR-023', 'ADR-070'],
67
+ consensus: ['ADR-015', 'ADR-023'],
68
+ architecture_decision: ['ADR-053', 'ADR-070'],
69
+ specification: ['ADR-014', 'ADR-023'],
70
+ decomposition: ['ADR-066', 'ADR-073'],
71
+ implementation: ['ADR-070', 'ADR-062'],
72
+ validation: ['ADR-051', 'ADR-023'],
73
+ testing: ['ADR-051', 'ADR-061'],
74
+ release: ['ADR-053', 'ADR-063', 'ADR-065'],
75
+ contribution: ['ADR-015', 'ADR-053'],
76
+ };
77
+
78
+ /**
79
+ * Build a set of ADR-id prefixes from .cleo/adrs/. Each filename starts
80
+ * with `ADR-NNN-...`; we extract the prefix before the second dash.
81
+ */
82
+ function loadAdrIdSet(): Set<string> {
83
+ const files = readdirSync(adrDir);
84
+ const ids = new Set<string>();
85
+ for (const file of files) {
86
+ const match = file.match(/^(ADR-\d{3})-/);
87
+ if (match) ids.add(match[1]);
88
+ }
89
+ return ids;
90
+ }
91
+
92
+ const adrIds = loadAdrIdSet();
93
+ const skillsByStage = new Map<string, SkillEntry>();
94
+ for (const s of manifest.skills) {
95
+ if (typeof s.loomStage === 'string') {
96
+ skillsByStage.set(s.loomStage, s);
97
+ }
98
+ }
99
+
100
+ // ---------------------------------------------------------------------------
101
+ // Gate 1: every LOOM-stage skill declares a non-empty adrRefs[]
102
+ // ---------------------------------------------------------------------------
103
+
104
+ describe('LOOM ADR links — adrRefs[] declared on every LOOM-stage skill', () => {
105
+ for (const stage of CANONICAL_LOOM_STAGES) {
106
+ it(`stage "${stage}" skill carries a non-empty adrRefs[]`, () => {
107
+ const skill = skillsByStage.get(stage);
108
+ expect(skill, `no skill found with loomStage="${stage}"`).toBeDefined();
109
+ expect(
110
+ Array.isArray(skill?.adrRefs),
111
+ `skill ${skill?.name} adrRefs is not an array`,
112
+ ).toBe(true);
113
+ expect(
114
+ (skill?.adrRefs ?? []).length,
115
+ `skill ${skill?.name} adrRefs is empty`,
116
+ ).toBeGreaterThan(0);
117
+ });
118
+ }
119
+ });
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // Gate 2: every adrRef resolves to a real file under .cleo/adrs/
123
+ // ---------------------------------------------------------------------------
124
+
125
+ describe('LOOM ADR links — every adrRefs entry resolves to .cleo/adrs/<id>-*.md', () => {
126
+ it('.cleo/adrs/ exists and was loaded', () => {
127
+ expect(existsSync(adrDir), `.cleo/adrs/ not found at ${adrDir}`).toBe(true);
128
+ expect(adrIds.size).toBeGreaterThan(0);
129
+ });
130
+
131
+ for (const stage of CANONICAL_LOOM_STAGES) {
132
+ const skill = skillsByStage.get(stage);
133
+ const refs = skill?.adrRefs ?? [];
134
+ for (const ref of refs) {
135
+ it(`stage "${stage}" skill ${skill?.name} references real ADR file "${ref}"`, () => {
136
+ expect(
137
+ adrIds.has(ref),
138
+ `${ref} not found under .cleo/adrs/ — known prefixes: ${[...adrIds].sort().join(', ')}`,
139
+ ).toBe(true);
140
+ });
141
+ }
142
+ }
143
+ });
144
+
145
+ // ---------------------------------------------------------------------------
146
+ // Gate 3: required ADR floor per stage is met
147
+ // ---------------------------------------------------------------------------
148
+
149
+ describe('LOOM ADR links — required ADR floor met per stage', () => {
150
+ for (const stage of CANONICAL_LOOM_STAGES) {
151
+ const required = REQUIRED_ADR_REFS[stage];
152
+ const skill = skillsByStage.get(stage);
153
+ const refs = new Set(skill?.adrRefs ?? []);
154
+ for (const requiredAdr of required) {
155
+ it(`stage "${stage}" includes required ADR "${requiredAdr}" in adrRefs`, () => {
156
+ expect(
157
+ refs.has(requiredAdr),
158
+ `skill ${skill?.name} for stage ${stage} missing required ADR ${requiredAdr} (has: ${[...refs].join(', ')})`,
159
+ ).toBe(true);
160
+ });
161
+ }
162
+ }
163
+ });
@@ -0,0 +1,167 @@
1
+ /**
2
+ * LOOM-stage coverage gate (T9664).
3
+ *
4
+ * Enforces that every canonical LOOM lifecycle stage emitted by `cleo lifecycle`
5
+ * has a bound skill in `packages/skills/skills/manifest.json` and that the
6
+ * skill's entry declares a `loomStage` field equal to the lifecycle stage name
7
+ * in underscored canonical form (the `cleo lifecycle` source-of-truth form).
8
+ *
9
+ * Why this exists:
10
+ * - The lifecycle CLI is the runtime source of truth for stage names.
11
+ * - The manifest's `dispatch_matrix.by_protocol` is the dispatch routing table.
12
+ * - Historically those two surfaces drifted (T9568 audit found
13
+ * `architecture-decision` dashed in manifest vs `architecture_decision`
14
+ * underscored in lifecycle CLI).
15
+ * - This test pins the contract so future drift fails CI instead of silently
16
+ * reaching agents at spawn time.
17
+ *
18
+ * @task T9664
19
+ * @epic T9568
20
+ */
21
+
22
+ import { readFileSync } from 'node:fs';
23
+ import { dirname, resolve } from 'node:path';
24
+ import { fileURLToPath } from 'node:url';
25
+ import { describe, expect, it } from 'vitest';
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Setup
29
+ // ---------------------------------------------------------------------------
30
+
31
+ const thisDir = dirname(fileURLToPath(import.meta.url));
32
+ const manifestPath = resolve(thisDir, '../../manifest.json');
33
+
34
+ interface SkillEntry {
35
+ name: string;
36
+ protocol?: string;
37
+ loomStage?: string;
38
+ status?: string;
39
+ // intentionally permissive — other fields ignored for this gate
40
+ [key: string]: unknown;
41
+ }
42
+
43
+ interface Manifest {
44
+ dispatch_matrix: {
45
+ by_protocol: Record<string, string>;
46
+ };
47
+ skills: SkillEntry[];
48
+ }
49
+
50
+ const manifest: Manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
51
+
52
+ /**
53
+ * The canonical 10 LOOM lifecycle stages emitted by `cleo lifecycle` (see
54
+ * `packages/core/src/lifecycle/`). Underscored form is authoritative.
55
+ * Update this constant ONLY when the lifecycle CLI itself adds or removes
56
+ * a stage — never to silence a drift failure.
57
+ */
58
+ const CANONICAL_LOOM_STAGES = [
59
+ 'research',
60
+ 'consensus',
61
+ 'architecture_decision',
62
+ 'specification',
63
+ 'decomposition',
64
+ 'implementation',
65
+ 'validation',
66
+ 'testing',
67
+ 'release',
68
+ 'contribution',
69
+ ] as const;
70
+
71
+ /**
72
+ * Cross-cutting protocols that live in `dispatch_matrix.by_protocol` but are
73
+ * NOT LOOM lifecycle stages. They route by capability, not by lifecycle
74
+ * position, and are excluded from the 10-stage gate.
75
+ */
76
+ const CROSS_CUTTING_PROTOCOLS = new Set([
77
+ 'artifact-publish',
78
+ 'provenance',
79
+ 'agent-protocol',
80
+ ]);
81
+
82
+ /**
83
+ * Skill-name lookup keyed by the `name` field.
84
+ */
85
+ const skillByName = new Map(manifest.skills.map((s) => [s.name, s]));
86
+
87
+ // ---------------------------------------------------------------------------
88
+ // Gate 1: every canonical stage has a binding in dispatch_matrix.by_protocol
89
+ // ---------------------------------------------------------------------------
90
+
91
+ describe('LOOM stage coverage — dispatch_matrix.by_protocol', () => {
92
+ for (const stage of CANONICAL_LOOM_STAGES) {
93
+ it(`stage "${stage}" is bound to a skill in dispatch_matrix.by_protocol`, () => {
94
+ // We accept either the underscored form (canonical) or the dashed
95
+ // legacy alias (architecture-decision) until T9672 reconciles. After
96
+ // T9672, only the underscored key is required.
97
+ const dashed = stage.replace(/_/g, '-');
98
+ const skillName =
99
+ manifest.dispatch_matrix.by_protocol[stage] ??
100
+ manifest.dispatch_matrix.by_protocol[dashed];
101
+ expect(
102
+ skillName,
103
+ `LOOM stage "${stage}" has no skill binding in manifest.dispatch_matrix.by_protocol (checked both "${stage}" and "${dashed}")`,
104
+ ).toBeTruthy();
105
+ });
106
+ }
107
+ });
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Gate 2: every protocol-bound skill carries a matching loomStage frontmatter
111
+ // ---------------------------------------------------------------------------
112
+
113
+ describe('LOOM stage coverage — loomStage field on bound skills', () => {
114
+ for (const stage of CANONICAL_LOOM_STAGES) {
115
+ it(`bound skill for "${stage}" declares loomStage === "${stage}"`, () => {
116
+ const dashed = stage.replace(/_/g, '-');
117
+ const skillName =
118
+ manifest.dispatch_matrix.by_protocol[stage] ??
119
+ manifest.dispatch_matrix.by_protocol[dashed];
120
+ const skill = skillName ? skillByName.get(skillName) : undefined;
121
+ expect(skill, `skill "${skillName}" not found in manifest.skills[]`).toBeDefined();
122
+ expect(
123
+ skill?.loomStage,
124
+ `skill "${skillName}" missing loomStage field; expected "${stage}"`,
125
+ ).toBe(stage);
126
+ });
127
+ }
128
+ });
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // Gate 3: every skill that has loomStage uses a canonical (underscored) value
132
+ // ---------------------------------------------------------------------------
133
+
134
+ describe('LOOM stage coverage — loomStage values are canonical', () => {
135
+ const stagesSet = new Set<string>(CANONICAL_LOOM_STAGES);
136
+ const skillsWithLoomStage = manifest.skills.filter((s) => typeof s.loomStage === 'string');
137
+
138
+ it('at least 10 skills carry a loomStage field (one per LOOM stage)', () => {
139
+ expect(skillsWithLoomStage.length).toBeGreaterThanOrEqual(CANONICAL_LOOM_STAGES.length);
140
+ });
141
+
142
+ for (const skill of skillsWithLoomStage) {
143
+ it(`skill "${skill.name}" loomStage value "${skill.loomStage}" is a canonical LOOM stage`, () => {
144
+ expect(stagesSet.has(skill.loomStage as string)).toBe(true);
145
+ });
146
+ }
147
+ });
148
+
149
+ // ---------------------------------------------------------------------------
150
+ // Gate 4: dispatch_matrix.by_protocol keys minus cross-cutting == LOOM stages
151
+ // (the union of the 10 lifecycle stages — checked allowing dashed alias for
152
+ // architecture_decision until T9672 lands the reconcile)
153
+ // ---------------------------------------------------------------------------
154
+
155
+ describe('LOOM stage coverage — dispatch_matrix.by_protocol key set', () => {
156
+ it('by_protocol keys minus cross-cutting protocols cover every canonical LOOM stage', () => {
157
+ const keys = new Set(Object.keys(manifest.dispatch_matrix.by_protocol));
158
+ const stageKeys = [...keys].filter((k) => !CROSS_CUTTING_PROTOCOLS.has(k));
159
+ const normalized = new Set(stageKeys.map((k) => k.replace(/-/g, '_')));
160
+ for (const stage of CANONICAL_LOOM_STAGES) {
161
+ expect(
162
+ normalized.has(stage),
163
+ `LOOM stage "${stage}" not represented in dispatch_matrix.by_protocol (normalized keys: ${[...normalized].join(', ')})`,
164
+ ).toBe(true);
165
+ }
166
+ });
167
+ });
@@ -1,6 +1,11 @@
1
1
  ---
2
2
  name: ct-adr-recorder
3
3
  description: "Records Architecture Decision Records from accepted consensus verdicts. Use when promoting a consensus outcome to a formal ADR: drafts the document in the proposed-then-accepted HITL lifecycle, links to the originating consensus manifest, persists the decision to the canonical SQLite decisions table, and triggers downstream invalidation when an accepted ADR is later superseded. Triggers on phrases like 'write ADR', 'record architecture decision', 'formalize this decision', 'lock in the choice', 'create ADR-XXX', or when a consensus task reaches completed status and needs formalization."
4
+ protocol: architecture_decision
5
+ loomStage: architecture_decision
6
+ adrRefs:
7
+ - ADR-053
8
+ - ADR-070
4
9
  ---
5
10
 
6
11
  # ADR Recorder
@@ -173,3 +178,16 @@ Exit code 0 = valid. Exit code 65 = `HANDOFF_REQUIRED`. Exit code 18 = `CASCADE_
173
178
  6. Superseding an accepted ADR MUST trigger the downstream cascade over linked specs, decomps, and impls.
174
179
  7. Agents MUST NOT retry the HITL handoff on a loop; wait for the human reviewer.
175
180
  8. Always validate via `cleo check protocol --protocolType architecture-decision` before exiting.
181
+
182
+ ## See also / References
183
+
184
+ This skill binds to the **architecture_decision** LOOM lifecycle stage (underscored canonical form — `cleo lifecycle` source of truth). Governing ADRs:
185
+
186
+ - [ADR-053 — playbook runtime](../../../../.cleo/adrs/ADR-053-playbook-runtime.md) — defines the lifecycle state machine; the ADR stage is one of its 10 nodes.
187
+ - [ADR-070 — three-tier orchestration](../../../../.cleo/adrs/ADR-070-three-tier-orchestration.md) — defines the Orchestrator HITL gate that owns the `proposed → accepted` ADR transition.
188
+
189
+ ### Naming Note (T9672)
190
+
191
+ The stage's canonical name is **`architecture_decision`** (underscored) because the `cleo lifecycle` CLI emits it that way. Historically `packages/skills/skills/manifest.json` `dispatch_matrix.by_protocol` used the dashed form `architecture-decision` — T9672 reconciled that key to the underscored form. The dashed form is retained only as a keyword alias under `dispatch_matrix.by_keyword` so legacy dispatch paths continue to resolve. Frontmatter on this skill (`protocol: architecture_decision`, `loomStage: architecture_decision`) uses the underscored form.
192
+
193
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -1,6 +1,11 @@
1
1
  ---
2
2
  name: ct-consensus-voter
3
3
  description: "Runs structured multi-agent voting for decision tasks with confidence scores, conflict detection, and HITL escalation when the threshold is not met. Use when two or more agents must vote on options: architecture choices, tool selection, policy decisions, when a task carries agent_type:analysis, or on phrases like 'reach consensus', 'vote on options', 'resolve the debate', 'pick the best approach'. Produces a voting matrix JSON, enforces the 0.5 threshold, flags ties within 0.1 confidence as contested and escalates to human tiebreak."
4
+ protocol: consensus
5
+ loomStage: consensus
6
+ adrRefs:
7
+ - ADR-015
8
+ - ADR-023
4
9
  ---
5
10
 
6
11
  # Consensus Voter
@@ -156,3 +161,12 @@ This skill typically hands off to ct-adr-recorder on a `PROVEN` verdict so the d
156
161
  6. Manifest entry MUST set `agent_type: "analysis"` and include the verdict.
157
162
  7. On PROVEN, hand off to ct-adr-recorder; on CONTESTED or INSUFFICIENT_EVIDENCE, hand off to HITL.
158
163
  8. Always validate via `cleo check protocol --protocolType consensus`.
164
+
165
+ ## See also / References
166
+
167
+ This skill binds to the **consensus** LOOM lifecycle stage. Governing ADRs:
168
+
169
+ - [ADR-015 — multi-contributor architecture](../../../../.cleo/adrs/ADR-015-multi-contributor-architecture.md) — defines the consensus framework that this skill implements.
170
+ - [ADR-023 — protocol validation dispatch](../../../../.cleo/adrs/ADR-023-protocol-validation-dispatch.md) — defines how consensus output is validated before downstream stages consume it.
171
+
172
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -11,6 +11,10 @@ tier: 3
11
11
  core: false
12
12
  category: meta
13
13
  protocol: contribution
14
+ loomStage: contribution
15
+ adrRefs:
16
+ - ADR-015
17
+ - ADR-053
14
18
  dependencies: []
15
19
  sharedResources:
16
20
  - subagent-protocol-base
@@ -519,3 +523,79 @@ jq -s '[.[] | select(.epicId == "T2204")] | .[0]' .cleo/contributions/CONTRIBUTI
519
523
  | [contribution.schema.json](../../schemas/contribution.schema.json) | **Authoritative** for JSON Schema |
520
524
  | [CONTRIBUTION-PROTOCOL-GUIDE.md](../../docs/guides/CONTRIBUTION-PROTOCOL-GUIDE.md) | Usage guide with examples |
521
525
  | [CONSENSUS-FRAMEWORK-SPEC.md](../../docs/specs/CONSENSUS-FRAMEWORK-SPEC.md) | Consensus voting thresholds |
526
+
527
+ ---
528
+
529
+ ## LOOM Stage Binding (T9670)
530
+
531
+ `ct-contribution` is bound to LOOM lifecycle stage **`contribution`** — the terminal node of the RCASD-IVTR+C pipeline. Use this skill to formalize an Epic's contribution back to canon after its work has converged.
532
+
533
+ ### Stage-Transition Contract
534
+
535
+ The contribution stage is entered from one of two upstream stages depending on the Epic's `kind`:
536
+
537
+ | Upstream stage | Epic kind | Entry condition |
538
+ |---|---|---|
539
+ | **`release`** | most epics (work, bug, experiment) | Release tag pushed; release manifest recorded |
540
+ | **`testing`** | epics whose `kind` is `release` or that gate on IVTR | IVT loop converged; `ivtLoopConverged: true` recorded |
541
+ | **`specification`** | spec-only epics (no code) | Specification accepted; HITL signoff recorded |
542
+
543
+ ```
544
+ research → consensus → architecture_decision → specification → decomposition
545
+ ↓
546
+ implementation
547
+ ↓
548
+ validation
549
+ ↓
550
+ testing ← (some epics return here)
551
+ ↓
552
+ release
553
+ ↓
554
+ contribution ← (this skill)
555
+ ```
556
+
557
+ The transition is enforced by the playbook runtime defined in **ADR-053**. The runtime is a deterministic state machine; `contribution` is its terminal accepting state. Once entered, the Epic is closed in canon.
558
+
559
+ ### Acceptance-Gate Evidence
560
+
561
+ The contribution stage's completion gate is satisfied by emitting **at least one** of the following ADR-051 evidence atoms, recorded via `cleo verify <epicId> --gate contribution --evidence "<atoms>"`:
562
+
563
+ | Atom kind | Format | Meaning |
564
+ |---|---|---|
565
+ | `decision:` | `decision:D-<slug>` | A BRAIN decision id that records the contribution outcome. |
566
+ | `files:` | `files:path/a.md,path/b.md` | A list of contribution-format JSON / markdown deliverables produced by `/contribution submit`. |
567
+ | `note:` | `note:<freeform>` | Owner-attested closure rationale; preferred when the contribution is non-textual (e.g. a tag push referenced by SHA in the note). |
568
+
569
+ Example:
570
+
571
+ ```bash
572
+ cleo verify T9568 --gate contribution \
573
+ --evidence "decision:D-loom-coverage-001;files:.cleo/contributions/T9568-final.json"
574
+ cleo complete T9568
575
+ ```
576
+
577
+ The gate validator (ADR-051 §2.4) rejects an empty evidence string with `E_EVIDENCE_MISSING`. Stale evidence (modified files after `verify` but before `complete`) fails with `E_EVIDENCE_STALE`.
578
+
579
+ ### Open Follow-Up
580
+
581
+ A future ADR dedicated to the contribution stage's lifecycle gates (covering automated rollup signals from `cleo saga rollup`, multi-Epic contribution aggregation, and the contribution → "saga close" promotion path) is on the roadmap. File via:
582
+
583
+ ```bash
584
+ cleo add --kind work --type task --severity P2 \
585
+ --title "T-LOOM-GAP-ADR-CONTRIBUTION: dedicated ADR for contribution stage gates" \
586
+ --relates T9670 \
587
+ --acceptance "ADR drafted under .cleo/adrs/|Cross-referenced from ct-contribution SKILL.md|Validator gate updated"
588
+ ```
589
+
590
+ Until that ADR lands, contribution gates derive from ADR-015 (multi-contributor architecture) and ADR-053 (playbook runtime) — both already referenced in this skill's `adrRefs`.
591
+
592
+ ---
593
+
594
+ ## See also / References
595
+
596
+ This skill binds to the **contribution** LOOM lifecycle stage (the final stage of the RCASD-IVTR+C pipeline). Governing ADRs:
597
+
598
+ - [ADR-015 — multi-contributor architecture](../../../../.cleo/adrs/ADR-015-multi-contributor-architecture.md) — defines the multi-contributor consensus mechanics that this stage formalizes for an Epic's downstream return path.
599
+ - [ADR-053 — playbook runtime](../../../../.cleo/adrs/ADR-053-playbook-runtime.md) — defines the lifecycle state machine; contribution is its terminal node.
600
+
601
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -6,6 +6,10 @@ tier: 1
6
6
  core: false
7
7
  category: recommended
8
8
  protocol: decomposition
9
+ loomStage: decomposition
10
+ adrRefs:
11
+ - ADR-066
12
+ - ADR-073
9
13
  dependencies: []
10
14
  sharedResources:
11
15
  - subagent-protocol-base
@@ -329,3 +333,14 @@ Recommendation: [Your recommendation]
329
333
  | 6 | Validation | Escape `$` as `\$`, check fields |
330
334
 
331
335
  **Shell Escaping**: Always `\$` in `--notes`/`--description`. See [shell-escaping.md](references/shell-escaping.md).
336
+
337
+ ---
338
+
339
+ ## See also / References
340
+
341
+ This skill binds to the **decomposition** LOOM lifecycle stage. Governing ADRs:
342
+
343
+ - [ADR-066 — task taxonomy consolidation](../../../../.cleo/adrs/ADR-066-task-taxonomy-consolidation.md) — defines the Type/Kind/Severity axes the decomposer must populate on every leaf task.
344
+ - [ADR-073 — above-epic naming](../../../../.cleo/adrs/ADR-073-above-epic-naming.md) — defines the Saga/Epic/Task/Subtask hierarchy that decomposition produces.
345
+
346
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -1,6 +1,11 @@
1
1
  ---
2
2
  name: ct-ivt-looper
3
3
  description: "Runs a project-agnostic autonomous Implement-then-Validate-then-Test compliance loop on any git worktree. Detects the project's test framework (vitest, jest, mocha, pytest, unittest, go-test, cargo-test, rspec, phpunit, bats, or other) and iterates until the implementation satisfies its specification, recording convergence metrics to the manifest. Use when given an implementation task that must ship verified: the IVT loop is the autonomous compliance layer enforced before any release or PR. Triggers on phrases like 'implement and verify', 'run the IVT loop', 'ship this task', 'complete implementation with tests', 'verify against spec', or any implementation task with acceptance criteria. Works in any git worktree regardless of language or framework, never hardcoded to one project's tooling."
4
+ protocol: testing
5
+ loomStage: testing
6
+ adrRefs:
7
+ - ADR-051
8
+ - ADR-061
4
9
  ---
5
10
 
6
11
  # IVT Looper
@@ -76,6 +81,24 @@ escalate_to_hitl() # IVT-007: exit code 65
76
81
 
77
82
  The loop is a *single* stage from the lifecycle's point of view. Implement, Validate, and Test are not three separate tasks — they are three phases of one autonomous run that either converges or escalates.
78
83
 
84
+ ## Out of Scope (T9675)
85
+
86
+ `ct-ivt-looper` operates on the **`testing`** LOOM lifecycle stage (stage 8). It performs the **dynamic** Implement-then-Validate-then-Test loop with framework detection and iterate-until-green convergence semantics.
87
+
88
+ This skill does NOT:
89
+
90
+ - Audit static artifacts for schema/compliance/RFC-2119 keyword usage, ADR-document structure, or JSON Schema conformance. Those belong to **`ct-validator`** at the `validation` stage (stage 7). When the question is "is this document/manifest well-formed?" rather than "does this code converge on its spec?", chain to `ct-validator` rather than expanding scope here.
91
+ - Promote a green loop to release. Release sequencing belongs to **`ct-release-orchestrator`** at stage 9.
92
+
93
+ ### Chain handoffs
94
+
95
+ | Direction | When | Handoff |
96
+ |---|---|---|
97
+ | `ct-ivt-looper` → `ct-validator` | Loop converged; need to audit the resulting artifacts (e.g. final manifest, spec back-references) against schema/compliance | Emit the convergence manifest entry, then dispatch the `validation` stage |
98
+ | `ct-validator` → `ct-ivt-looper` | Spec is valid but implementation needs dynamic verification | Receive a dispatch from the `validation` stage; iterate the IVT loop on the worktree |
99
+
100
+ Governance: see **ADR-051** (programmatic gate integrity) which defines the evidence atoms (`tool:test`, `test-run:<json>`) the loop emits and that downstream `cleo verify --gate testsPassed` re-validates, and **ADR-061** (project-agnostic verify tools) which defines the canonical tool-resolution layer.
101
+
79
102
  ## Framework Detection
80
103
 
81
104
  Framework detection is project-agnostic: the skill walks the worktree, inspects config files, and selects the correct test command. No language or framework is special-cased above another. The full detection table lives in [references/frameworks.md](references/frameworks.md). In summary: detection reads the project manifest (`package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Gemfile`, `composer.json`, or `.cleo/project-context.json#testing.command`) and selects one of: `vitest`, `jest`, `mocha`, `pytest`, `unittest`, `go-test`, `cargo-test`, `rspec`, `phpunit`, `bats`, `other`.
@@ -179,3 +202,12 @@ cleo check protocol \
179
202
  6. Record `framework`, `testsRun`, `testsPassed`, `testsFailed`, `ivtLoopConverged`, `ivtLoopIterations` in the manifest.
180
203
  7. On non-convergence, exit 65 and leave the worktree untouched.
181
204
  8. Validate every run via `cleo check protocol --protocolType testing`.
205
+
206
+ ## See also / References
207
+
208
+ This skill binds to the **testing** LOOM lifecycle stage. Governing ADRs:
209
+
210
+ - [ADR-051 — programmatic gate integrity](../../../../.cleo/adrs/ADR-051-programmatic-gate-integrity.md) — defines the evidence atoms (`tool:test`, `test-run:<json>`) that the IVT loop emits and that downstream `cleo verify --gate testsPassed` re-validates.
211
+ - [ADR-061 — project-agnostic verify tools](../../../../.cleo/adrs/ADR-061-project-agnostic-verify-tools.md) — defines the canonical tool-resolution layer (`test`, `build`, `lint`, `typecheck`) that the loop walks for framework-agnostic execution.
212
+
213
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -1,6 +1,12 @@
1
1
  ---
2
2
  name: ct-release-orchestrator
3
3
  description: "Orchestrates the full release pipeline: version bump, then changelog, then commit, then tag, then conditionally forks to artifact-publish and provenance based on release config. Parent protocol that composes ct-artifact-publisher and ct-provenance-keeper as sub-protocols: not every release publishes artifacts (source-only releases skip it), and artifact publishers delegate signing and attestation to provenance. Use when shipping a new version, running cleo release ship, or promoting a completed epic to released status."
4
+ protocol: release
5
+ loomStage: release
6
+ adrRefs:
7
+ - ADR-053
8
+ - ADR-063
9
+ - ADR-065
4
10
  ---
5
11
 
6
12
  # Release Orchestrator
@@ -132,3 +138,13 @@ For source-only releases, pass `--no-artifacts` to skip the artifact-publish han
132
138
  6. `released` entries are immutable; hotfixes go into new entries.
133
139
  7. Manifest entry MUST set `agent_type: "documentation"` and record the full chain via `record_release()`.
134
140
  8. Always validate via `cleo check protocol --protocolType release` before declaring the release done.
141
+
142
+ ## See also / References
143
+
144
+ This skill binds to the **release** LOOM lifecycle stage. Governing ADRs:
145
+
146
+ - [ADR-053 — project-agnostic release pipeline](../../../../.cleo/adrs/ADR-053-project-agnostic-release-pipeline.md) — defines the language-agnostic version bump → changelog → tag flow.
147
+ - [ADR-063 — release pipeline](../../../../.cleo/adrs/ADR-063-release-pipeline.md) — defines the 12-step `cleo release ship` integration with CI.
148
+ - [ADR-065 — PR-required release flow](../../../../.cleo/adrs/ADR-065-pr-required-release-flow.md) — defines the PR-gated path; direct pushes to `main` are prohibited.
149
+
150
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -6,6 +6,10 @@ tier: 2
6
6
  core: false
7
7
  category: recommended
8
8
  protocol: research
9
+ loomStage: research
10
+ adrRefs:
11
+ - ADR-023
12
+ - ADR-070
9
13
  dependencies: []
10
14
  sharedResources:
11
15
  - subagent-protocol-base
@@ -224,3 +228,14 @@ If research cannot proceed (access denied, topic too broad, etc.):
224
228
  - **Prioritized** - Most important first
225
229
  - **Justified** - Tied to specific findings
226
230
  - **Feasible** - Achievable within project constraints
231
+
232
+ ---
233
+
234
+ ## See also / References
235
+
236
+ This skill binds to the **research** LOOM lifecycle stage. Governing ADRs:
237
+
238
+ - [ADR-023 — protocol validation dispatch](../../../../.cleo/adrs/ADR-023-protocol-validation-dispatch.md) — defines how research output is validated before downstream stages consume it.
239
+ - [ADR-070 — three-tier orchestration](../../../../.cleo/adrs/ADR-070-three-tier-orchestration.md) — defines the Orchestrator → Phase Lead → Worker tiers; research runs as a leaf Worker.
240
+
241
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -6,6 +6,10 @@ tier: 2
6
6
  core: false
7
7
  category: recommended
8
8
  protocol: specification
9
+ loomStage: specification
10
+ adrRefs:
11
+ - ADR-014
12
+ - ADR-023
9
13
  dependencies: []
10
14
  sharedResources:
11
15
  - subagent-protocol-base
@@ -187,3 +191,14 @@ Specifications go in: `docs/specs/{{SPEC_NAME}}.md`
187
191
  - [ ] Manifest entry appended
188
192
  - [ ] Task completed via `{{TASK_COMPLETE_CMD}}`
189
193
  - [ ] Return summary message only
194
+
195
+ ---
196
+
197
+ ## See also / References
198
+
199
+ This skill binds to the **specification** LOOM lifecycle stage. Governing ADRs:
200
+
201
+ - [ADR-014 — RCASD rename and protocol validation](../../../../.cleo/adrs/ADR-014-rcasd-rename-and-protocol-validation.md) — defines the specification stage's role inside the RCASD-IVTR+C lifecycle.
202
+ - [ADR-023 — protocol validation dispatch](../../../../.cleo/adrs/ADR-023-protocol-validation-dispatch.md) — defines how specifications are validated before decomposition.
203
+
204
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -6,6 +6,10 @@ tier: 2
6
6
  core: true
7
7
  category: core
8
8
  protocol: implementation
9
+ loomStage: implementation
10
+ adrRefs:
11
+ - ADR-070
12
+ - ADR-062
9
13
  dependencies: []
10
14
  sharedResources:
11
15
  - subagent-protocol-base
@@ -294,3 +298,14 @@ cleo session gc --include-active
294
298
  | Partial deliverables | Missing outputs | Complete all or report partial |
295
299
  | Undocumented changes | Lost context | Write detailed output file |
296
300
  | Silent failures | Orchestrator unaware | Report via manifest status |
301
+
302
+ ---
303
+
304
+ ## See also / References
305
+
306
+ This skill binds to the **implementation** LOOM lifecycle stage. Governing ADRs:
307
+
308
+ - [ADR-070 — three-tier orchestration](../../../../.cleo/adrs/ADR-070-three-tier-orchestration.md) — defines the Worker tier that ct-task-executor occupies.
309
+ - [ADR-062 — worktree merge, not cherry-pick](../../../../.cleo/adrs/ADR-062-worktree-merge-not-cherry-pick.md) — defines the integration path that preserves the executor's commit SHAs end-to-end.
310
+
311
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -6,6 +6,10 @@ tier: 2
6
6
  core: false
7
7
  category: recommended
8
8
  protocol: validation
9
+ loomStage: validation
10
+ adrRefs:
11
+ - ADR-051
12
+ - ADR-023
9
13
  dependencies: []
10
14
  sharedResources:
11
15
  - subagent-protocol-base
@@ -41,6 +45,26 @@ Context injection for compliance validation tasks spawned via cleo-subagent. Pro
41
45
 
42
46
  ---
43
47
 
48
+ ## Out of Scope (T9675)
49
+
50
+ `ct-validator` operates on the **`validation`** LOOM lifecycle stage (stage 7). It performs **static** schema, compliance, and audit checks against artifacts that already exist on disk (specs, ADRs, JSON files, RFC 2119 keyword usage, manifest schemas).
51
+
52
+ This skill does NOT:
53
+
54
+ - Run a test suite, framework detection, or iterative IVT loop. Those belong to **`ct-ivt-looper`** at the `testing` stage (stage 8). When dynamic verification is required — e.g. "does the implementation actually pass its tests?" — chain to `ct-ivt-looper` rather than expanding scope here.
55
+ - Modify code or apply fixes. The validator reports; downstream skills remediate.
56
+
57
+ ### Chain handoffs
58
+
59
+ | Direction | When | Handoff |
60
+ |---|---|---|
61
+ | `ct-validator` → `ct-ivt-looper` | Spec is valid but implementation needs dynamic verification | Emit a manifest entry, then dispatch the `testing` stage |
62
+ | `ct-ivt-looper` → `ct-validator` | IVT loop converged; need to audit the resulting artifacts against schema/compliance | Dispatch the `validation` stage after the test convergence record |
63
+
64
+ Governance: see **ADR-051** (programmatic gate integrity) which defines the evidence atoms each stage emits and that the other stage may re-validate, and **ADR-023** (protocol validation dispatch) which routes between them.
65
+
66
+ ---
67
+
44
68
  ## Validation Methodology
45
69
 
46
70
  ### Standard Workflow
@@ -214,3 +238,14 @@ When invoked by orchestrator, expect these context tokens:
214
238
  | Vague findings | Unclear remediation | Specific issue + file/line + fix |
215
239
  | Missing severity | Can't prioritize | Always classify: critical/warning/suggestion |
216
240
  | No remediation | Findings not actionable | Always provide fix for FAIL/PARTIAL |
241
+
242
+ ---
243
+
244
+ ## See also / References
245
+
246
+ This skill binds to the **validation** LOOM lifecycle stage. Governing ADRs:
247
+
248
+ - [ADR-051 — programmatic gate integrity](../../../../.cleo/adrs/ADR-051-programmatic-gate-integrity.md) — defines the evidence-atom grammar that the validator emits and re-validates.
249
+ - [ADR-023 — protocol validation dispatch](../../../../.cleo/adrs/ADR-023-protocol-validation-dispatch.md) — defines the protocol-validation routing layer that dispatches to this skill.
250
+
251
+ LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "$schema": "https://cleo-dev.com/schemas/v1/skills-manifest.schema.json",
3
3
  "_meta": {
4
- "schemaVersion": "2.4.0",
5
- "lastUpdated": "2026-04-07",
4
+ "schemaVersion": "2.7.0",
5
+ "lastUpdated": "2026-05-19",
6
6
  "totalSkills": 22,
7
- "generatedFrom": "T260 — lifecycle pipeline rework: dedicated skills for ADR, IVT loop, consensus, release, artifact-publish, provenance",
8
- "architectureNote": "Universal Subagent Architecture: All spawns use provider-neutral delegation with skill/protocol injection. Pipeline stages and cross-cutting protocols each have a dedicated skill — no overloading."
7
+ "generatedFrom": "T260 — lifecycle pipeline rework: dedicated skills for ADR, IVT loop, consensus, release, artifact-publish, provenance. T9664/T9665/T9672 (epic T9568) — adds loomStage + adrRefs fields on every LOOM-stage skill entry (underscored canonical form matching `cleo lifecycle` stage names; ADR refs point at .cleo/adrs/). T9672 reconciled dispatch_matrix.by_protocol key 'architecture-decision' → 'architecture_decision' matching the lifecycle CLI source of truth; the dashed form is retained as a keyword alias.",
8
+ "architectureNote": "Universal Subagent Architecture: All spawns use provider-neutral delegation with skill/protocol injection. Pipeline stages and cross-cutting protocols each have a dedicated skill — no overloading.",
9
+ "loomStageContract": "Each of the 10 LOOM lifecycle stages (research, consensus, architecture_decision, specification, decomposition, implementation, validation, testing, release, contribution) MUST have a bound skill whose manifest entry declares loomStage matching the lifecycle CLI stage name. The legacy `protocol` field is retained as an alias; dispatch_matrix.by_protocol is the authoritative routing table. See docs/skills/loom-coverage-matrix.md.",
10
+ "adrRefsContract": "Each LOOM-stage skill MUST declare an adrRefs[] array naming the ADR file(s) that govern the stage. Every referenced ADR-NNN MUST resolve to a file under .cleo/adrs/. The Vitest gate at packages/skills/skills/_shared/__tests__/loom-adr-links.test.ts enforces both conditions."
9
11
  },
10
12
  "dispatch_matrix": {
11
13
  "_comment": "Maps task types/keywords to skill NAMES. Provider adapter decides HOW to execute.",
@@ -33,7 +35,7 @@
33
35
  "spec|rfc|protocol|contract": "ct-spec-writer",
34
36
  "validate|verify|audit|compliance": "ct-validator",
35
37
  "consensus|vote|verdict|resolve the debate": "ct-consensus-voter",
36
- "adr|architecture decision|formalize|lock in the choice": "ct-adr-recorder",
38
+ "adr|architecture decision|architecture-decision|formalize|lock in the choice": "ct-adr-recorder",
37
39
  "release|version|ship|changelog|cut release": "ct-release-orchestrator",
38
40
  "artifact|publish|registry|npm publish|docker push": "ct-artifact-publisher",
39
41
  "provenance|attestation|sbom|sigstore|slsa": "ct-provenance-keeper"
@@ -41,7 +43,7 @@
41
43
  "by_protocol": {
42
44
  "research": "ct-research-agent",
43
45
  "consensus": "ct-consensus-voter",
44
- "architecture-decision": "ct-adr-recorder",
46
+ "architecture_decision": "ct-adr-recorder",
45
47
  "specification": "ct-spec-writer",
46
48
  "decomposition": "ct-epic-architect",
47
49
  "implementation": "ct-task-executor",
@@ -120,6 +122,9 @@
120
122
  "status": "active",
121
123
  "tier": 0,
122
124
  "token_budget": 8000,
125
+ "protocol": "implementation",
126
+ "loomStage": "implementation",
127
+ "adrRefs": ["ADR-070", "ADR-062"],
123
128
  "references": [],
124
129
  "capabilities": {
125
130
  "inputs": ["TASK_ID", "TASK_NAME", "TASK_INSTRUCTIONS", "DELIVERABLES_LIST", "ACCEPTANCE_CRITERIA"],
@@ -148,6 +153,9 @@
148
153
  "status": "active",
149
154
  "tier": 1,
150
155
  "token_budget": 8000,
156
+ "protocol": "decomposition",
157
+ "loomStage": "decomposition",
158
+ "adrRefs": ["ADR-066", "ADR-073"],
151
159
  "references": ["skills/ct-epic-architect/references/bug-epic-example.md", "skills/ct-epic-architect/references/commands.md", "skills/ct-epic-architect/references/feature-epic-example.md"],
152
160
  "capabilities": {
153
161
  "inputs": ["TASK_ID", "FEATURE_NAME", "EPIC_ID", "SESSION_ID"],
@@ -176,6 +184,9 @@
176
184
  "status": "active",
177
185
  "tier": 1,
178
186
  "token_budget": 8000,
187
+ "protocol": "research",
188
+ "loomStage": "research",
189
+ "adrRefs": ["ADR-023", "ADR-070"],
179
190
  "references": [],
180
191
  "capabilities": {
181
192
  "inputs": ["TASK_ID", "TOPIC", "RESEARCH_QUESTIONS"],
@@ -204,6 +215,9 @@
204
215
  "status": "active",
205
216
  "tier": 1,
206
217
  "token_budget": 8000,
218
+ "protocol": "specification",
219
+ "loomStage": "specification",
220
+ "adrRefs": ["ADR-014", "ADR-023"],
207
221
  "references": [],
208
222
  "capabilities": {
209
223
  "inputs": ["TASK_ID", "SPEC_NAME", "spec_topic"],
@@ -232,6 +246,9 @@
232
246
  "status": "active",
233
247
  "tier": 1,
234
248
  "token_budget": 6000,
249
+ "protocol": "validation",
250
+ "loomStage": "validation",
251
+ "adrRefs": ["ADR-051", "ADR-023"],
235
252
  "references": [],
236
253
  "capabilities": {
237
254
  "inputs": ["TASK_ID", "VALIDATION_TARGET", "VALIDATION_CRITERIA"],
@@ -239,7 +256,7 @@
239
256
  "dependencies": [],
240
257
  "dispatch_triggers": ["validate", "verify", "check compliance", "audit"],
241
258
  "compatible_subagent_types": ["general-purpose"],
242
- "chains_to": [],
259
+ "chains_to": ["ct-ivt-looper"],
243
260
  "dispatch_keywords": {
244
261
  "primary": ["validate", "verify", "audit", "compliance"],
245
262
  "secondary": ["check", "conformance", "standards", "requirements"]
@@ -400,6 +417,9 @@
400
417
  "status": "active",
401
418
  "tier": 2,
402
419
  "token_budget": 6000,
420
+ "protocol": "contribution",
421
+ "loomStage": "contribution",
422
+ "adrRefs": ["ADR-015", "ADR-053"],
403
423
  "references": [],
404
424
  "capabilities": {
405
425
  "inputs": ["TASK_ID", "contribution_type", "context"],
@@ -484,7 +504,9 @@
484
504
  "status": "active",
485
505
  "tier": 2,
486
506
  "token_budget": 8000,
487
- "protocol": "architecture-decision",
507
+ "protocol": "architecture_decision",
508
+ "loomStage": "architecture_decision",
509
+ "adrRefs": ["ADR-053", "ADR-070"],
488
510
  "references": [
489
511
  "skills/ct-adr-recorder/references/cascade.md",
490
512
  "skills/ct-adr-recorder/references/examples.md"
@@ -523,6 +545,8 @@
523
545
  "tier": 2,
524
546
  "token_budget": 10000,
525
547
  "protocol": "testing",
548
+ "loomStage": "testing",
549
+ "adrRefs": ["ADR-051", "ADR-061"],
526
550
  "references": [
527
551
  "skills/ct-ivt-looper/references/escalation.md",
528
552
  "skills/ct-ivt-looper/references/frameworks.md",
@@ -562,6 +586,8 @@
562
586
  "tier": 2,
563
587
  "token_budget": 6000,
564
588
  "protocol": "consensus",
589
+ "loomStage": "consensus",
590
+ "adrRefs": ["ADR-015", "ADR-023"],
565
591
  "references": ["skills/ct-consensus-voter/references/matrix-examples.md"],
566
592
  "capabilities": {
567
593
  "inputs": ["task-id", "question", "candidate-options"],
@@ -597,6 +623,8 @@
597
623
  "tier": 2,
598
624
  "token_budget": 8000,
599
625
  "protocol": "release",
626
+ "loomStage": "release",
627
+ "adrRefs": ["ADR-053", "ADR-063", "ADR-065"],
600
628
  "references": [
601
629
  "skills/ct-release-orchestrator/references/composition.md",
602
630
  "skills/ct-release-orchestrator/references/release-types.md"