@peterxiaoyang/superspec 0.1.4 → 0.1.6
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/adapters/codex/agents/architect.toml +4 -148
- package/adapters/codex/agents/code-reviewer.toml +4 -166
- package/adapters/codex/agents/critic.toml +5 -106
- package/adapters/codex/agents/executor.toml +13 -0
- package/adapters/codex/agents/test-engineer.toml +4 -154
- package/adapters/codex/agents/test-runner.toml +13 -0
- package/adapters/codex/agents/verifier.toml +4 -110
- package/adapters/codex/install-map.json +20 -0
- package/dist/src/apply_worker_chain.d.ts +57 -0
- package/dist/src/apply_worker_chain.js +1188 -0
- package/dist/src/cli.js +13 -0
- package/dist/src/cli_args.d.ts +13 -1
- package/dist/src/cli_args.js +237 -12
- package/dist/src/core.d.ts +1 -0
- package/dist/src/core.js +1 -0
- package/dist/src/evidence.js +152 -0
- package/dist/src/gates.d.ts +2 -1
- package/dist/src/gates.js +275 -21
- package/dist/src/i18n.js +4 -3
- package/dist/src/install_engine.d.ts +17 -0
- package/dist/src/install_engine.js +125 -2
- package/dist/src/packet_measure.d.ts +43 -0
- package/dist/src/packet_measure.js +417 -0
- package/dist/src/packet_render.d.ts +4 -0
- package/dist/src/packet_render.js +1623 -0
- package/dist/src/packet_schema.d.ts +56 -0
- package/dist/src/packet_schema.js +1 -0
- package/dist/src/project_init.js +7 -49
- package/dist/src/tasks.d.ts +10 -0
- package/dist/src/tasks.js +86 -0
- package/dist/src/util.d.ts +11 -3
- package/dist/src/util.js +27 -6
- package/package.json +2 -2
- package/schemas/install-manifest.schema.json +17 -0
- package/templates/workflow/prompts/architect.md +16 -109
- package/templates/workflow/prompts/code-reviewer.md +20 -134
- package/templates/workflow/prompts/critic.md +18 -75
- package/templates/workflow/prompts/executor.md +32 -0
- package/templates/workflow/prompts/test-engineer.md +16 -126
- package/templates/workflow/prompts/test-runner.md +33 -0
- package/templates/workflow/prompts/verifier.md +20 -77
- package/templates/workflow/skills/superspec-apply/SKILL.md +102 -78
- package/templates/workflow/skills/superspec-archive/SKILL.md +41 -37
- package/templates/workflow/skills/superspec-explore/SKILL.md +63 -77
- package/templates/workflow/skills/superspec-propose/SKILL.md +64 -85
- package/templates/workflow/skills/superspec-review/SKILL.md +76 -233
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { dispatch_packet } from "./packet_render.js";
|
|
5
|
+
import { GuardError, REQUIRED_SUPERSPEC_AGENT_ROLES, REQUIRED_SUPERSPEC_WORKFLOW_SKILLS, runtime, } from "./util.js";
|
|
6
|
+
import { file_blob_sha } from "./git.js";
|
|
7
|
+
const REPRESENTATIVE_SCENARIOS = [
|
|
8
|
+
{
|
|
9
|
+
name: "explore_complete",
|
|
10
|
+
description: "Post-bridge runtime surface for discovery authoring plus proposal-entry critic review.",
|
|
11
|
+
files: [
|
|
12
|
+
".codex/skills/superspec-explore/SKILL.md",
|
|
13
|
+
".codex/prompts/critic.md",
|
|
14
|
+
".codex/agents/critic.toml",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "proposal_reviewed",
|
|
19
|
+
description: "Post-bridge runtime surface for proposal authoring and proposal critic review.",
|
|
20
|
+
files: [
|
|
21
|
+
".codex/skills/superspec-propose/SKILL.md",
|
|
22
|
+
".codex/prompts/critic.md",
|
|
23
|
+
".codex/agents/critic.toml",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "design_complete",
|
|
28
|
+
description: "Post-bridge runtime surface for design authoring and the architect/critic/test-engineer review bundle.",
|
|
29
|
+
files: [
|
|
30
|
+
".codex/skills/superspec-propose/SKILL.md",
|
|
31
|
+
".codex/prompts/architect.md",
|
|
32
|
+
".codex/prompts/critic.md",
|
|
33
|
+
".codex/prompts/test-engineer.md",
|
|
34
|
+
".codex/agents/architect.toml",
|
|
35
|
+
".codex/agents/critic.toml",
|
|
36
|
+
".codex/agents/test-engineer.toml",
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "test_contract_drafted",
|
|
41
|
+
description: "Post-bridge runtime surface for test-contract authoring and its review lanes.",
|
|
42
|
+
files: [
|
|
43
|
+
".codex/skills/superspec-propose/SKILL.md",
|
|
44
|
+
".codex/prompts/critic.md",
|
|
45
|
+
".codex/prompts/test-engineer.md",
|
|
46
|
+
".codex/agents/critic.toml",
|
|
47
|
+
".codex/agents/test-engineer.toml",
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "apply_ready",
|
|
52
|
+
description: "Post-bridge runtime surface for apply orchestration and bounded executor handoff.",
|
|
53
|
+
files: [
|
|
54
|
+
".codex/skills/superspec-apply/SKILL.md",
|
|
55
|
+
".codex/prompts/executor.md",
|
|
56
|
+
".codex/agents/executor.toml",
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "review_complete_allow",
|
|
61
|
+
description: "Post-bridge runtime surface for merged review + final verification on the allow path.",
|
|
62
|
+
files: [
|
|
63
|
+
".codex/skills/superspec-review/SKILL.md",
|
|
64
|
+
".codex/prompts/code-reviewer.md",
|
|
65
|
+
".codex/prompts/architect.md",
|
|
66
|
+
".codex/prompts/critic.md",
|
|
67
|
+
".codex/prompts/verifier.md",
|
|
68
|
+
".codex/agents/code-reviewer.toml",
|
|
69
|
+
".codex/agents/architect.toml",
|
|
70
|
+
".codex/agents/critic.toml",
|
|
71
|
+
".codex/agents/verifier.toml",
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "archive_ready",
|
|
76
|
+
description: "Post-bridge runtime surface for archive handoff after review passes.",
|
|
77
|
+
files: [
|
|
78
|
+
".codex/skills/superspec-archive/SKILL.md",
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "round2_reviewer_prompt",
|
|
83
|
+
description: "Post-bridge runtime surface for a round>1 reviewer lane.",
|
|
84
|
+
files: [
|
|
85
|
+
".codex/prompts/critic.md",
|
|
86
|
+
".codex/agents/critic.toml",
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "request_changes_reopen_tasks",
|
|
91
|
+
description: "Post-bridge runtime surface for a review round that routes back to apply via reopen_tasks.",
|
|
92
|
+
files: [
|
|
93
|
+
".codex/skills/superspec-review/SKILL.md",
|
|
94
|
+
".codex/prompts/code-reviewer.md",
|
|
95
|
+
".codex/prompts/architect.md",
|
|
96
|
+
".codex/prompts/critic.md",
|
|
97
|
+
".codex/agents/code-reviewer.toml",
|
|
98
|
+
".codex/agents/architect.toml",
|
|
99
|
+
".codex/agents/critic.toml",
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "task_reopen_to_resolved",
|
|
104
|
+
description: "Post-bridge runtime surface for reopened apply work from revert through successor executor completion.",
|
|
105
|
+
files: [
|
|
106
|
+
".codex/skills/superspec-apply/SKILL.md",
|
|
107
|
+
".codex/prompts/executor.md",
|
|
108
|
+
".codex/agents/executor.toml",
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "scope_expansion",
|
|
113
|
+
description: "Post-bridge runtime surface for apply-side user confirmation when task scope expands.",
|
|
114
|
+
files: [
|
|
115
|
+
".codex/skills/superspec-apply/SKILL.md",
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
const MATERIALIZED_WORKFLOW_PACKET_SAMPLES = [
|
|
120
|
+
{
|
|
121
|
+
name: "apply_ready_blocked",
|
|
122
|
+
description: "workflow-packet agent output for apply_ready before all required evidence is present.",
|
|
123
|
+
args: { command: "workflow-packet", change: "demo-change", gate: "apply_ready", packet_format: "agent" },
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "task_complete_blocked",
|
|
127
|
+
description: "workflow-packet agent output for a task-scoped apply completion packet.",
|
|
128
|
+
args: { command: "workflow-packet", change: "demo-change", gate: "task_complete", task_id: "TASK-001", packet_format: "agent" },
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
const MATERIALIZED_REVIEW_PACKET_SAMPLES = [
|
|
132
|
+
{
|
|
133
|
+
name: "proposal_reviewed_critic",
|
|
134
|
+
description: "review-packet agent output for a disclosure reviewer lane.",
|
|
135
|
+
args: { command: "review-packet", change: "demo-change", gate: "proposal_reviewed", role: "critic", round: 1, packet_format: "agent" },
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "review_complete_verifier",
|
|
139
|
+
description: "review-packet agent output for the final verification lane.",
|
|
140
|
+
args: { command: "review-packet", change: "demo-change", gate: "review_complete", role: "verifier", round: 1, packet_format: "agent" },
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
const MATERIALIZED_REVIEW_PROMPT_SAMPLES = [
|
|
144
|
+
{
|
|
145
|
+
name: "proposal_reviewed_round2_critic",
|
|
146
|
+
description: "review-packet prompt output for a round>1 disclosure reviewer lane with ledger injection.",
|
|
147
|
+
args: { command: "review-packet", change: "demo-change", gate: "proposal_reviewed", role: "critic", round: 2, packet_format: "prompt" },
|
|
148
|
+
requiredMarkers: ["[SUPERSPEC-FINDING-LEDGER gate=proposal_reviewed findings=1]", "PROP-SCOPE-001", "proposal silently widens scope beyond discovery"],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "review_complete_critic_verification",
|
|
152
|
+
description: "review-packet prompt output for the critic verification_review lane.",
|
|
153
|
+
args: { command: "review-packet", change: "demo-change", gate: "review_complete", role: "critic", round: 1, evidence_kind: "verification_review", packet_format: "prompt" },
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
const LEDGER_BLOCK_SAMPLES = [
|
|
157
|
+
{
|
|
158
|
+
name: "proposal_reviewed_round2_ledger",
|
|
159
|
+
description: "ledger-render output used by round>1 reviewer prompts.",
|
|
160
|
+
args: { command: "ledger-render", change: "demo-change", gate: "proposal_reviewed", round: 2 },
|
|
161
|
+
requiredMarkers: ["[SUPERSPEC-FINDING-LEDGER gate=proposal_reviewed findings=1]", "PROP-SCOPE-001", "proposal silently widens scope beyond discovery"],
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
function ensureReadableTextFile(repoRoot, relPath) {
|
|
165
|
+
const absPath = join(repoRoot, relPath);
|
|
166
|
+
if (existsSync(absPath) && statSync(absPath).isFile()) {
|
|
167
|
+
return readFileSync(absPath, "utf8");
|
|
168
|
+
}
|
|
169
|
+
const skillMatch = /^\.codex\/skills\/([^/]+)\/SKILL\.md$/u.exec(relPath);
|
|
170
|
+
if (skillMatch) {
|
|
171
|
+
const fallback = join(repoRoot, "templates", "workflow", "skills", skillMatch[1], "SKILL.md");
|
|
172
|
+
if (existsSync(fallback) && statSync(fallback).isFile())
|
|
173
|
+
return readFileSync(fallback, "utf8");
|
|
174
|
+
}
|
|
175
|
+
const promptMatch = /^\.codex\/prompts\/([^/]+)\.md$/u.exec(relPath);
|
|
176
|
+
if (promptMatch) {
|
|
177
|
+
const fallback = join(repoRoot, "templates", "workflow", "prompts", `${promptMatch[1]}.md`);
|
|
178
|
+
if (existsSync(fallback) && statSync(fallback).isFile())
|
|
179
|
+
return readFileSync(fallback, "utf8");
|
|
180
|
+
}
|
|
181
|
+
const agentMatch = /^\.codex\/agents\/([^/]+)\.toml$/u.exec(relPath);
|
|
182
|
+
if (agentMatch) {
|
|
183
|
+
const fallback = join(repoRoot, "adapters", "codex", "agents", `${agentMatch[1]}.toml`);
|
|
184
|
+
if (existsSync(fallback) && statSync(fallback).isFile())
|
|
185
|
+
return readFileSync(fallback, "utf8");
|
|
186
|
+
}
|
|
187
|
+
throw new GuardError(`packet_measure_missing_file: ${relPath}`);
|
|
188
|
+
}
|
|
189
|
+
function dedupePaths(paths) {
|
|
190
|
+
return [...new Set(paths)].sort();
|
|
191
|
+
}
|
|
192
|
+
function measuredFiles(repoRoot, relPaths) {
|
|
193
|
+
return dedupePaths(relPaths).map((relPath) => ({
|
|
194
|
+
path: relPath,
|
|
195
|
+
chars: ensureReadableTextFile(repoRoot, relPath).length,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
function measureSurface(repoRoot, relPaths) {
|
|
199
|
+
const files = measuredFiles(repoRoot, relPaths);
|
|
200
|
+
return {
|
|
201
|
+
total_chars: files.reduce((sum, item) => sum + item.chars, 0),
|
|
202
|
+
files,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function writeSyntheticText(repoRoot, relPath, text) {
|
|
206
|
+
const absPath = join(repoRoot, relPath);
|
|
207
|
+
mkdirSync(dirname(absPath), { recursive: true });
|
|
208
|
+
writeFileSync(absPath, text, "utf8");
|
|
209
|
+
}
|
|
210
|
+
function syntheticRef(root, relPath) {
|
|
211
|
+
return {
|
|
212
|
+
path: relPath,
|
|
213
|
+
blob_sha: file_blob_sha(join(root, relPath)),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function syntheticStatus(repoRoot, changeRoot) {
|
|
217
|
+
return {
|
|
218
|
+
changeRoot,
|
|
219
|
+
planningHome: { root: repoRoot },
|
|
220
|
+
schemaName: "spec-driven",
|
|
221
|
+
applyRequires: ["tasks"],
|
|
222
|
+
artifacts: ["proposal", "specs", "design", "tasks"].map((id) => ({ id, status: "done", missingDeps: [] })),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function materializeSyntheticEvidence(changeRoot, relPath, evidence) {
|
|
226
|
+
const absPath = join(changeRoot, relPath);
|
|
227
|
+
mkdirSync(dirname(absPath), { recursive: true });
|
|
228
|
+
writeFileSync(absPath, `${JSON.stringify(evidence, null, 2)}\n`, "utf8");
|
|
229
|
+
return { ...evidence, _path: relPath };
|
|
230
|
+
}
|
|
231
|
+
function syntheticDisclosureEvidences(changeRoot) {
|
|
232
|
+
const promptRef = ".superspec/reports/proposal-r1-critic-prompt.md";
|
|
233
|
+
const outputRef = ".superspec/reports/proposal-r1-critic.md";
|
|
234
|
+
mkdirSync(dirname(join(changeRoot, promptRef)), { recursive: true });
|
|
235
|
+
writeFileSync(join(changeRoot, promptRef), "critic prompt for proposal round 1\n", "utf8");
|
|
236
|
+
writeFileSync(join(changeRoot, outputRef), "critic found a scope issue\n", "utf8");
|
|
237
|
+
const finding = {
|
|
238
|
+
finding_id: "PROP-SCOPE-001",
|
|
239
|
+
finding_uid: "proposal_reviewed:EV-proposal-r1-critic:PROP-SCOPE-001",
|
|
240
|
+
finding_type: "blocker",
|
|
241
|
+
category: "scope",
|
|
242
|
+
material_categories: ["scope"],
|
|
243
|
+
decision_scope_key: "demo-change:proposal:hidden-scope",
|
|
244
|
+
summary: "proposal silently widens scope beyond discovery",
|
|
245
|
+
};
|
|
246
|
+
const targetRefs = [
|
|
247
|
+
syntheticRef(changeRoot, "proposal.md"),
|
|
248
|
+
syntheticRef(changeRoot, ".superspec/artifacts/discovery.md"),
|
|
249
|
+
];
|
|
250
|
+
const review = materializeSyntheticEvidence(changeRoot, ".superspec/evidence/reviews/EV-proposal-r1-critic.json", {
|
|
251
|
+
schema_version: 1,
|
|
252
|
+
evidence_id: "EV-proposal-r1-critic",
|
|
253
|
+
change_id: "demo-change",
|
|
254
|
+
gate: "proposal_reviewed",
|
|
255
|
+
kind: "review",
|
|
256
|
+
created_at: "2026-06-08T00:00:00Z",
|
|
257
|
+
created_by: "measure",
|
|
258
|
+
status: "pass",
|
|
259
|
+
agent_role: "critic",
|
|
260
|
+
execution_mode: "native_subagent",
|
|
261
|
+
agent_id: "agent-critic",
|
|
262
|
+
prompt_ref: promptRef,
|
|
263
|
+
output_ref: outputRef,
|
|
264
|
+
source_anchors: [],
|
|
265
|
+
target_refs: targetRefs,
|
|
266
|
+
review_round_id: "proposal_reviewed-r1",
|
|
267
|
+
findings: [finding],
|
|
268
|
+
});
|
|
269
|
+
const digest = materializeSyntheticEvidence(changeRoot, ".superspec/evidence/reviews/EV-proposal-r1-digest.json", {
|
|
270
|
+
schema_version: 1,
|
|
271
|
+
evidence_id: "EV-proposal-r1-digest",
|
|
272
|
+
change_id: "demo-change",
|
|
273
|
+
gate: "proposal_reviewed",
|
|
274
|
+
kind: "main_review_digest",
|
|
275
|
+
created_at: "2026-06-08T00:01:00Z",
|
|
276
|
+
created_by: "main-thread",
|
|
277
|
+
status: "blocked",
|
|
278
|
+
review_round_id: "proposal_reviewed-r1",
|
|
279
|
+
target_refs: targetRefs,
|
|
280
|
+
source_review_evidence_refs: ["EV-proposal-r1-critic"],
|
|
281
|
+
previous_digest_refs: [],
|
|
282
|
+
finding_dispositions: [{
|
|
283
|
+
...finding,
|
|
284
|
+
origin_review_evidence_id: "EV-proposal-r1-critic",
|
|
285
|
+
disposition: "needs_user_decision",
|
|
286
|
+
rationale: "material scope finding requires user confirmation",
|
|
287
|
+
route: "stay_same_gate_user_decision",
|
|
288
|
+
route_reason: "material scope finding requires user confirmation",
|
|
289
|
+
}],
|
|
290
|
+
});
|
|
291
|
+
return [review, digest];
|
|
292
|
+
}
|
|
293
|
+
function createMaterializedMeasureContext() {
|
|
294
|
+
const repoRoot = mkdtempSync(join(tmpdir(), "superspec-packet-measure-"));
|
|
295
|
+
const changeRoot = join(repoRoot, "openspec", "changes", "demo-change");
|
|
296
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/.superspec/artifacts/discovery.md", "discovery facts\n");
|
|
297
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/.superspec/artifacts/business-invariants.md", "## Business Invariants\n\n| id | description |\n| --- | --- |\n| INV-001 | Preserve behavior |\n");
|
|
298
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/.superspec/artifacts/test-contract.md", "## Test Contract\n\n| test_id | invariant_refs |\n| --- | --- |\n| TEST-001 | INV-001 |\n");
|
|
299
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/proposal.md", "proposal\n");
|
|
300
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/design.md", "design\n");
|
|
301
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/specs/demo/spec.md", "#### Scenario: Demo\n");
|
|
302
|
+
writeSyntheticText(repoRoot, "openspec/changes/demo-change/tasks.md", "- [ ] TASK-001 Implement\n - invariant_refs: INV-001\n - test_refs: TEST-001\n");
|
|
303
|
+
const evidences = syntheticDisclosureEvidences(changeRoot);
|
|
304
|
+
return {
|
|
305
|
+
repoRoot,
|
|
306
|
+
changeRoot,
|
|
307
|
+
status: syntheticStatus(repoRoot, changeRoot),
|
|
308
|
+
evidences,
|
|
309
|
+
cleanup: () => rmSync(repoRoot, { recursive: true, force: true }),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function withMaterializedMeasureRuntime(ctx, fn) {
|
|
313
|
+
const overrides = {
|
|
314
|
+
load_context: () => [ctx.status, ctx.repoRoot, ctx.changeRoot, ctx.evidences],
|
|
315
|
+
dirty_worktree_paths: () => [],
|
|
316
|
+
file_blob_sha,
|
|
317
|
+
};
|
|
318
|
+
const previous = new Map();
|
|
319
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
320
|
+
previous.set(key, { had: Object.prototype.hasOwnProperty.call(runtime, key), value: runtime[key] });
|
|
321
|
+
runtime[key] = value;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
return fn();
|
|
325
|
+
}
|
|
326
|
+
finally {
|
|
327
|
+
for (const [key, item] of previous) {
|
|
328
|
+
if (item.had)
|
|
329
|
+
runtime[key] = item.value;
|
|
330
|
+
else
|
|
331
|
+
delete runtime[key];
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function packetOutputText(args) {
|
|
336
|
+
const result = dispatch_packet(args);
|
|
337
|
+
if (result.output_format === "prompt") {
|
|
338
|
+
const text = String(result.payload);
|
|
339
|
+
return text.endsWith("\n") ? text : `${text}\n`;
|
|
340
|
+
}
|
|
341
|
+
return `${JSON.stringify(result.payload, null, 2)}\n`;
|
|
342
|
+
}
|
|
343
|
+
function measureMaterializedSamples(specs) {
|
|
344
|
+
const ctx = createMaterializedMeasureContext();
|
|
345
|
+
try {
|
|
346
|
+
const samples = withMaterializedMeasureRuntime(ctx, () => specs.map((spec) => {
|
|
347
|
+
const text = packetOutputText(spec.args);
|
|
348
|
+
const missingMarkers = (spec.requiredMarkers ?? []).filter((marker) => !text.includes(marker));
|
|
349
|
+
if (missingMarkers.length > 0) {
|
|
350
|
+
throw new GuardError(`packet_measure_missing_marker: ${spec.name}: ${missingMarkers.join(", ")}`);
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
name: spec.name,
|
|
354
|
+
description: spec.description,
|
|
355
|
+
chars: text.length,
|
|
356
|
+
...(spec.requiredMarkers && spec.requiredMarkers.length > 0 ? { matched_markers: [...spec.requiredMarkers] } : {}),
|
|
357
|
+
};
|
|
358
|
+
}));
|
|
359
|
+
return {
|
|
360
|
+
total_chars: samples.reduce((sum, item) => sum + item.chars, 0),
|
|
361
|
+
samples,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
finally {
|
|
365
|
+
ctx.cleanup();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function templateWorkflowSkillPaths() {
|
|
369
|
+
return REQUIRED_SUPERSPEC_WORKFLOW_SKILLS.map((name) => `templates/workflow/skills/${name}/SKILL.md`);
|
|
370
|
+
}
|
|
371
|
+
function templatePromptPaths() {
|
|
372
|
+
return REQUIRED_SUPERSPEC_AGENT_ROLES.map((name) => `templates/workflow/prompts/${name}.md`);
|
|
373
|
+
}
|
|
374
|
+
function adapterAgentPaths() {
|
|
375
|
+
return REQUIRED_SUPERSPEC_AGENT_ROLES.map((name) => `adapters/codex/agents/${name}.toml`);
|
|
376
|
+
}
|
|
377
|
+
function repoLocalSkillPaths(repoRoot) {
|
|
378
|
+
return REQUIRED_SUPERSPEC_WORKFLOW_SKILLS
|
|
379
|
+
.map((name) => join(".codex", "skills", name, "SKILL.md"))
|
|
380
|
+
.filter((relPath) => existsSync(join(repoRoot, relPath)));
|
|
381
|
+
}
|
|
382
|
+
function runtimeBridgeSkillPaths() {
|
|
383
|
+
return [];
|
|
384
|
+
}
|
|
385
|
+
export function representative_scenarios() {
|
|
386
|
+
return REPRESENTATIVE_SCENARIOS;
|
|
387
|
+
}
|
|
388
|
+
export function measure_packet_surface_report(repoRoot) {
|
|
389
|
+
const fixedSurfaceInstallUpperBound = measureSurface(repoRoot, [
|
|
390
|
+
...templateWorkflowSkillPaths(),
|
|
391
|
+
...templatePromptPaths(),
|
|
392
|
+
...adapterAgentPaths(),
|
|
393
|
+
...repoLocalSkillPaths(repoRoot),
|
|
394
|
+
]);
|
|
395
|
+
const fixedSurfaceRuntimeRequiredSubset = measureSurface(repoRoot, [
|
|
396
|
+
...templateWorkflowSkillPaths(),
|
|
397
|
+
...templatePromptPaths(),
|
|
398
|
+
...adapterAgentPaths(),
|
|
399
|
+
...runtimeBridgeSkillPaths(),
|
|
400
|
+
]);
|
|
401
|
+
const scenarios = REPRESENTATIVE_SCENARIOS.map((scenario) => ({
|
|
402
|
+
name: scenario.name,
|
|
403
|
+
description: scenario.description,
|
|
404
|
+
...measureSurface(repoRoot, scenario.files),
|
|
405
|
+
}));
|
|
406
|
+
return {
|
|
407
|
+
fixed_surface_chars_install_upper_bound: fixedSurfaceInstallUpperBound,
|
|
408
|
+
fixed_surface_chars_runtime_required_subset: fixedSurfaceRuntimeRequiredSubset,
|
|
409
|
+
materialized_workflow_packet_chars: measureMaterializedSamples(MATERIALIZED_WORKFLOW_PACKET_SAMPLES),
|
|
410
|
+
materialized_review_packet_chars: measureMaterializedSamples(MATERIALIZED_REVIEW_PACKET_SAMPLES),
|
|
411
|
+
materialized_review_prompt_chars: measureMaterializedSamples(MATERIALIZED_REVIEW_PROMPT_SAMPLES),
|
|
412
|
+
ledger_block_chars: measureMaterializedSamples(LEDGER_BLOCK_SAMPLES),
|
|
413
|
+
representative_loaded_surface_chars: {
|
|
414
|
+
scenarios,
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|