@hybridlabor-api/aos 4.7.0 → 4.7.1
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/.agents/agents.md +8 -3
- package/.agents/nodes.json +2 -1
- package/.agents/state.schema.json +24 -0
- package/.agents/vendor-manifest.json +6 -0
- package/.agents/workflows/startcycle-graph.md +2 -2
- package/.claude/agents/architect.md +5 -4
- package/.claude/agents/techlead.md +2 -0
- package/.claude/workflows/startcycle-dispatch.mjs +175 -17
- package/.opencode/agents/architect.md +5 -4
- package/.opencode/agents/techlead.md +2 -0
- package/THIRD_PARTY_NOTICES.md +9 -1
- package/bin/aos-doctor.mjs +366 -0
- package/bin/aos-store.mjs +167 -0
- package/docs/AUDIT_BRIEF_ECC_STORE.md +122 -0
- package/docs/PLAN_AOS_STORE_PHASE1.md +190 -0
- package/installer.js +41 -1
- package/lib/aos-archify-contract.mjs +277 -0
- package/lib/ecc-store-index.json +1 -0
- package/mcp_config.json +4 -0
- package/mcps/mcsc/packages/core/src/adapters/codex.js +160 -37
- package/package.json +6 -2
- package/scripts/build-ecc-store-index.mjs +147 -0
- package/skills/basic/startcycle-graph/SKILL.md +13 -0
- package/skills/global_config/agenttrail/bin/agenttrail.mjs +153 -42
- package/skills/global_config/agenttrail/public/index.html +5 -4
- package/skills/global_config/archify/examples/dataflow-product-analytics.html +15048 -0
- package/skills/global_config/archify/examples/lifecycle-agent-run.html +14983 -0
- package/skills/global_config/archify/examples/sequence-cache-miss-request.html +15063 -0
- package/skills/global_config/archify/examples/web-app-rendered.html +15012 -0
- package/skills/global_config/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
- package/skills/global_config/ask-tim/SKILL.md +10 -0
- package/skills/global_config/mcsc/SKILL.md +60 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +31 -6
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +4 -2
package/.agents/agents.md
CHANGED
|
@@ -21,8 +21,12 @@ next. This file defines *what each agent is*, not *what calls what*.
|
|
|
21
21
|
- **MCP Servers**:
|
|
22
22
|
- `openwiki-skill`
|
|
23
23
|
- `memb_mcp`
|
|
24
|
-
- **Output
|
|
25
|
-
- **Reads**: `state.goal` · **Writes**: `state.artifacts.plan`, `state.phase: plan`
|
|
24
|
+
- **Output Artifacts**: `production_artifacts/00_execution_plan.md`, `production_artifacts/00_architecture.json` (editable Archify specification), `production_artifacts/00_architecture.html` (read-only `archify deliver` artifact)
|
|
25
|
+
- **Reads**: `state.goal` · **Writes**: `state.artifacts.plan`, `state.artifacts.architecture`, `state.phase: plan`
|
|
26
|
+
- The plan uses the agenttrail component convention (`## Name {#id}`, `needs:`, `files:`, tasks `- [ ] ... {#id}`).
|
|
27
|
+
- The Architect authors the architecture as Archify `architecture` JSON to `production_artifacts/00_architecture.json`, runs `aos-archify validate architecture <spec> --quality showcase --json` during repair and `aos-archify deliver architecture <spec> production_artifacts/00_architecture.html --quality showcase --json` once for final acceptance, and records `state.artifacts.architecture` only on a passing showcase receipt (9/9 checks, 0 errors). A failed validate/deliver preserves the previous HTML and escalates at the Architect→TechLead boundary instead of proceeding silently.
|
|
28
|
+
- The relevant plan component links the delivered diagram with a `url: production_artifacts/00_architecture.html` line so the live map opens it from the card.
|
|
29
|
+
- Plan-canvas reviews that HTML too via the existing path as fixed argv `aos-plan-canvas open production_artifacts/00_architecture.html --no-open` with `shell: false` from the repo root (no new port, single open, no shell interpolation). A missing or unavailable canvas never invalidates the verified architecture; the `url:` line and the `aos-trail . --plan production_artifacts/00_execution_plan.md --no-open` map stay authoritative.
|
|
26
30
|
|
|
27
31
|
---
|
|
28
32
|
|
|
@@ -36,7 +40,8 @@ next. This file defines *what each agent is*, not *what calls what*.
|
|
|
36
40
|
- **MCP Servers**:
|
|
37
41
|
- `memb_mcp`
|
|
38
42
|
- **Output Artifact**: capability-map approval recorded in `state.json` (no separate markdown file — this is a gate, not a deliverable)
|
|
39
|
-
- **Reads**: `state.artifacts.plan` · **Writes**: plan-approval decision, `state.phase: build` (or back to `plan`)
|
|
43
|
+
- **Reads**: `state.artifacts.plan`, `state.artifacts.architecture` · **Writes**: plan-approval decision, `state.phase: build` (or back to `plan`)
|
|
44
|
+
- TechLead rejects the plan when the architecture gate fails: `production_artifacts/00_architecture.json` and `production_artifacts/00_architecture.html` are missing, the `url: production_artifacts/00_architecture.html` link is absent from the plan, or the deliver receipt is not a passing showcase receipt (9/9 checks, 0 errors). A failed receipt preserves the previous HTML and sends the run back to Architect.
|
|
40
45
|
|
|
41
46
|
---
|
|
42
47
|
|
package/.agents/nodes.json
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"description": "Paths to the human-readable markdown artifacts nodes produce. state.json is what edges evaluate; these stay the readable payload. Known keys are documented below; additionalProperties stays a typed string-or-null (not fully open) so a registry-driven build domain beyond these can validate without making this object permissive to arbitrary JSON.",
|
|
25
25
|
"properties": {
|
|
26
26
|
"plan": { "type": ["string", "null"] },
|
|
27
|
+
"architecture": { "type": ["string", "null"] },
|
|
27
28
|
"frontend": { "type": ["string", "null"] },
|
|
28
29
|
"backend": { "type": ["string", "null"] },
|
|
29
30
|
"media": { "type": ["string", "null"] },
|
|
@@ -96,6 +97,29 @@
|
|
|
96
97
|
"default": [],
|
|
97
98
|
"description": "Skill names the user required via /startcycle-graph's --skill=<name> flag (repeatable), validated to exist before the run proceeds. Empty when the user didn't ask for one. Build nodes (and Architect) are told to actually apply these, not just have them available; Reviewer checks the resulting artifacts for evidence they were used and flags a contract-misread finding if not. See .agents/graph.md's 'Mandatory Skill Injection' section."
|
|
98
99
|
},
|
|
100
|
+
"pipeline": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"description": "AO scaffold metadata: which pipeline bootstrapped this run, e.g. startcycle-graph."
|
|
103
|
+
},
|
|
104
|
+
"planCanvasRequired": {
|
|
105
|
+
"type": "boolean",
|
|
106
|
+
"description": "AO scaffold metadata: whether the plan-canvas review is required before build."
|
|
107
|
+
},
|
|
108
|
+
"roles": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"description": "AO scaffold metadata: per-role enablement flags.",
|
|
111
|
+
"additionalProperties": { "type": "boolean" }
|
|
112
|
+
},
|
|
113
|
+
"models": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"description": "AO scaffold metadata: per-role model routing labels.",
|
|
116
|
+
"additionalProperties": { "type": "string" }
|
|
117
|
+
},
|
|
118
|
+
"harnesses": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"description": "AO scaffold metadata: per-role harness assignments.",
|
|
121
|
+
"additionalProperties": { "type": "string" }
|
|
122
|
+
},
|
|
99
123
|
"needs_human": {
|
|
100
124
|
"type": "boolean",
|
|
101
125
|
"default": false,
|
|
@@ -45,6 +45,12 @@
|
|
|
45
45
|
"pinned_commit": "739512a8588b28ff3b554e669391c22508602878",
|
|
46
46
|
"purpose": "Defensive audit heuristics and vulnerability checklists (offensive exploits stripped)",
|
|
47
47
|
"target_skill": "bdb-security-audit, security-reviewer"
|
|
48
|
+
},
|
|
49
|
+
"ecc-store": {
|
|
50
|
+
"upstream": "https://github.com/affaan-m/ECC",
|
|
51
|
+
"pinned_commit": "e482e579415fde18357cafce70f177ae19fd7f03",
|
|
52
|
+
"purpose": "Markdown-only fallback store for skills and auxiliary subagents",
|
|
53
|
+
"target": "lib/ecc-store-index.json"
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
}
|
|
@@ -58,8 +58,8 @@ agents calling agents; see `audit-agents.md` F-17 for why that's corrected.
|
|
|
58
58
|
|
|
59
59
|
| Node | Role | Reads | Writes |
|
|
60
60
|
|---|---|---|---|
|
|
61
|
-
| **Architect** | Turns the goal into a system plan | `state.goal` | `state.artifacts.plan` |
|
|
62
|
-
| **TechLead** | Approves/rejects the plan's capability map | `state.artifacts.plan` | plan approval, `state.phase` |
|
|
61
|
+
| **Architect** | Turns the goal into a system plan | `state.goal` | `state.artifacts.plan`, `state.artifacts.architecture` (`production_artifacts/00_architecture.json` + `production_artifacts/00_architecture.html` via `aos-archify deliver`, linked with a `url:` line) |
|
|
62
|
+
| **TechLead** | Approves/rejects the plan's capability map | `state.artifacts.plan` | plan approval, `state.phase` (rejects on a failed architecture gate: missing spec/HTML, missing `url:` link, or no passing showcase receipt) |
|
|
63
63
|
| **Godmode_UI_UX** | Frontend implementation | plan, own findings | `state.artifacts.frontend` |
|
|
64
64
|
| **Godmode_Engineering** | Backend implementation | plan, own findings | `state.artifacts.backend` |
|
|
65
65
|
| **Godmode_Media_EventTech** | Media/show-control implementation (if the goal needs it) | plan, own findings | `state.artifacts.media` |
|
|
@@ -5,12 +5,13 @@ model: opus
|
|
|
5
5
|
---
|
|
6
6
|
Turns the user's goal (or `/bdbrainstorm` / `/grill-me` output) into a system plan. Reads existing architecture before proposing changes. Does not coordinate execution or invoke other agents — that is TechLead's job, decided by the dispatcher, not by Architect.
|
|
7
7
|
|
|
8
|
-
**Primary skills:** bdbrainstorm, planning-with-files, concise-planning
|
|
8
|
+
**Primary skills:** bdbrainstorm, planning-with-files, concise-planning, archify
|
|
9
9
|
|
|
10
10
|
**MCP servers used:** openwiki-skill, memb_mcp
|
|
11
11
|
|
|
12
|
-
**Output artifact(s):** `production_artifacts/00_execution_plan.md`
|
|
12
|
+
**Output artifact(s):** `production_artifacts/00_execution_plan.md`, `production_artifacts/00_architecture.json`, `production_artifacts/00_architecture.html`
|
|
13
13
|
|
|
14
14
|
- The plan uses the agenttrail component convention (`## Name {#id}`, `needs:`, `files:`, tasks `- [ ] ... {#id}`).
|
|
15
|
-
- The Architect
|
|
16
|
-
-
|
|
15
|
+
- The Architect authors the architecture as Archify `architecture` JSON to `production_artifacts/00_architecture.json`, runs `aos-archify validate architecture <spec> --quality showcase --json` during repair and `aos-archify deliver architecture <spec> production_artifacts/00_architecture.html --quality showcase --json` once for final acceptance, and records `state.artifacts.architecture` only on a passing showcase receipt (9/9 checks, 0 errors). A failed validate/deliver preserves the previous HTML and escalates at the Architect→TechLead boundary.
|
|
16
|
+
- The relevant plan component links the delivered diagram with a `url: production_artifacts/00_architecture.html` line so the live map opens it from the card.
|
|
17
|
+
- Plan-canvas reviews that HTML too via the existing path as fixed argv `aos-plan-canvas open production_artifacts/00_architecture.html --no-open` with `shell: false` from the repo root (no new port, single open, no shell interpolation). A missing or unavailable canvas never invalidates the verified architecture; the `url:` line and the `aos-trail . --plan production_artifacts/00_execution_plan.md --no-open` map stay authoritative.
|
|
@@ -10,3 +10,5 @@ Reviews Architect's plan for a capability map (module boundaries, dependency dir
|
|
|
10
10
|
**MCP servers used:** memb_mcp
|
|
11
11
|
|
|
12
12
|
**Output artifact(s):** capability-map approval recorded in `state.json` (no separate markdown file — this is a gate, not a deliverable)
|
|
13
|
+
|
|
14
|
+
- TechLead rejects the plan when the architecture gate fails: `production_artifacts/00_architecture.json` and `production_artifacts/00_architecture.html` are missing, the `url: production_artifacts/00_architecture.html` link is absent from the plan, or the deliver receipt is not a passing showcase receipt (9/9 checks, 0 errors). A failed receipt preserves the previous HTML and sends the run back to Architect.
|
|
@@ -92,6 +92,21 @@ if (!fs && typeof process !== 'undefined') {
|
|
|
92
92
|
} catch {}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
let archifyContractPromise;
|
|
96
|
+
async function loadArchifyContract() {
|
|
97
|
+
if (!archifyContractPromise) {
|
|
98
|
+
archifyContractPromise = (async () => {
|
|
99
|
+
if (typeof process === 'undefined') return null;
|
|
100
|
+
try {
|
|
101
|
+
return await import(new URL('../../lib/aos-archify-contract.mjs', import.meta.url).href);
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
})();
|
|
106
|
+
}
|
|
107
|
+
return archifyContractPromise;
|
|
108
|
+
}
|
|
109
|
+
|
|
95
110
|
function readStdinSync() {
|
|
96
111
|
const chunks = [];
|
|
97
112
|
const buffer = Buffer.alloc(64 * 1024);
|
|
@@ -346,12 +361,54 @@ if (typeof globalThis.agent === 'undefined') {
|
|
|
346
361
|
return { phase: 'escalated' };
|
|
347
362
|
}
|
|
348
363
|
|
|
364
|
+
if (label.startsWith('archify-verify')) {
|
|
365
|
+
const failVerify = (error) => ({ validateOk: false, deliverOk: false, checksPassed: 0, checkCount: 9, error: String(error).slice(0, 400) });
|
|
366
|
+
if (!fs || !path || !child_process) return failVerify('archify verify has no process runtime in this environment');
|
|
367
|
+
const contract = await loadArchifyContract();
|
|
368
|
+
if (!contract || typeof contract.runArchifyBoundary !== 'function') return failVerify('archify contract unavailable');
|
|
369
|
+
const repoRoot = process.cwd();
|
|
370
|
+
const spec = contract.ARCHITECTURE_SPEC_PATH;
|
|
371
|
+
const html = contract.ARCHITECTURE_HTML_PATH;
|
|
372
|
+
const localBin = typeof contract.resolveArchifyBin === 'function' ? contract.resolveArchifyBin(repoRoot) : null;
|
|
373
|
+
const run = (args, options) => child_process.spawnSync(
|
|
374
|
+
localBin ? process.execPath : 'aos-archify',
|
|
375
|
+
[...(localBin ? [localBin] : []), ...args],
|
|
376
|
+
{
|
|
377
|
+
cwd: options.cwd,
|
|
378
|
+
encoding: 'utf8',
|
|
379
|
+
timeout: options.timeoutMs,
|
|
380
|
+
maxBuffer: options.maxBuffer,
|
|
381
|
+
shell: false,
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
try {
|
|
385
|
+
const result = await contract.runArchifyBoundary({
|
|
386
|
+
bin: localBin,
|
|
387
|
+
cwd: repoRoot,
|
|
388
|
+
specPath: spec,
|
|
389
|
+
htmlPath: html,
|
|
390
|
+
run,
|
|
391
|
+
});
|
|
392
|
+
if (!result || result.ok !== true) return failVerify((result && result.error) || 'archify boundary failed');
|
|
393
|
+
return {
|
|
394
|
+
validateOk: result.validate?.status === 0,
|
|
395
|
+
deliverOk: result.deliver?.status === 0,
|
|
396
|
+
checksPassed: result.receipt?.checksPassed ?? 0,
|
|
397
|
+
checkCount: result.receipt?.checkCount ?? contract.ARCHITECTURE_CHECK_COUNT ?? 9,
|
|
398
|
+
error: '',
|
|
399
|
+
};
|
|
400
|
+
} catch (error) {
|
|
401
|
+
return failVerify((error && error.message) || 'archify boundary executor failed');
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
349
405
|
// LLM Agent Steps: runner adapter / graceful execution
|
|
350
406
|
if (child_process) {
|
|
351
407
|
try {
|
|
352
408
|
const agyRes = child_process.spawnSync('agy', ['--print', prompt, '--output-format', 'json', '--print-timeout', '30s'], {
|
|
353
409
|
encoding: 'utf8',
|
|
354
410
|
timeout: 35000,
|
|
411
|
+
shell: false,
|
|
355
412
|
});
|
|
356
413
|
if (agyRes.status === 0 && agyRes.stdout) {
|
|
357
414
|
const jsonMatch = agyRes.stdout.match(/\{[\s\S]*\}/);
|
|
@@ -571,6 +628,38 @@ async function mergeStateD() {
|
|
|
571
628
|
);
|
|
572
629
|
}
|
|
573
630
|
|
|
631
|
+
async function verifyArchifyArtifacts() {
|
|
632
|
+
return await agent(
|
|
633
|
+
'You are the dedicated /startcycle-graph archify-verify step -- a deterministic check, not a reasoning task. ' +
|
|
634
|
+
'Working directory is the repository root. Run exactly these two commands in this order, ' +
|
|
635
|
+
'each as an argument array with no shell and no string interpolation: ' +
|
|
636
|
+
'first ["validate", "architecture", "production_artifacts/00_architecture.json", "--quality", "showcase", "--json"], ' +
|
|
637
|
+
'then ["deliver", "architecture", "production_artifacts/00_architecture.json", "production_artifacts/00_architecture.html", "--quality", "showcase", "--json"], ' +
|
|
638
|
+
'both via the node archify binary at skills/global_config/archify/bin/archify.mjs with a 120 second timeout each. ' +
|
|
639
|
+
'Only run deliver when validate exits 0. Read at most 65536 bytes of each command output. ' +
|
|
640
|
+
'Deliver passes only on a showcase receipt with 9 of 9 checks and 0 errors plus sha256 evidence for specification and artifact. ' +
|
|
641
|
+
'On any non-zero exit, oversized output, or invalid receipt, report failure and preserve the previous HTML artifact untouched -- ' +
|
|
642
|
+
'never invent success and never write state.artifacts.architecture yourself. ' +
|
|
643
|
+
'Keep any logged output bounded to 400 characters with home directories and long hashes redacted.\n\n' +
|
|
644
|
+
'Return only: { "validateOk": boolean, "deliverOk": boolean, "checksPassed": number, "checkCount": number, "error": string }.',
|
|
645
|
+
{
|
|
646
|
+
label: `archify-verify-${iteration}`,
|
|
647
|
+
model: 'haiku',
|
|
648
|
+
schema: {
|
|
649
|
+
type: 'object',
|
|
650
|
+
required: ['validateOk', 'deliverOk', 'checksPassed', 'checkCount', 'error'],
|
|
651
|
+
properties: {
|
|
652
|
+
validateOk: { type: 'boolean' },
|
|
653
|
+
deliverOk: { type: 'boolean' },
|
|
654
|
+
checksPassed: { type: 'number' },
|
|
655
|
+
checkCount: { type: 'number' },
|
|
656
|
+
error: { type: 'string' },
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
}
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
574
663
|
// ---------------------------------------------------------------------
|
|
575
664
|
// Load the node registry. First thing this run does, per comment block
|
|
576
665
|
// item #4 -- everything below is derived from this, nothing is hardcoded.
|
|
@@ -706,20 +795,22 @@ if (mandatorySkillNames.length > 0) {
|
|
|
706
795
|
'this workflow may be driven from a harness whose directory is not ~/.claude. ' +
|
|
707
796
|
'If this project has its own skills/ directory, also accept skills/<name>/SKILL.md or skills/<container>/<name>/SKILL.md. ' +
|
|
708
797
|
'This is a read-only lookup, not a reasoning task -- do not invent a path that does not exist, and never report a close match as `found`.\n\n' +
|
|
709
|
-
'For any name that does NOT resolve,
|
|
798
|
+
'For any name that does NOT resolve, read lib/ecc-store-index.json and list exact available store item names in `store_matches`. ' +
|
|
799
|
+
'Also list up to five installed skills whose directory names are plausible near-misses ' +
|
|
710
800
|
'(substring, obvious typo, or the same words in another order) in `suggestions`. Read the real directory listing to do this -- ' +
|
|
711
801
|
'suggest only names that actually exist on disk. `--skill=` requires an exact directory name, and a user who mistyped one ' +
|
|
712
802
|
'has no way to discover the right spelling from an error that only says "not found".\n\n' +
|
|
713
|
-
'Return only: { "found": string[], "missing": string[], "suggestions": string[] }.',
|
|
803
|
+
'Return only: { "found": string[], "missing": string[], "store_matches": string[], "suggestions": string[] }.',
|
|
714
804
|
{
|
|
715
805
|
label: 'validate-mandatory-skills',
|
|
716
806
|
model: 'haiku',
|
|
717
807
|
schema: {
|
|
718
808
|
type: 'object',
|
|
719
|
-
required: ['found', 'missing'],
|
|
809
|
+
required: ['found', 'missing', 'store_matches'],
|
|
720
810
|
properties: {
|
|
721
811
|
found: { type: 'array', items: { type: 'string' } },
|
|
722
812
|
missing: { type: 'array', items: { type: 'string' } },
|
|
813
|
+
store_matches: { type: 'array', items: { type: 'string' } },
|
|
723
814
|
suggestions: { type: 'array', items: { type: 'string' } },
|
|
724
815
|
},
|
|
725
816
|
},
|
|
@@ -727,15 +818,21 @@ if (mandatorySkillNames.length > 0) {
|
|
|
727
818
|
);
|
|
728
819
|
const missing = skillCheckResult?.missing ?? [];
|
|
729
820
|
if (missing.length > 0) {
|
|
821
|
+
const storeMatches = skillCheckResult?.store_matches ?? [];
|
|
730
822
|
const near = skillCheckResult?.suggestions ?? [];
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
823
|
+
let message = `--skill named skill(s) that could not be found on this machine: ${missing.join(', ')}. `;
|
|
824
|
+
if (storeMatches.length > 0) {
|
|
825
|
+
message += `Found in the AOS / ECC Store: ${storeMatches.join(', ')}. ` +
|
|
826
|
+
`Run: aos store install ${storeMatches.join(' ')} ` +
|
|
827
|
+
'Then re-run your startcycle command. ';
|
|
828
|
+
} else if (near.length > 0) {
|
|
829
|
+
message += `Did you mean: ${near.join(', ')}? `;
|
|
830
|
+
} else {
|
|
831
|
+
message += 'No installed or store skill has a similar name. ';
|
|
832
|
+
}
|
|
833
|
+
message += '--skill= takes the exact skill directory name; run /ask-tim to find the one you want. ' +
|
|
834
|
+
'Refusing to silently proceed without a mandated skill.';
|
|
835
|
+
return await escalate(message);
|
|
739
836
|
}
|
|
740
837
|
mandatorySkills = skillCheckResult?.found ?? mandatorySkillNames;
|
|
741
838
|
}
|
|
@@ -759,9 +856,14 @@ while (!approved) {
|
|
|
759
856
|
: '') +
|
|
760
857
|
`Turn this goal into a system plan with an explicit capability map (module boundaries, ` +
|
|
761
858
|
`dependency direction, build order). Write it to production_artifacts/00_execution_plan.md. ` +
|
|
762
|
-
`
|
|
859
|
+
`Author the architecture as Archify architecture JSON to production_artifacts/00_architecture.json, ` +
|
|
860
|
+
`run aos-archify validate architecture production_artifacts/00_architecture.json --quality showcase --json during repair and ` +
|
|
861
|
+
`aos-archify deliver architecture production_artifacts/00_architecture.json production_artifacts/00_architecture.html --quality showcase --json once for final acceptance, ` +
|
|
862
|
+
`link it from the relevant plan component with a url: production_artifacts/00_architecture.html line, ` +
|
|
863
|
+
`and set state.goal, state.phase = "plan", state.artifacts.plan to the plan path, state.artifacts.architecture to production_artifacts/00_architecture.html only on a passing showcase receipt (9/9 checks, 0 errors), and state.mandatory_skills to ${JSON.stringify(mandatorySkills)}. ` +
|
|
864
|
+
`On a failed validate/deliver preserve the previous HTML and report deliverOk false instead of proceeding silently. ` +
|
|
763
865
|
`Decide whether the goal needs the Media_EventTech build node (TouchDesigner/show-control/3D/media work) -- most goals don't.\n\n` +
|
|
764
|
-
`Return only: { "planPath": string, "needsMedia": boolean }.`,
|
|
866
|
+
`Return only: { "planPath": string, "needsMedia": boolean, "architectureSpec": string, "architectureHtml": string, "deliverOk": boolean }.`,
|
|
765
867
|
{
|
|
766
868
|
label: `architect-${iteration}`,
|
|
767
869
|
agentType: architectNode.agentType,
|
|
@@ -769,22 +871,78 @@ while (!approved) {
|
|
|
769
871
|
schema: {
|
|
770
872
|
type: 'object',
|
|
771
873
|
required: ['planPath', 'needsMedia'],
|
|
772
|
-
properties: {
|
|
874
|
+
properties: {
|
|
875
|
+
planPath: { type: 'string' },
|
|
876
|
+
needsMedia: { type: 'boolean' },
|
|
877
|
+
architectureSpec: { type: 'string' },
|
|
878
|
+
architectureHtml: { type: 'string' },
|
|
879
|
+
deliverOk: { type: 'boolean' },
|
|
880
|
+
},
|
|
773
881
|
},
|
|
774
882
|
}
|
|
775
883
|
);
|
|
776
884
|
|
|
777
885
|
planPath = architectResult?.planPath;
|
|
778
886
|
needsMedia = !!architectResult?.needsMedia;
|
|
887
|
+
const architectureSpec = architectResult?.architectureSpec || 'production_artifacts/00_architecture.json';
|
|
888
|
+
const architectureHtml = architectResult?.architectureHtml || 'production_artifacts/00_architecture.html';
|
|
889
|
+
const deliverOk = architectResult?.deliverOk !== false;
|
|
779
890
|
|
|
780
891
|
if (!planPath) {
|
|
781
892
|
return await escalate('Architect did not return a plan path.');
|
|
782
893
|
}
|
|
894
|
+
if (!deliverOk) {
|
|
895
|
+
iteration++;
|
|
896
|
+
if (iteration >= MAX_ITERATIONS) {
|
|
897
|
+
return await escalate(
|
|
898
|
+
'Archify deliver reported failure at the Architect step; previous HTML preserved.',
|
|
899
|
+
{ planPath }
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
lastRejectionReason = 'Archify deliver/validate failed; previous HTML preserved. Repair the spec and deliver again.';
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
if (architectureSpec !== 'production_artifacts/00_architecture.json' || architectureHtml !== 'production_artifacts/00_architecture.html') {
|
|
906
|
+
iteration++;
|
|
907
|
+
if (iteration >= MAX_ITERATIONS) {
|
|
908
|
+
return await escalate(
|
|
909
|
+
'Archify boundary rejected untrusted artifact paths; previous HTML preserved.',
|
|
910
|
+
{ planPath }
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
lastRejectionReason = 'Archify boundary rejected untrusted artifact paths; previous HTML preserved. Use production_artifacts/00_architecture.json and production_artifacts/00_architecture.html.';
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const boundaryResult = await verifyArchifyArtifacts();
|
|
917
|
+
if (!boundaryResult || boundaryResult.validateOk !== true || boundaryResult.deliverOk !== true) {
|
|
918
|
+
iteration++;
|
|
919
|
+
const boundaryError = typeof boundaryResult?.error === 'string' && boundaryResult.error
|
|
920
|
+
? boundaryResult.error.slice(0, 400)
|
|
921
|
+
: 'archify validate/deliver failed';
|
|
922
|
+
if (iteration >= MAX_ITERATIONS) {
|
|
923
|
+
return await escalate(
|
|
924
|
+
`Archify boundary verification failed; previous HTML preserved: ${boundaryError}`,
|
|
925
|
+
{ planPath }
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
lastRejectionReason = `Archify boundary verification failed; previous HTML preserved: ${boundaryError}. Repair the spec and deliver again.`;
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
try {
|
|
932
|
+
if (fs && fs.existsSync && fs.existsSync(architectureHtml) && child_process) {
|
|
933
|
+
const canvas = child_process.spawn('aos-plan-canvas', ['open', architectureHtml, '--no-open'], { cwd: process.cwd(), timeout: 15000, stdio: 'ignore', shell: false, detached: true });
|
|
934
|
+
if (canvas && typeof canvas.on === 'function') canvas.on('error', () => {});
|
|
935
|
+
if (canvas && typeof canvas.unref === 'function') canvas.unref();
|
|
936
|
+
}
|
|
937
|
+
} catch {}
|
|
783
938
|
|
|
784
939
|
const techLeadResult = await agent(
|
|
785
940
|
`You are acting as the ${techleadNode.label} agent (${techleadNode.personaFile}). ${dispatchNote(techleadNode)}${skillsNote(techleadNode)}\n\n` +
|
|
786
941
|
`Read the plan at ${planPath}. Approve it only if it has an explicit capability map: ` +
|
|
787
942
|
`module boundaries, dependency direction, and build order are all stated, not implicit. ` +
|
|
943
|
+
`Apply the architecture gate: reject unless ${architectureSpec} and ${architectureHtml} both exist, ` +
|
|
944
|
+
`the plan links the diagram with a url: ${architectureHtml} line, ` +
|
|
945
|
+
`and the deliver receipt is a passing showcase receipt (9/9 checks, 0 errors, failure preserves the previous HTML). ` +
|
|
788
946
|
(mandatorySkills.length > 0
|
|
789
947
|
? `The user also required this run to use the following skill(s) via /startcycle-graph's --skill flag: ${mandatorySkills.join(', ')}. ` +
|
|
790
948
|
`Reject the plan if it does not actually account for them — catching that here costs one planning round, ` +
|
|
@@ -843,7 +1001,7 @@ const NODE_NAMES = humanList(NODE_ENUM);
|
|
|
843
1001
|
// aos-trail exits on its own when a map for this repo is already running.
|
|
844
1002
|
try {
|
|
845
1003
|
child_process?.spawn('aos-trail', [process.cwd(), '--plan', 'production_artifacts/00_execution_plan.md', '--no-open'],
|
|
846
|
-
{ detached: true, stdio: 'ignore', shell:
|
|
1004
|
+
{ detached: true, stdio: 'ignore', shell: false }).on('error', () => {}).unref();
|
|
847
1005
|
} catch { /* no child_process in this runtime: run without the map */ }
|
|
848
1006
|
|
|
849
1007
|
let findings = [];
|
|
@@ -1011,7 +1169,7 @@ while (!reviewedClean) {
|
|
|
1011
1169
|
// state.d + merge treatment as the build/review loop above.
|
|
1012
1170
|
// ---------------------------------------------------------------------
|
|
1013
1171
|
|
|
1014
|
-
const GATE_KEYS = ['lint', 'typecheck', 'tests', 'a11y', 'seo'];
|
|
1172
|
+
const GATE_KEYS = ['lint', 'typecheck', 'tests', 'a11y', 'seo', 'security'];
|
|
1015
1173
|
const GATE_VALUE_ENUM = ['pass', 'fail', 'skip'];
|
|
1016
1174
|
let allGatesPass = false;
|
|
1017
1175
|
let lastGate = null;
|
|
@@ -1020,7 +1178,7 @@ while (!allGatesPass) {
|
|
|
1020
1178
|
const shipResult = await agent(
|
|
1021
1179
|
`You are acting as the ${shippingNode.label} agent (${shippingNode.personaFile}). ${dispatchNote(shippingNode)}${skillsNote(shippingNode)}\n\n` +
|
|
1022
1180
|
`Run the automated quality gate against the artifacts from the plan at ${planPath}: lint, typecheck, ` +
|
|
1023
|
-
`tests, a11y, seo. Use the repository's own commands (npm test / pytest / tsc --noEmit / etc -- detect ` +
|
|
1181
|
+
`tests, a11y, seo, security. Use the repository's own commands (npm test / pytest / tsc --noEmit / etc -- detect ` +
|
|
1024
1182
|
`which apply; use "skip" only for a check that genuinely doesn't apply to this repo, not for one you didn't run). ` +
|
|
1025
1183
|
`Write production_artifacts/04_release_report.md and update state.gate. ` +
|
|
1026
1184
|
`If every gate check is 'pass' or 'skip', you must also set state.phase = "ready_to_ship" in state.json.\n\n` +
|
|
@@ -5,12 +5,13 @@ model: opus
|
|
|
5
5
|
---
|
|
6
6
|
Turns the user's goal (or `/bdbrainstorm` / `/grill-me` output) into a system plan. Reads existing architecture before proposing changes. Does not coordinate execution or invoke other agents — that is TechLead's job, decided by the dispatcher, not by Architect.
|
|
7
7
|
|
|
8
|
-
**Primary skills:** bdbrainstorm, planning-with-files, concise-planning
|
|
8
|
+
**Primary skills:** bdbrainstorm, planning-with-files, concise-planning, archify
|
|
9
9
|
|
|
10
10
|
**MCP servers used:** openwiki-skill, memb_mcp
|
|
11
11
|
|
|
12
|
-
**Output artifact(s):** `production_artifacts/00_execution_plan.md`
|
|
12
|
+
**Output artifact(s):** `production_artifacts/00_execution_plan.md`, `production_artifacts/00_architecture.json`, `production_artifacts/00_architecture.html`
|
|
13
13
|
|
|
14
14
|
- The plan uses the agenttrail component convention (`## Name {#id}`, `needs:`, `files:`, tasks `- [ ] ... {#id}`).
|
|
15
|
-
- The Architect
|
|
16
|
-
-
|
|
15
|
+
- The Architect authors the architecture as Archify `architecture` JSON to `production_artifacts/00_architecture.json`, runs `aos-archify validate architecture <spec> --quality showcase --json` during repair and `aos-archify deliver architecture <spec> production_artifacts/00_architecture.html --quality showcase --json` once for final acceptance, and records `state.artifacts.architecture` only on a passing showcase receipt (9/9 checks, 0 errors). A failed validate/deliver preserves the previous HTML and escalates at the Architect→TechLead boundary.
|
|
16
|
+
- The relevant plan component links the delivered diagram with a `url: production_artifacts/00_architecture.html` line so the live map opens it from the card.
|
|
17
|
+
- Plan-canvas reviews that HTML too via the existing path as fixed argv `aos-plan-canvas open production_artifacts/00_architecture.html --no-open` with `shell: false` from the repo root (no new port, single open, no shell interpolation). A missing or unavailable canvas never invalidates the verified architecture; the `url:` line and the `aos-trail . --plan production_artifacts/00_execution_plan.md --no-open` map stay authoritative.
|
|
@@ -10,3 +10,5 @@ Reviews Architect's plan for a capability map (module boundaries, dependency dir
|
|
|
10
10
|
**MCP servers used:** memb_mcp
|
|
11
11
|
|
|
12
12
|
**Output artifact(s):** capability-map approval recorded in `state.json` (no separate markdown file — this is a gate, not a deliverable)
|
|
13
|
+
|
|
14
|
+
- TechLead rejects the plan when the architecture gate fails: `production_artifacts/00_architecture.json` and `production_artifacts/00_architecture.html` are missing, the `url: production_artifacts/00_architecture.html` link is absent from the plan, or the deliver receipt is not a passing showcase receipt (9/9 checks, 0 errors). A failed receipt preserves the previous HTML and sends the run back to Architect.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -99,7 +99,15 @@ browser-internal identifiers private to the served page
|
|
|
99
99
|
No ECC tests, hooks (`scripts/hooks/plan-canvas-*.js`), or the
|
|
100
100
|
`commands/plan-canvas.md` wrapper were ported.
|
|
101
101
|
|
|
102
|
-
###
|
|
102
|
+
### 3. Store index
|
|
103
|
+
|
|
104
|
+
The AOS Store exposes selected ECC Markdown capabilities through
|
|
105
|
+
`lib/ecc-store-index.json` at pinned commit
|
|
106
|
+
`e482e579415fde18357cafce70f177ae19fd7f03`. The index contains only
|
|
107
|
+
`skills/**/SKILL.md` and `agents/*.md` metadata. Installation verifies the raw
|
|
108
|
+
Markdown SHA-256 before writing it. Scripts, hooks, rules, and non-entrypoint
|
|
109
|
+
Markdown files are excluded from the Phase 1 store.
|
|
110
|
+
|
|
103
111
|
|
|
104
112
|
```
|
|
105
113
|
MIT License
|