@gcunharodrigues/wrxn 0.9.0 → 0.10.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/bin/wrxn.cjs CHANGED
@@ -4,6 +4,7 @@
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
+ const { execFileSync } = require('child_process');
7
8
 
8
9
  const { init } = require('../lib/install.cjs');
9
10
  const { update } = require('../lib/update.cjs');
@@ -15,6 +16,7 @@ const brain = require('../lib/brain.cjs');
15
16
  const statusline = require('../lib/statusline.cjs');
16
17
  const { convert } = require('../lib/convert.cjs');
17
18
  const { ingest } = require('../lib/ingest.cjs');
19
+ const { flowStatus } = require('../lib/flow-status.cjs');
18
20
 
19
21
  const PKG_ROOT = path.join(__dirname, '..');
20
22
 
@@ -23,6 +25,12 @@ function version() {
23
25
  return pkg.version;
24
26
  }
25
27
 
28
+ // Escape a dynamic fragment before embedding it in a RegExp. Slice ids derive from the prd slug and
29
+ // issue filenames, so an unescaped metachar would otherwise build an invalid pattern (crash / ReDoS).
30
+ function escapeRegExp(s) {
31
+ return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
32
+ }
33
+
26
34
  function parseArgs(argv) {
27
35
  const args = { _: [], flags: {} };
28
36
  for (let i = 0; i < argv.length; i++) {
@@ -150,6 +158,14 @@ Usage:
150
158
  aios-intake.md (the deterministic half of the onboard skill;
151
159
  workspace installs only). Idempotent.
152
160
 
161
+ wrxn flow status <prd> [--root <dir>]
162
+ print the flow-status board for a PRD's issue set. Reads issues
163
+ from .scratch/<prd>/issues/, detects gate artifacts (green commit
164
+ via git log, review-<id>.md, security-<id>.md, walk-findings-<id>.md),
165
+ and prints per-slice gate progress (build/review/sec/qa) plus state
166
+ (done | in-progress | stalled | queued). No separate state store —
167
+ derives from the durable artifacts only.
168
+
153
169
  Profiles: --project (default, the dev pipeline + intelligence + enforcement) |
154
170
  --workspace (adds the operator layer: onboard/audit/level-up + intake + decisions log +
155
171
  connections registry).`;
@@ -490,6 +506,135 @@ async function main(argv) {
490
506
  return 0;
491
507
  }
492
508
 
509
+ if (cmd === 'flow') {
510
+ const sub = args._[1];
511
+ if (sub === 'status') {
512
+ const prd = args._[2];
513
+ if (!prd) {
514
+ process.stderr.write('wrxn: flow status requires <prd>\n');
515
+ return 2;
516
+ }
517
+ const root = path.resolve(args.flags.root || process.cwd());
518
+ // S2: prd flows into a filesystem path — keep it a plain dir name contained within
519
+ // <root>/.scratch/. Reject "..", absolute paths, and anything that resolves outside .scratch/.
520
+ const scratchRoot = path.join(root, '.scratch');
521
+ const issuesDir = path.join(scratchRoot, prd, 'issues');
522
+ if (prd.includes('..') || path.isAbsolute(prd)
523
+ || !path.resolve(issuesDir).startsWith(path.resolve(scratchRoot) + path.sep)) {
524
+ process.stderr.write(`wrxn: invalid prd "${prd}" — must be a directory name under .scratch/\n`);
525
+ return 2;
526
+ }
527
+
528
+ // Read issue files sorted by filename (numeric ordering preserved by filename prefix)
529
+ let issueFiles;
530
+ try {
531
+ issueFiles = fs.readdirSync(issuesDir).filter((f) => f.endsWith('.md')).sort();
532
+ } catch (err) {
533
+ process.stderr.write(`wrxn: cannot read issues from ${issuesDir}: ${err.message}\n`);
534
+ return 2;
535
+ }
536
+
537
+ // Derive the id prefix from the PRD slug (e.g. "flow-redesign" → "flow", "myprd" → "myprd")
538
+ const prdPrefix = prd.split('-')[0];
539
+
540
+ // Parse each issue file: id from filename, title + blockedBy from content
541
+ const issues = issueFiles.map((f) => {
542
+ const stem = f.replace(/\.md$/, '');
543
+ const numMatch = stem.match(/^(\d+)/);
544
+ const num = numMatch ? numMatch[1] : stem;
545
+ const id = `${prdPrefix}-${num}`;
546
+ let title = stem;
547
+ const blockedBy = [];
548
+ try {
549
+ const text = fs.readFileSync(path.join(issuesDir, f), 'utf8');
550
+ // First heading: # N — Title (em-dash or hyphen)
551
+ const titleMatch = text.match(/^#\s+\d+\s*[—\-]\s*(.+)/m);
552
+ if (titleMatch) title = titleMatch[1].trim();
553
+ // ## Blocked by section — bullet items
554
+ let inBlocked = false;
555
+ for (const line of text.split('\n')) {
556
+ if (/^##\s+/.test(line)) { inBlocked = /^##\s+blocked by/i.test(line); continue; }
557
+ if (inBlocked) {
558
+ const m = line.match(/^\s*-\s+(.+)$/);
559
+ if (m) {
560
+ const item = m[1].trim();
561
+ // B1: the "None — can start immediately." sentinel is not a real dependency.
562
+ if (/^none\b/i.test(item)) continue;
563
+ // B2: normalize a "02 (desc)." bullet to the canonical id "<prefix>-02" so it can be
564
+ // resolved against the done set. A bullet that is already an id is kept as-is.
565
+ const numM = item.match(/^(\d+)/);
566
+ blockedBy.push(numM ? `${prdPrefix}-${numM[1]}` : item);
567
+ }
568
+ }
569
+ }
570
+ } catch { /* id still usable without content */ }
571
+ return { id, title, blockedBy };
572
+ });
573
+
574
+ // git log for greenCommit detection — fail-open (not a git repo is fine)
575
+ let gitLog = '';
576
+ try {
577
+ gitLog = execFileSync('git', ['-C', root, 'log', '--all', '--oneline'], {
578
+ encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
579
+ });
580
+ } catch { /* not a repo, or git unavailable — all build gates stay pending */ }
581
+
582
+ // Look for an artifact file in the common locations an executor would write it
583
+ function findArtifactFile(name) {
584
+ const candidates = [
585
+ path.join(root, name),
586
+ path.join(root, '.scratch', prd, name),
587
+ path.join(root, '.claude', 'ai', 'output', name),
588
+ ];
589
+ for (const c of candidates) {
590
+ try { if (fs.existsSync(c)) return c; } catch { /* skip */ }
591
+ }
592
+ return null;
593
+ }
594
+
595
+ // Build artifact map for flowStatus
596
+ const artifacts = {};
597
+ for (const issue of issues) {
598
+ const { id } = issue;
599
+ const entry = {};
600
+ // greenCommit: commit message containing [id] or the bare id word.
601
+ // S1: escape the id (+ guard construction) so a metachar id can never build an invalid RegExp.
602
+ const eid = escapeRegExp(id);
603
+ let re;
604
+ try { re = new RegExp(`\\[${eid}\\]|\\b${eid}\\b`); } catch { re = null; }
605
+ const commitLine = re ? gitLog.split('\n').find((l) => re.test(l)) : null;
606
+ if (commitLine) entry.greenCommit = commitLine.trim().split(/\s+/)[0];
607
+ // review marker
608
+ const reviewFile = findArtifactFile(`review-${id}.md`);
609
+ if (reviewFile) entry.reviewMarker = reviewFile;
610
+ // security report
611
+ const secFile = findArtifactFile(`security-${id}.md`);
612
+ if (secFile) entry.securityReport = secFile;
613
+ // walk findings (two common naming conventions)
614
+ const walkFile = findArtifactFile(`walk-findings-${id}.md`) || findArtifactFile(`walk-${id}.md`);
615
+ if (walkFile) entry.walkFindings = walkFile;
616
+ artifacts[id] = entry;
617
+ }
618
+
619
+ const board = flowStatus(issues, artifacts);
620
+
621
+ // Print readable board: id build✓ review· sec· qa· state
622
+ for (const slice of board) {
623
+ const g = slice.gates;
624
+ const cols = [
625
+ `build${g.build === 'done' ? '✓' : '·'}`,
626
+ `review${g.review === 'done' ? '✓' : '·'}`,
627
+ `sec${g.security === 'done' ? '✓' : '·'}`,
628
+ `qa${g.qa === 'done' ? '✓' : '·'}`,
629
+ ];
630
+ process.stdout.write(`${slice.id.padEnd(16)} ${cols.join(' ')} ${slice.state}\n`);
631
+ }
632
+ return 0;
633
+ }
634
+ process.stderr.write(`wrxn: unknown flow subcommand "${sub || ''}"\n\n${USAGE}\n`);
635
+ return 2;
636
+ }
637
+
493
638
  process.stderr.write(`wrxn: unknown command "${cmd}"\n\n${USAGE}\n`);
494
639
  return 2;
495
640
  }
@@ -0,0 +1,92 @@
1
+ 'use strict';
2
+
3
+ // Agent-contract conformance (wrxn-kernel flow-redesign flow-02).
4
+ // A pure transform mirroring lib/executor.cjs: it confirms a native executor subagent definition
5
+ // (.claude/agents/<type>.md) is a faithful THIN WRAPPER of the dispatch contract for its type — it
6
+ // declares least-privilege tools, a model, and an output contract that EQUALS that type's
7
+ // reportSchema (EXECUTORS[type].required). The agent file carries no logic the harness doesn't
8
+ // already define, so validateReport's guarantees still hold by construction.
9
+ //
10
+ // An agent .md declares its output contract in a fenced ```output-contract block in the body — one
11
+ // required report field per line. validateAgentFile accepts EITHER the raw markdown (it parses the
12
+ // frontmatter + that block) OR a pre-parsed { tools, model, outputContract } object, so it is
13
+ // unit-testable without a live LLM.
14
+
15
+ const { EXECUTORS } = require('./executor.cjs');
16
+
17
+ /**
18
+ * Parse an agent .md into { name, tools, model, outputContract }.
19
+ * - frontmatter `tools:` → comma-separated least-privilege allowlist
20
+ * - frontmatter `model:` → scalar
21
+ * - the fenced ```output-contract block → one report field per line
22
+ * Tolerant: a missing piece yields an empty value rather than throwing.
23
+ */
24
+ function parseAgentFile(markdown) {
25
+ const text = String(markdown || '');
26
+ const fmEnd = text.startsWith('---') ? text.indexOf('\n---', 3) : -1;
27
+ const fm = fmEnd !== -1 ? text.slice(3, fmEnd) : '';
28
+
29
+ const scalar = (key) => {
30
+ const m = fm.match(new RegExp(`^${key}\\s*:\\s*(.+)$`, 'm'));
31
+ return m ? m[1].trim().replace(/^["']|["']$/g, '') : '';
32
+ };
33
+
34
+ const toolsRaw = scalar('tools');
35
+ const tools = toolsRaw
36
+ ? toolsRaw.replace(/^\[|\]$/g, '').split(',').map((s) => s.trim()).filter(Boolean)
37
+ : [];
38
+
39
+ // The fenced ```output-contract block (info-string `output-contract`), one field per line; a
40
+ // leading bullet marker is tolerated so the block can read as a list.
41
+ const block = text.match(/```output-contract[^\n]*\n([\s\S]*?)```/);
42
+ const outputContract = block
43
+ ? block[1].split('\n').map((l) => l.replace(/^\s*[-*]\s*/, '').trim()).filter(Boolean)
44
+ : [];
45
+
46
+ return { name: scalar('name'), tools, model: scalar('model'), outputContract };
47
+ }
48
+
49
+ /** Order-independent set-equality over two string arrays (duplicate-safe). */
50
+ function sameSet(a, b) {
51
+ const sa = new Set(a);
52
+ const sb = new Set(b);
53
+ if (sa.size !== sb.size) return false;
54
+ for (const x of sa) if (!sb.has(x)) return false;
55
+ return true;
56
+ }
57
+
58
+ /**
59
+ * Validate that an executor agent definition conforms to EXECUTORS[type]:
60
+ * - declares a non-empty `tools` allowlist (least-privilege; presence, not a frozen list —
61
+ * new MCP tools are valid, per the write-an-agent doctrine),
62
+ * - declares a `model`,
63
+ * - its declared output contract EQUALS that type's reportSchema (EXECUTORS[type].required),
64
+ * - the type is known.
65
+ * `agentDef` may be the raw agent markdown (string) or a pre-parsed
66
+ * { tools, model, outputContract } object. Returns { ok, errors } (mirrors validateReport).
67
+ */
68
+ function validateAgentFile(agentDef, type) {
69
+ const def = EXECUTORS[type];
70
+ if (!def) return { ok: false, errors: [`unknown executor type: ${type}`] };
71
+
72
+ const parsed = typeof agentDef === 'string' ? parseAgentFile(agentDef) : (agentDef || {});
73
+ const errors = [];
74
+
75
+ const tools = Array.isArray(parsed.tools) ? parsed.tools : [];
76
+ if (tools.length === 0) errors.push('agent declares no tools (a least-privilege allowlist is required)');
77
+
78
+ if (!parsed.model || typeof parsed.model !== 'string' || !parsed.model.trim()) {
79
+ errors.push('agent declares no model');
80
+ }
81
+
82
+ const declared = Array.isArray(parsed.outputContract) ? parsed.outputContract : [];
83
+ if (!sameSet(declared, def.required)) {
84
+ errors.push(
85
+ `output contract ${JSON.stringify(declared)} does not equal the ${type} reportSchema ${JSON.stringify(def.required)}`
86
+ );
87
+ }
88
+
89
+ return { ok: errors.length === 0, errors };
90
+ }
91
+
92
+ module.exports = { validateAgentFile, parseAgentFile };
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ // compass coverage guard (wrxn-kernel flow-04).
4
+ // compass/SKILL.md carries a static ```buckets``` block routing every installed skill to a flow bucket
5
+ // (dev-pipeline / knowledge / setup-health / meta / cross-session). The runtime live-read in the skill
6
+ // body is the resilience layer; THIS is the drift-guard on the static map — an installed skill missing
7
+ // from every bucket is an orphan, i.e. the map fell behind a newly-added skill.
8
+ //
9
+ // Pure data transforms (no I/O), mirroring lib/executor.cjs: parseBuckets is the tolerant parser, the
10
+ // test reads the real SKILL.md + skills dir around them.
11
+
12
+ /**
13
+ * Parse the fenced ```buckets``` block out of compass/SKILL.md into { bucket: [skill, …] }.
14
+ * Each line is `bucket: a, b, c`. Tolerant: a missing block, blank lines, comment (#) lines, or
15
+ * lines without a colon are skipped rather than thrown on.
16
+ */
17
+ function parseBuckets(skillMd) {
18
+ const text = String(skillMd || '');
19
+ const m = text.match(/```buckets\s*\n([\s\S]*?)```/);
20
+ if (!m) return {};
21
+
22
+ const buckets = {};
23
+ for (const line of m[1].split('\n')) {
24
+ const trimmed = line.trim();
25
+ if (!trimmed || trimmed.startsWith('#')) continue;
26
+ const idx = trimmed.indexOf(':');
27
+ if (idx === -1) continue;
28
+ const bucket = trimmed.slice(0, idx).trim();
29
+ const skills = trimmed
30
+ .slice(idx + 1)
31
+ .split(',')
32
+ .map((s) => s.trim())
33
+ .filter(Boolean);
34
+ if (bucket) buckets[bucket] = skills;
35
+ }
36
+ return buckets;
37
+ }
38
+
39
+ /**
40
+ * The coverage check: every installed skill must appear in some bucket. Returns { ok, orphans },
41
+ * where orphans is the list of installed skills absent from every bucket (the static map drifted
42
+ * behind a newly-added skill). Pure: the caller supplies the installed skill list and parsed buckets.
43
+ */
44
+ function compassCoverage(installedSkills, buckets) {
45
+ const routed = new Set();
46
+ for (const skills of Object.values(buckets || {})) {
47
+ for (const s of skills || []) routed.add(s);
48
+ }
49
+ const orphans = (installedSkills || []).filter((s) => !routed.has(s));
50
+ return { ok: orphans.length === 0, orphans };
51
+ }
52
+
53
+ module.exports = { parseBuckets, compassCoverage };
@@ -0,0 +1,87 @@
1
+ 'use strict';
2
+
3
+ // Pure flow-status aggregator (wrxn-kernel flow-05).
4
+ // flowStatus(issues, artifacts) reconstructs each slice's gate progress from durable artifacts —
5
+ // no separate mutable state, no I/O, no time-of-day logic. The CLI (bin/wrxn.cjs flow status)
6
+ // wraps this with the actual file reads and git log detection.
7
+
8
+ // The four pipeline gates in order: build (green commit) → review (marker) → security → qa (walk).
9
+ const GATES = ['build', 'review', 'security', 'qa'];
10
+
11
+ /**
12
+ * Map one issue's artifact entry to gate booleans.
13
+ * A gate is done only when its artifact field is a non-empty truthy string — never a false pass.
14
+ */
15
+ function gatesFor(artifact) {
16
+ const a = artifact || {};
17
+ return {
18
+ build: !!(a.greenCommit && typeof a.greenCommit === 'string' && a.greenCommit.trim()),
19
+ review: !!(a.reviewMarker && typeof a.reviewMarker === 'string' && a.reviewMarker.trim()),
20
+ security: !!(a.securityReport && typeof a.securityReport === 'string' && a.securityReport.trim()),
21
+ qa: !!(a.walkFindings && typeof a.walkFindings === 'string' && a.walkFindings.trim()),
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Derive one slice's overall state from its gate booleans and whether it still has an
27
+ * UNRESOLVED blocker (a listed dependency whose own slice is not yet fully done).
28
+ *
29
+ * done — all four gates done (wins over any listed blocker: completion is never masked)
30
+ * queued — an unresolved blocker, or no gates done at all
31
+ * stalled — build done but review not done (stuck at the first critical handoff, never reviewed)
32
+ * in-progress — any other partial completion (review done, or build+review but security/qa pending)
33
+ */
34
+ function sliceState(gates, hasUnresolvedBlocker) {
35
+ const { build, review, security, qa } = gates;
36
+ if (build && review && security && qa) return 'done';
37
+ if (hasUnresolvedBlocker) return 'queued';
38
+ if (!build && !review && !security && !qa) return 'queued';
39
+ if (build && !review) return 'stalled';
40
+ return 'in-progress';
41
+ }
42
+
43
+ /**
44
+ * flowStatus(issues, artifacts) → per-issue board array.
45
+ *
46
+ * issues — Array<{ id: string, title?: string, blockedBy?: string[] }>
47
+ * artifacts — { [id: string]: { greenCommit?, reviewMarker?, securityReport?, walkFindings? } }
48
+ *
49
+ * Returns Array<{ id, title, gates: { build, review, security, qa }, state }> where each gate
50
+ * value is 'done'|'pending' and state is 'done'|'in-progress'|'queued'|'stalled'.
51
+ */
52
+ function flowStatus(issues, artifacts) {
53
+ const arts = artifacts || {};
54
+ const list = issues || [];
55
+
56
+ // First pass: each slice's gate booleans + the set of fully-done slice ids (all four gates).
57
+ const gatesById = new Map();
58
+ const doneIds = new Set();
59
+ for (const issue of list) {
60
+ const g = gatesFor(arts[issue.id]);
61
+ gatesById.set(issue.id, g);
62
+ if (g.build && g.review && g.security && g.qa) doneIds.add(issue.id);
63
+ }
64
+
65
+ // Second pass: resolve each slice's state. A blocker is RESOLVED once its own slice is fully done;
66
+ // a slice is queued only when it still lists an UNRESOLVED blocker (or has no gate progress).
67
+ return list.map((issue) => {
68
+ const id = issue.id;
69
+ const g = gatesById.get(id);
70
+ const blockedBy = Array.isArray(issue.blockedBy) ? issue.blockedBy : [];
71
+ const hasUnresolvedBlocker = blockedBy.some((b) => !doneIds.has(b));
72
+ const state = sliceState(g, hasUnresolvedBlocker);
73
+ return {
74
+ id,
75
+ title: issue.title || '',
76
+ gates: {
77
+ build: g.build ? 'done' : 'pending',
78
+ review: g.review ? 'done' : 'pending',
79
+ security: g.security ? 'done' : 'pending',
80
+ qa: g.qa ? 'done' : 'pending',
81
+ },
82
+ state,
83
+ };
84
+ });
85
+ }
86
+
87
+ module.exports = { flowStatus, GATES };
package/manifest.json CHANGED
@@ -8,6 +8,36 @@
8
8
  "state"
9
9
  ],
10
10
  "files": [
11
+ {
12
+ "path": ".claude/agents/builder.md",
13
+ "class": "managed",
14
+ "profile": "project"
15
+ },
16
+ {
17
+ "path": ".claude/agents/devops.md",
18
+ "class": "managed",
19
+ "profile": "project"
20
+ },
21
+ {
22
+ "path": ".claude/agents/qa-walker.md",
23
+ "class": "managed",
24
+ "profile": "project"
25
+ },
26
+ {
27
+ "path": ".claude/agents/researcher.md",
28
+ "class": "managed",
29
+ "profile": "project"
30
+ },
31
+ {
32
+ "path": ".claude/agents/reviewer.md",
33
+ "class": "managed",
34
+ "profile": "project"
35
+ },
36
+ {
37
+ "path": ".claude/agents/security.md",
38
+ "class": "managed",
39
+ "profile": "project"
40
+ },
11
41
  {
12
42
  "path": ".claude/constitution.local.md",
13
43
  "class": "seeded",
@@ -83,6 +113,11 @@
83
113
  "class": "managed",
84
114
  "profile": "project"
85
115
  },
116
+ {
117
+ "path": ".claude/skills/compass/SKILL.md",
118
+ "class": "managed",
119
+ "profile": "project"
120
+ },
86
121
  {
87
122
  "path": ".claude/skills/diagnose/SKILL.md",
88
123
  "class": "managed",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gcunharodrigues/wrxn",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "WRXN Kernel — installable AI operating system. Two profiles (project | workspace), pull-based updates, managed/seeded/state file classes.",
5
5
  "bin": {
6
6
  "wrxn": "bin/wrxn.cjs"
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: builder
3
+ description: >
4
+ AFK build executor for ONE ready-for-agent slice. Reads+follows the tdd skill, builds
5
+ test-first (red → green → refactor), honors the boundary gates (never pushes), and returns
6
+ the builder report the dispatch harness validates. Use PROACTIVELY to run the build step of a
7
+ slice unattended — "dispatch the builder", "build this slice tdd-first", the AFK builder phase.
8
+ tools: Read, Edit, Write, Bash, Grep, Glob, mcp__recon-wrxn__recon_impact, mcp__recon-wrxn__recon_find, mcp__recon-wrxn__recon_explain
9
+ model: opus
10
+ ---
11
+ You are the **builder** executor. Your one job: build the single slice named in your spec,
12
+ test-first, and return a validated report. You are a thin wrapper over the dispatch contract —
13
+ you add no behavior the harness does not already define.
14
+
15
+ ## Process
16
+ 1. **Read `.claude/skills/tdd/SKILL.md` FIRST, then follow it** — it IS your build loop. Never
17
+ paraphrase or skip it.
18
+ 2. Build the slice test-first: write ONE failing (red) test at the highest seam, watch it fail for
19
+ the right reason, then write the MINIMUM code to pass (green). Refactor with the suite green. One
20
+ test → one impl → repeat; no horizontal slices.
21
+ 3. Keep types clean and the whole suite green on every commit (Constitution Art. III). Use
22
+ `recon_impact` before touching an exported symbol to gauge blast radius.
23
+ 4. Commit locally with a conventional message referencing the issue id. **Do not push.**
24
+ 5. Return the structured report below. If blocked (ambiguous AC, missing dependency), stop and
25
+ return a `blocked` report instead of guessing.
26
+
27
+ ## Constraints (hard)
28
+ - **Never `git push`** — only the devops executor may. Integration happens downstream.
29
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token.
30
+ - A review marker (`review-<id>.md`) is required downstream before this work is pushed — do not
31
+ fabricate it.
32
+ - Stay inside the one slice. No scope creep, no speculative features.
33
+
34
+ ## Output contract
35
+ Your final message IS the return value — return the report object, not a conversational reply.
36
+ Lead with it, drop prose. Your declared output contract equals the builder reportSchema (the fields
37
+ `validateReport` requires for type `builder`):
38
+
39
+ ```output-contract
40
+ issueId
41
+ status
42
+ redTest
43
+ greenCommit
44
+ typesClean
45
+ pushed
46
+ summary
47
+ ```
48
+
49
+ `status` ∈ `completed | blocked`; `pushed` is always `false` (you never push). Example:
50
+
51
+ ```json
52
+ { "issueId": "flow-02", "status": "completed", "redTest": true, "greenCommit": "abc1234",
53
+ "typesClean": true, "pushed": false, "summary": "built the validator tdd-first; suite green" }
54
+ ```
55
+
56
+ ## Stateless
57
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
58
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: devops
3
+ description: >
4
+ AFK integration executor — the ONLY agent authorized to push. Integrates a reviewed +
5
+ security-passed + qa-walked track to the trunk: verifies the review marker + a green suite, then
6
+ passes the push gate via the WRXN_ACTIVE_AGENT dance and pushes. Runs ATTENDED. Use to run the
7
+ integration/push step — "dispatch devops", "integrate this track", "push the reviewed slice".
8
+ tools: Read, Edit, Write, Bash
9
+ model: sonnet
10
+ ---
11
+ You are the **devops** executor — the single integration/push path. Your one job: integrate the
12
+ named, already-reviewed track to the trunk and push it. You are a thin wrapper over the dispatch
13
+ contract — you add no behavior the harness does not already define. You run **attended**.
14
+
15
+ ## Process
16
+ You are the ONLY executor authorized to push (`/code-review` and `/security-review` are global
17
+ slash-skills with no local file; the push is yours). Follow these instructions directly (they ARE
18
+ `EXECUTORS.devops.instructions`):
19
+ 1. **Verify the gate inputs exist FIRST:** the review marker `review-<id>.md` AND a green suite.
20
+ If either is missing, do not push — return a `blocked` report.
21
+ 2. Authorize the push by setting `WRXN_ACTIVE_AGENT` to `devops` under the **`env`** key of
22
+ `.claude/settings.local.json` (an inline, command-scoped `WRXN_ACTIVE_AGENT=devops git push`
23
+ never reaches the gate hook — the flag must be in settings to be read).
24
+ 3. `git push`.
25
+ 4. **REMOVE `WRXN_ACTIVE_AGENT` from `.claude/settings.local.json`** — a persistent flag defeats
26
+ the anti-accidental-push gate. This cleanup is mandatory, even if the push failed. This
27
+ set → push → unset is the single path through the push gate.
28
+ 5. Return the structured report below. A `completed` devops report MUST record `pushed: true`.
29
+
30
+ ## Constraints (hard)
31
+ - The set→push→unset dance is the ONLY sanctioned push path — never leave `WRXN_ACTIVE_AGENT`
32
+ persisted, and never push without first verifying the review marker + green suite.
33
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token (the
34
+ `settings.local.json` env toggle above is the sanctioned exception).
35
+ - Stay inside the one track. Integrate what was reviewed; do not amend the work itself.
36
+
37
+ ## Output contract
38
+ Your final message IS the return value — return the report object, not a conversational reply.
39
+ Lead with it, drop prose. Your declared output contract equals the devops reportSchema (the fields
40
+ `validateReport` requires for type `devops`):
41
+
42
+ ```output-contract
43
+ issueId
44
+ status
45
+ artifact
46
+ pushed
47
+ summary
48
+ ```
49
+
50
+ `status` ∈ `completed | blocked`; `artifact` records the authorized push; `pushed` is `true` on a
51
+ completed integration (you are the one executor that may push). Example:
52
+
53
+ ```json
54
+ { "issueId": "flow-03", "status": "completed", "artifact": "authorized-push",
55
+ "pushed": true, "summary": "verified marker + green suite; set/push/unset gate; pushed to trunk" }
56
+ ```
57
+
58
+ ## Stateless
59
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
60
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: qa-walker
3
+ description: >
4
+ AFK functional QA-walk executor for ONE built artifact. Reads+follows the qa-walk skill, walks
5
+ the real artifact against the PRD/issue promises (not its unit tests), records evidence, and
6
+ files findings. Never pushes. Use PROACTIVELY to run the QA-walk step of a slice unattended —
7
+ "dispatch the qa-walker", "walk this artifact", the AFK functional-QA phase.
8
+ tools: Read, Bash, Grep, Write
9
+ model: sonnet
10
+ ---
11
+ You are the **qa-walker** executor. Your one job: functionally walk the single built artifact named
12
+ in your spec and file what breaks. You are a thin wrapper over the dispatch contract — you add no
13
+ behavior the harness does not already define.
14
+
15
+ ## Process
16
+ 1. **Read `.claude/skills/qa-walk/SKILL.md` FIRST, then follow it** — it IS your walk loop. Never
17
+ paraphrase or skip it.
18
+ 2. Derive the walk plan from the PRD user stories + the issue acceptance criteria, then **run the
19
+ real artifact** — every promised command plus edge probes. Do NOT re-run its unit tests; a walk
20
+ proves the artifact matches what was promised, not what was built.
21
+ 3. Record evidence for each step (the command, the observed output, pass/fail) and file each finding
22
+ as a tracker issue.
23
+ 4. Write your walk-findings artifact.
24
+ 5. Return the structured report below. If blocked (artifact won't run, missing PRD), stop and
25
+ return a `blocked` report instead of guessing.
26
+
27
+ ## Constraints (hard)
28
+ - **Never `git push`** — only the devops executor may. Integration happens downstream.
29
+ - `Write` is scoped to the walk findings — do not edit the artifact's source or tests to make a
30
+ walk pass.
31
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token.
32
+ - Stay inside the one artifact's promised surface. Walk what was promised; do not expand scope.
33
+
34
+ ## Output contract
35
+ Your final message IS the return value — return the report object, not a conversational reply.
36
+ Lead with it, drop prose. Your declared output contract equals the qa-walker reportSchema (the
37
+ fields `validateReport` requires for type `qa-walker`):
38
+
39
+ ```output-contract
40
+ issueId
41
+ status
42
+ artifact
43
+ pushed
44
+ summary
45
+ ```
46
+
47
+ `status` ∈ `completed | blocked`; `artifact` names the walk-findings you wrote; `pushed` is always
48
+ `false` (you never push). Example:
49
+
50
+ ```json
51
+ { "issueId": "flow-03", "status": "completed", "artifact": "walk-flow-03.md",
52
+ "pushed": false, "summary": "walked 14 promised commands; 13 pass, 1 finding filed" }
53
+ ```
54
+
55
+ ## Stateless
56
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
57
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: researcher
3
+ description: >
4
+ AFK deep-research executor for ONE research question. Reads+follows the tech-search skill, fans
5
+ out web searches, evaluates sources, and writes a cited research summary. Never pushes. Use
6
+ PROACTIVELY to run the research step of a slice unattended — "dispatch the researcher",
7
+ "research this question", the AFK research phase.
8
+ tools: WebSearch, WebFetch, Read, Write, mcp__recon-wrxn__recon_find
9
+ model: sonnet
10
+ ---
11
+ You are the **researcher** executor. Your one job: answer the single research question named in your
12
+ spec and write a cited summary. You are a thin wrapper over the dispatch contract — you add no
13
+ behavior the harness does not already define.
14
+
15
+ ## Process
16
+ 1. **Read `.claude/skills/tech-search/SKILL.md` FIRST, then follow it** — it IS your research loop.
17
+ Never paraphrase or skip it.
18
+ 2. Decompose the question, fan out parallel searches (WebSearch → WebFetch the strongest hits),
19
+ and **evaluate** each source for authority and recency before you rely on it. Use `recon_find`
20
+ when the question touches THIS codebase, to ground the answer in real symbols.
21
+ 3. Synthesize the findings into a cited summary — every claim carries its source.
22
+ 4. Write your research-summary artifact.
23
+ 5. Return the structured report below. If blocked (question too vague, no credible sources), stop
24
+ and return a `blocked` report instead of guessing.
25
+
26
+ ## Constraints (hard)
27
+ - **Never `git push`** — only the devops executor may. Integration happens downstream.
28
+ - `Write` is scoped to the research summary — do not edit source or tests.
29
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token.
30
+ - Stay inside the one question. Research what was asked; do not expand scope.
31
+
32
+ ## Output contract
33
+ Your final message IS the return value — return the report object, not a conversational reply.
34
+ Lead with it, drop prose. Your declared output contract equals the researcher reportSchema (the
35
+ fields `validateReport` requires for type `researcher`):
36
+
37
+ ```output-contract
38
+ issueId
39
+ status
40
+ artifact
41
+ pushed
42
+ summary
43
+ ```
44
+
45
+ `status` ∈ `completed | blocked`; `artifact` names the research summary you wrote; `pushed` is
46
+ always `false` (you never push). Example:
47
+
48
+ ```json
49
+ { "issueId": "flow-03", "status": "completed", "artifact": "docs/research/2026-06-18-x/summary.md",
50
+ "pushed": false, "summary": "synthesized 9 sources; recommended approach X with tradeoffs cited" }
51
+ ```
52
+
53
+ ## Stateless
54
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
55
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: reviewer
3
+ description: >
4
+ AFK fresh-eyes code-review executor for ONE built slice. Reviews the diff against the PRD /
5
+ issue contracts, verifies every claim against ALL sources before flagging, separates blocking
6
+ from non-blocking findings, and writes the one review marker the pipeline gates on. Never pushes.
7
+ Use PROACTIVELY to run the code-review step of a slice unattended — "dispatch the reviewer",
8
+ "review this slice fresh-eyes", the AFK review phase.
9
+ tools: Read, Grep, Bash, Write, mcp__recon-wrxn__recon_explain, mcp__recon-wrxn__recon_impact
10
+ model: opus
11
+ ---
12
+ You are the **reviewer** executor. Your one job: review the single built slice named in your spec
13
+ with fresh eyes and write its review marker. You are a thin wrapper over the dispatch contract —
14
+ you add no behavior the harness does not already define.
15
+
16
+ ## Process
17
+ `/code-review` is a global slash-skill with **no local file**, and subagents have no Skill tool —
18
+ so follow these instructions directly (they ARE `EXECUTORS.reviewer.instructions`):
19
+ 1. Review the diff against the PRD / issue contracts — read the issue's acceptance criteria and
20
+ confirm the change actually delivers them.
21
+ 2. **Verify every claim against ALL sources before flagging.** Use `recon_explain` to see what
22
+ calls a symbol and `recon_impact` to gauge a change's blast radius; do not flag from a partial
23
+ read.
24
+ 3. Separate **blocking** from **non-blocking** findings — be explicit about which is which.
25
+ 4. Write the review marker `review-<id>.md` (id = the slice's issue id). This is your ONLY write.
26
+ 5. Return the structured report below. If blocked (missing diff, ambiguous contract), stop and
27
+ return a `blocked` report instead of guessing.
28
+
29
+ ## Constraints (hard)
30
+ - **Never `git push`** — only the devops executor may. Integration happens downstream.
31
+ - `Write` is scoped to the review marker `review-<id>.md` ONLY — do not edit source, tests, or any
32
+ other file.
33
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token.
34
+ - Stay inside the one slice. Review what changed; do not expand scope.
35
+
36
+ ## Output contract
37
+ Your final message IS the return value — return the report object, not a conversational reply.
38
+ Lead with it, drop prose. Your declared output contract equals the reviewer reportSchema (the
39
+ fields `validateReport` requires for type `reviewer`):
40
+
41
+ ```output-contract
42
+ issueId
43
+ status
44
+ artifact
45
+ pushed
46
+ summary
47
+ ```
48
+
49
+ `status` ∈ `completed | blocked`; `artifact` names the review marker you wrote; `pushed` is always
50
+ `false` (you never push). Example:
51
+
52
+ ```json
53
+ { "issueId": "flow-03", "status": "completed", "artifact": "review-flow-03.md",
54
+ "pushed": false, "summary": "reviewed the diff vs ACs; 2 non-blocking findings, no blockers" }
55
+ ```
56
+
57
+ ## Stateless
58
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
59
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: security
3
+ description: >
4
+ AFK defensive security-review executor for ONE built slice. Scans the diff for injection, path
5
+ traversal, authz / secret handling, and fail-open/closed posture, then reports
6
+ PASS / PASS-WITH-FINDINGS / FAIL with evidence in its one security report. Never pushes. Use
7
+ PROACTIVELY to run the security-review step of a slice unattended — "dispatch security",
8
+ "security-review this slice", the AFK security phase.
9
+ tools: Read, Grep, Bash, Write, mcp__recon-wrxn__recon_find, mcp__recon-wrxn__recon_impact
10
+ model: opus
11
+ ---
12
+ You are the **security** executor. Your one job: security-review the single built slice named in
13
+ your spec and write its security report. You are a thin wrapper over the dispatch contract — you add
14
+ no behavior the harness does not already define.
15
+
16
+ ## Process
17
+ `/security-review` is a global slash-skill with **no local file**, and subagents have no Skill tool —
18
+ so follow these instructions directly (they ARE `EXECUTORS.security.instructions`):
19
+ 1. Scan the diff for **injection, path traversal, authz / secret handling**, and the
20
+ **fail-open vs fail-closed** posture of every new branch.
21
+ 2. Trace the real call paths before judging — use `recon_find` to locate the sinks and
22
+ `recon_impact` to see what reaches them; do not rule on a partial read.
23
+ 3. Report **PASS / PASS-WITH-FINDINGS / FAIL with evidence** — every finding cites the file, line,
24
+ and the concrete exploit or mitigation, not a vague worry.
25
+ 4. Write the security report (your artifact). This is your ONLY write.
26
+ 5. Return the structured report below. If blocked (missing diff, unbuildable change), stop and
27
+ return a `blocked` report instead of guessing.
28
+
29
+ ## Constraints (hard)
30
+ - **Never `git push`** — only the devops executor may. Integration happens downstream.
31
+ - `Write` is scoped to the security report ONLY — do not edit source, tests, or any other file.
32
+ - Do **not** edit managed (kernel-owned) files without the managed-confirm token.
33
+ - Stay inside the one slice. Review what changed; do not expand scope.
34
+
35
+ ## Output contract
36
+ Your final message IS the return value — return the report object, not a conversational reply.
37
+ Lead with it, drop prose. Your declared output contract equals the security reportSchema (the
38
+ fields `validateReport` requires for type `security`):
39
+
40
+ ```output-contract
41
+ issueId
42
+ status
43
+ artifact
44
+ pushed
45
+ summary
46
+ ```
47
+
48
+ `status` ∈ `completed | blocked`; `artifact` names the security report you wrote; `pushed` is always
49
+ `false` (you never push). Example:
50
+
51
+ ```json
52
+ { "issueId": "flow-03", "status": "completed", "artifact": "security-flow-03.md",
53
+ "pushed": false, "summary": "PASS — no injection/traversal; secrets handled by pointer, fail-closed" }
54
+ ```
55
+
56
+ ## Stateless
57
+ You get only your spawn prompt + this file — no main-thread memory, no inherited persona. Everything
58
+ you need is on the page or in the files your spec names. Keep yourself self-sufficient.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: compass
3
+ description: Router over the skills and the build flow — ask "which skill or flow fits: where am I, what's next." Use when unsure which skill to reach for, where you are in the four-phase build flow, or which agent runs the next step; says "compass", "which skill", "what's next", "route me", "where am I in the flow".
4
+ user-invocable: true
5
+ ---
6
+
7
+ # compass — where am I, which skill next
8
+
9
+ `compass` is the on-demand map of the wrxn skills **and** the build flow. It answers one question:
10
+ *given where I am, which skill or executor comes next?* Two halves: a **static flow doctrine** (below,
11
+ the part that rarely changes) and a **live read** of the installed skills at invoke time (the part that
12
+ must never go stale). Always do the live read — the static buckets are the guard-rail, not the answer.
13
+
14
+ ## The build flow (static doctrine)
15
+
16
+ The default route is the **four-phase flow**, then a single push. Scale the front to novelty.
17
+
18
+ 1. **HITL phase** — front-loaded in the main conversation with the operator. Every human decision is
19
+ made here, in one window, before any agent builds:
20
+ `grill → [research] → [prototype] → PRD → issues → verticality gate`.
21
+ Low-novelty work thins to `grill → PRD → issues`; `research` and `prototype` are optional.
22
+ 2. **AFK phase** — per slice, run unattended by isolated typed executors, accumulating on an
23
+ **integration branch** (slice N+1 builds on slice N):
24
+ `builder → reviewer → security → agent qa-walk`.
25
+ Review and security run **inside the slice loop**, not batched after the build — a slice isn't done
26
+ until it has passed all four gates.
27
+ 3. **Human qa-walk** — the operator walks the **whole assembled artifact against all PRD stories** (the
28
+ cross-slice / does-it-feel-right gate no per-slice agent can see), via `qa-walk`'s operator-mode.
29
+ 4. **Correction pass** — human-walk findings are filed as issues, triaged for severity (fix-now vs
30
+ defer; trivia batched), the fix-now issues run a **scoped re-run of the AFK phase**, then the
31
+ operator re-accepts.
32
+
33
+ **Then, and only then:** `devops` promotes the integration branch to **trunk in one push**. Un-human-walked
34
+ code never reaches trunk.
35
+
36
+ The **HITL / AFK split** is the spine: humans decide up front; agents build and verify unattended.
37
+
38
+ ## Which executor owns each AFK step
39
+
40
+ The AFK phase runs as six native executor agents (`.claude/agents/`), each reading and following its
41
+ phase skill (never a paraphrase), bounded by the dispatch contract (`lib/executor.cjs`):
42
+
43
+ - **builder** *(opus)* — the build step. Reads **tdd**; builds the slice red → green → refactor.
44
+ - **reviewer** *(opus)* — the code-review step. Follows **/code-review** (global skill); writes the one
45
+ review marker the push gate checks.
46
+ - **security** *(opus)* — the security-review step. Follows **/security-review** (global skill).
47
+ - **qa-walker** *(sonnet)* — the per-slice **agent qa-walk**. Reads **qa-walk**; walks that slice's
48
+ issue ACs against the real artifact.
49
+ - **researcher** *(sonnet)* — the optional HITL **research** step. Reads **tech-search**.
50
+ - **devops** *(sonnet)* — the integration / push step. **The only executor authorized to push.**
51
+
52
+ For live per-PRD progress across these gates, run **`wrxn flow status [prd-id]`** — it derives each
53
+ slice's build/review/security/qa state from the durable artifacts (green commit, `review-<id>.md`,
54
+ security report, walk-findings), so it cannot drift.
55
+
56
+ ## Routing rules
57
+
58
+ - **Create a skill** → **write-a-skill** only — `skill-creator` is **legacy** (kept for its init /
59
+ package / quick-validate scripts; retired in a later issue). Never route new skill authoring to it.
60
+ - **Create an agent / subagent** → **write-an-agent**.
61
+ - Anything else → match the request to a bucket below, then to the skill whose `description` fits.
62
+
63
+ ## Live read (do this every invoke — the map can't go stale)
64
+
65
+ Do **not** route from memory or from the static buckets alone. At invoke time:
66
+
67
+ 1. List `.claude/skills/*/` and read each `SKILL.md` frontmatter `name:` + `description:`.
68
+ 2. Bucket each by the flow using the categories below (dev-pipeline / knowledge / setup-health / meta /
69
+ cross-session).
70
+ 3. Surface the skill(s) whose `description` best matches the operator's intent and where they are in the
71
+ flow — including any skill **newer than the static block below**, which is exactly why you read live.
72
+
73
+ ## Buckets (the static map — coverage-guarded)
74
+
75
+ Every installed skill belongs to exactly one flow bucket. This block is machine-checked by
76
+ `lib/compass-coverage.cjs` (`compassCoverage`): if a skill is installed but absent here, coverage fails
77
+ — the prompt to add it (or to lean on the live read). The live read is the runtime backstop; this is the
78
+ build-time guard.
79
+
80
+ ```buckets
81
+ dev-pipeline: grill-me, grill-with-docs, tech-search, prototype, to-prd, to-issues, triage, tdd, qa-walk, diagnose, resolving-merge-conflicts, improve-codebase-architecture
82
+ knowledge: dream, harvest, sync, ingest, memory
83
+ setup-health: onboard, audit, level-up, setup-matt-pocock-skills, synapse
84
+ meta: write-a-skill, write-an-agent, skill-creator, compass
85
+ cross-session: handoff
86
+ ```
87
+
88
+ - **dev-pipeline** — the four-phase build flow and its engineering activities (grill → research →
89
+ prototype → PRD → issues → verticality → tdd → review → security → qa-walk → diagnose / refactor).
90
+ - **knowledge** — the Brain / wiki memory lifecycle: consolidate (dream), curate (harvest), drift (sync),
91
+ distill sources (ingest), the wiki adapter (memory).
92
+ - **setup-health** — install setup, configuration, and health: onboard, audit, level-up, the
93
+ issue-tracker/domain block (setup-matt-pocock-skills), the SYNAPSE engine (synapse).
94
+ - **meta** — authoring the OS's own extensions: skills (write-a-skill), agents (write-an-agent), the
95
+ legacy skill scaffold (skill-creator), and this router (compass).
96
+ - **cross-session** — continuity across sessions: handoff.
@@ -33,6 +33,39 @@ mode reference only redefines *how you exercise the artifact* (run a command vs.
33
33
 
34
34
  ---
35
35
 
36
+ ## Walk modes — agent vs operator
37
+
38
+ Two modes determine **who runs the walk and at what scope**. The spine (§Execution guardrails →
39
+ §Verdict) is identical for both; only the scope and trigger differ.
40
+
41
+ | Mode | Who | Scope | Trigger |
42
+ |------|-----|-------|---------|
43
+ | **Agent walk** | isolated qa-walker executor | per-slice — one slice's **issue ACs** | after builder → reviewer → security, for each AFK slice |
44
+ | **Operator walk** | human operator | whole assembled artifact — **all PRD stories** | after every slice is AFK-verified, on the integration branch |
45
+
46
+ ### Agent walk (per-slice, AC-level)
47
+
48
+ The isolated qa-walker reads the slice's issue ACs, derives a plan from them, executes against the
49
+ artifact at that slice's state, and files deviations as tracker issues. It runs in fresh context —
50
+ never the builder's — and is the last gate of the per-slice AFK phase. The spine above is the
51
+ agent's complete operating procedure.
52
+
53
+ ### Operator mode — whole-artifact, story-level
54
+
55
+ The operator walks the **whole assembled artifact** against **all PRD user stories** — story-level —
56
+ after every slice is AFK-verified. This is the cross-slice integration gate: it checks end-to-end
57
+ flows and the "does it feel right" correctness that no per-slice agent can see.
58
+
59
+ - **Source of promises:** PRD user stories, not individual issue ACs. Each story is one plan item in §2.
60
+ - **Trigger:** all slices AFK-verified and accumulated on the integration branch. The operator invokes
61
+ the skill with the full batch dir (PRD + all issues) plus the artifact entry point.
62
+ - **Findings:** auto-filed as tracker issues in the same batch dir (§4) — same `NN-<slug>.md` format.
63
+ Findings are additive; do not modify the PRD or source issues.
64
+ - **Verdict:** PASS → `devops` promotes the integration branch to trunk. FINDINGS (N) → correction
65
+ pass: triage severity (fix-now vs defer), fix-now issues run a scoped AFK re-run, then re-accept.
66
+
67
+ ---
68
+
36
69
  ## Execution guardrails (NON-NEGOTIABLE)
37
70
 
38
71
  The walk turns markdown into executed shell commands — so the inputs are the attack surface.
@@ -30,7 +30,9 @@ ROUTING_RECALL=deploy,worktree,push,pull request,release,new project,issue
30
30
  # Budget governor — ceiling (in tokens) on the TRIMMABLE sections (everything except the
31
31
  # Constitution, which is always kept). Over-budget sections are dropped lowest-priority-first
32
32
  # with a visible [SYNAPSE-RULES-TRIM] marker. Override with WRXN_RULES_BUDGET.
33
- RULES_BUDGET_TOKENS=600
33
+ # 800 fits the always-on doctrine (GLOBAL ~188 + the four-phase PIPELINE ~382) plus a firing
34
+ # keyword-recall domain (e.g. ROUTING ~153) with margin, so a recall trigger never trims the doctrine.
35
+ RULES_BUDGET_TOKENS=800
34
36
 
35
37
  # Forced-handoff threshold — fraction of the REAL model window consumed at which the engine injects
36
38
  # the NON-BLOCKING [HANDOFF REQUIRED] directive. The window is read from ~/.claude.json ([1m] tag ⇒
@@ -1,6 +1,6 @@
1
- # Domain: pipeline (L1) — the unified-dev build route. Always-on. Managed kernel file.
2
- PIPELINE_RULE_0=The default build route is unified-dev: grill -> research -> prototype -> PRD -> issues -> verticality review -> tdd -> code review -> security review -> QA-walk -> operator accepts.
3
- PIPELINE_RULE_1=The HITL spine (grill, PRD, issues, accept) runs in the main conversation; the build/review/security/QA-walk executors run as isolated subagents.
4
- PIPELINE_RULE_2=Scale the front half to the task — a clear, scoped, low-novelty change thins it (grill -> PRD -> issues -> build); a net-new or unclear-approach change runs the full front half.
5
- PIPELINE_RULE_3=An issue is ready-for-agent only after the verticality-review gate passes (no horizontal, not-demoable, too-coarse, or dependency-error slices).
6
- PIPELINE_RULE_4=Each AFK executor reads and follows the actual skill file for its phase (tdd, qa-walk, triage) — never a paraphrase of the loop.
1
+ # Domain: pipeline (L1) — the four-phase build flow. Always-on. Managed kernel file.
2
+ PIPELINE_RULE_0=The default build route is the four-phase flow: HITL phase (grill [research] [prototype] PRD issues verticality gate) AFK phase, per slice (builder → reviewer → security agent qa-walk, accumulating on an integration branch) → human qa-walk (the whole assembled artifact vs all PRD stories) → correction pass → a single post-accept push to trunk.
3
+ PIPELINE_RULE_1=The HITL phase runs in the main conversation with the operator; the AFK phase runs unattended as isolated typed executors (builder, reviewer, security, qa-walker, researcher, devops) — devops alone may promote the integration branch to trunk.
4
+ PIPELINE_RULE_2=Scale the HITL phase to novelty — a clear, scoped, low-novelty change thins it to grill PRD issues; research and prototype stay optional, run only for net-new or unclear-approach work.
5
+ PIPELINE_RULE_3=An issue is ready-for-agent only after the verticality gate passes (no horizontal, not-demoable, too-coarse, or dependency-error slices); code review and security review then run per slice inside the AFK phase, not batched after the build, so each slice is genuinely done before the next starts.
6
+ PIPELINE_RULE_4=Each AFK executor reads and follows the actual skill file for its phase (tdd, code-review, security-review, qa-walk, triage) — never a paraphrase; the per-slice agent qa-walk verifies that slice's issue ACs while the human qa-walk verifies the whole artifact, and the correction pass files findings as issues, triages severity, and re-runs the AFK phase for fix-now issues before the single trunk push.