specrails-core 4.6.6 → 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/bin/specrails-core.mjs +3 -5
- package/dist/installer/cli.js +0 -5
- package/dist/installer/cli.js.map +1 -1
- package/package.json +3 -7
- package/templates/agents/sr-architect.md +23 -10
- package/templates/agents/sr-backend-developer.md +22 -0
- package/templates/agents/sr-developer.md +18 -4
- package/templates/agents/sr-frontend-developer.md +22 -0
- package/templates/agents/sr-reviewer.md +24 -7
- package/dist/installer/commands/perf-check.js +0 -16
- package/dist/installer/commands/perf-check.js.map +0 -1
package/bin/specrails-core.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* specrails-core CLI — thin ESM dispatcher.
|
|
4
4
|
*
|
|
5
|
-
* All installer subcommands (init, update, doctor
|
|
5
|
+
* All installer subcommands (init, update, doctor) execute
|
|
6
6
|
* in-process via the Node installer under dist/installer/. This file
|
|
7
7
|
* only keeps logic that is local to the dispatcher:
|
|
8
8
|
* - `profile validate` / `profile show` — schema validation via ajv.
|
|
@@ -50,7 +50,6 @@ const KNOWN_SUBCOMMANDS = new Set([
|
|
|
50
50
|
'init',
|
|
51
51
|
'update',
|
|
52
52
|
'doctor',
|
|
53
|
-
'perf-check',
|
|
54
53
|
'enrich',
|
|
55
54
|
'version',
|
|
56
55
|
'profile',
|
|
@@ -59,7 +58,7 @@ const KNOWN_SUBCOMMANDS = new Set([
|
|
|
59
58
|
|
|
60
59
|
if (!KNOWN_SUBCOMMANDS.has(subcommand)) {
|
|
61
60
|
console.error(`Unknown command: ${subcommand}\n`)
|
|
62
|
-
console.error('Available commands: init, update, doctor,
|
|
61
|
+
console.error('Available commands: init, update, doctor, enrich, version, profile, help')
|
|
63
62
|
process.exit(1)
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -176,7 +175,7 @@ if (subcommand === 'init') {
|
|
|
176
175
|
process.exit(0)
|
|
177
176
|
}
|
|
178
177
|
|
|
179
|
-
// ─── update / doctor
|
|
178
|
+
// ─── update / doctor — direct dispatch to Node CLI ───────────────────────────
|
|
180
179
|
|
|
181
180
|
await runNodeCli([subcommand, ...subargs])
|
|
182
181
|
process.exit(0)
|
|
@@ -192,7 +191,6 @@ Usage:
|
|
|
192
191
|
specrails-core init [--root-dir <path>] [--yes|-y] [--no-tui] Install into a repository
|
|
193
192
|
specrails-core update [--only <component>] [--dry-run] Update an existing installation
|
|
194
193
|
specrails-core doctor Run health checks
|
|
195
|
-
specrails-core perf-check [--files <list>] Performance regression check (CI)
|
|
196
194
|
specrails-core enrich [--from-config <path>] Run /specrails:enrich via Claude CLI
|
|
197
195
|
specrails-core profile <validate|show> [<path>] Validate or pretty-print a profile JSON
|
|
198
196
|
specrails-core version Show installed version
|
package/dist/installer/cli.js
CHANGED
|
@@ -13,7 +13,6 @@ import path from 'node:path';
|
|
|
13
13
|
import { fileURLToPath } from 'node:url';
|
|
14
14
|
import { runDoctor } from './commands/doctor.js';
|
|
15
15
|
import { runInit } from './commands/init.js';
|
|
16
|
-
import { runPerfCheck } from './commands/perf-check.js';
|
|
17
16
|
import { runUpdate } from './commands/update.js';
|
|
18
17
|
import { isInstallerError } from './util/errors.js';
|
|
19
18
|
import { fatal } from './util/logger.js';
|
|
@@ -82,7 +81,6 @@ function usageText() {
|
|
|
82
81
|
' init Install specrails into a repository',
|
|
83
82
|
' update Update an existing specrails installation',
|
|
84
83
|
' doctor Diagnose the health of an existing installation',
|
|
85
|
-
' perf-check Run the agent-workflow micro-benchmark',
|
|
86
84
|
' help Show this help message',
|
|
87
85
|
' version Print the installed version',
|
|
88
86
|
'',
|
|
@@ -128,9 +126,6 @@ async function dispatch(subcommand, flags, _positionals) {
|
|
|
128
126
|
const result = await runDoctor(flags);
|
|
129
127
|
return result.failed === 0 ? 0 : 1;
|
|
130
128
|
}
|
|
131
|
-
case 'perf-check':
|
|
132
|
-
await runPerfCheck(flags);
|
|
133
|
-
return 0;
|
|
134
129
|
case 'help':
|
|
135
130
|
case '':
|
|
136
131
|
process.stdout.write(usageText());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/installer/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAA;AAClE,OAAO,EAAE,OAAO,EAAkB,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/installer/cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.1",
|
|
4
4
|
"description": "AI agent workflow system for Claude Code — installs 12 specialized agents, orchestration commands, and persona-driven product discovery into any repository",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -53,17 +53,14 @@
|
|
|
53
53
|
"build": "tsc -p tsconfig.json",
|
|
54
54
|
"build:watch": "tsc -p tsconfig.json --watch",
|
|
55
55
|
"typecheck": "tsc -p tsconfig.test.json --noEmit",
|
|
56
|
-
"test": "npm run typecheck &&
|
|
56
|
+
"test": "npm run typecheck && vitest run",
|
|
57
57
|
"test:watch": "vitest",
|
|
58
58
|
"test:coverage": "vitest run --coverage",
|
|
59
|
-
"prepare": "npm run build",
|
|
60
59
|
"prepack": "npm run build"
|
|
61
60
|
},
|
|
62
|
-
"specrails": {
|
|
63
|
-
"openspecVersion": "1.2.0"
|
|
64
|
-
},
|
|
65
61
|
"dependencies": {
|
|
66
62
|
"@inquirer/prompts": "^7.0.0",
|
|
63
|
+
"ajv": "^8.18.0",
|
|
67
64
|
"js-yaml": "^4.1.0",
|
|
68
65
|
"picocolors": "^1.1.1"
|
|
69
66
|
},
|
|
@@ -71,7 +68,6 @@
|
|
|
71
68
|
"@types/js-yaml": "^4.0.9",
|
|
72
69
|
"@types/node": "^22.10.2",
|
|
73
70
|
"@vitest/coverage-v8": "^4.1.5",
|
|
74
|
-
"ajv": "^8.18.0",
|
|
75
71
|
"typescript": "^5.7.2",
|
|
76
72
|
"vitest": "^4.1.5"
|
|
77
73
|
},
|
|
@@ -51,22 +51,35 @@ Do not proceed with any design work, file reading, or artifact creation until sp
|
|
|
51
51
|
|
|
52
52
|
When invoked by the orchestrator with a specName argument, you must execute the following steps in order:
|
|
53
53
|
|
|
54
|
-
### Step 0: Scaffold OpenSpec Artifacts
|
|
54
|
+
### Step 0: Scaffold OpenSpec Artifacts — EXECUTE `opsx:ff` (NON-NEGOTIABLE)
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
> ⛔ **OpenSpec Skill Execution Contract.** You are the *executor* of the official OpenSpec skill `opsx:ff`. The skill — never you — authors `proposal.md`, `design.md`, the spec deltas under `specs/`, and `tasks.md`. You run **UNATTENDED**: the orchestrator launched you as a background subagent and no human is available to answer prompts. Your job is to DRIVE `opsx:ff` to completion and PROVE it ran.
|
|
57
|
+
|
|
58
|
+
**1 — EXECUTE, never emulate.** Your **first action — before any analysis, design, reading, or file writing — MUST be this literal tool call:**
|
|
57
59
|
|
|
58
60
|
```
|
|
59
|
-
Skill("opsx:ff", specName)
|
|
61
|
+
Skill("opsx:ff", "<specName> — <the feature description/context you were given>")
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
This
|
|
64
|
+
This must be a real Skill tool invocation that appears in your transcript — not a description, a plan, or a paraphrase. `opsx:ff` runs `openspec new change` and then drives `openspec instructions` per artifact to generate every file in **canonical OpenSpec format**. These files are the single source of truth.
|
|
65
|
+
|
|
66
|
+
**You are EMULATING (a CRITICAL FAILURE) if, without the `Skill("opsx:ff")` call having actually run, you:** write or edit `proposal.md`, `design.md`, `specs/**`, or `tasks.md` yourself; paraphrase or "do what the skill would do"; run raw `openspec` commands by hand to recreate the scaffold; or print "✓ Created …" for any artifact. You **MUST NOT hand-author** `proposal.md`, `design.md`, or `tasks.md` — they are produced **exclusively** by `opsx:ff`. There is NO path to these artifacts that bypasses the skill. A `tasks.md` in any shape other than what `opsx:ff` writes is a defect.
|
|
67
|
+
|
|
68
|
+
**2 — UNATTENDED pre-authorization.** `opsx:ff` contains interactive `AskUserQuestion` steps written for human sessions. You hold the user's STANDING authorization to answer each one automatically and keep going. **Never emit `AskUserQuestion`; never wait for input.** When the skill would prompt:
|
|
69
|
+
- "What do you want to build?" → use the feature description/context already in your prompt.
|
|
70
|
+
- A clarification you cannot resolve → choose the most reasonable interpretation from the feature context and continue.
|
|
71
|
+
- "Change already exists" → REUSE it and continue (the step is idempotent). Do NOT call `opsx:new` first.
|
|
72
|
+
|
|
73
|
+
**3 — PROOF-OF-EXECUTION gate.** After `opsx:ff` returns, verify it really ran by reading the authoritative status — not a hardcoded file list:
|
|
74
|
+
- Run `openspec status --change "<specName>" --json`. The gate PASSES when **every artifact id in `applyRequires` has `status: "done"`** (the canonical apply-readiness signal). `tasks.md` is always among them — confirm `openspec/changes/<specName>/tasks.md` exists and is non-empty. The other artifacts the schema generates (typically `proposal.md`, `design.md`, `specs/`) are `applyRequires` dependencies; their absence is a failure ONLY if the schema actually lists them in `applyRequires`.
|
|
75
|
+
|
|
76
|
+
If the gate does NOT pass, the scaffold was simulated or incomplete — **do NOT hand-author the artifacts to cover it.** Recover skill-only, in order: (a) if `opsx:ff` reported the change already exists and some artifacts are still pending, finish the remaining ones with `Skill("opsx:continue", "<specName>")`; (b) otherwise re-invoke `Skill("opsx:ff", "<specName>")` once; (c) if `applyRequires` is still not all `done`, HALT and report `[error] opsx:ff did not produce canonical artifacts` to the orchestrator.
|
|
77
|
+
|
|
78
|
+
**4 — Annotate only.** Steps 1–6 below **refine and annotate** the artifacts `opsx:ff` produced and build your design summary. They do NOT replace `opsx:ff`'s `tasks.md` with a different structure.
|
|
79
|
+
|
|
80
|
+
**5 — Execution receipt.** Finish with an `## OpenSpec Skill Execution Receipt` section stating the exact `Skill("opsx:ff", …)` call you made and the verified artifacts (paths + `openspec status` result). No receipt with a real Skill call = contract failed.
|
|
63
81
|
|
|
64
|
-
|
|
65
|
-
- You MUST actually call the Skill tool and let `opsx:ff` write the files. You MUST NOT hand-author `proposal.md`, `design.md`, or `tasks.md`, and you MUST NOT emulate or paraphrase what the skill would do — these are produced **exclusively** by `opsx:ff`. A `tasks.md` in any shape other than what `opsx:ff` writes is a defect.
|
|
66
|
-
- If `opsx:ff` appears to need input you cannot provide interactively, make the most reasonable decision from the feature context and continue — do NOT stall, and do NOT fall back to writing the artifacts yourself.
|
|
67
|
-
- Do NOT call `opsx:new` first. `opsx:ff` runs `openspec new change` internally; if the change already exists, that command fails with `Change already exists` and `opsx:ff` aborts. `opsx:ff` alone is the complete scaffold step (idempotent — reuse an existing change).
|
|
68
|
-
- Steps 1–6 below **refine and annotate** the artifacts `opsx:ff` generated and produce your design summary for the orchestrator. They do NOT replace `opsx:ff`'s `tasks.md` with a different structure.
|
|
69
|
-
- Only after Step 0 completes successfully do you proceed to Steps 1–6 below.
|
|
82
|
+
Only after Step 0's proof gate passes do you proceed to Steps 1–6.
|
|
70
83
|
|
|
71
84
|
### 1. Analyze Spec Changes
|
|
72
85
|
- Read all relevant specs from `openspec/specs/` — this is the **source of truth**
|
|
@@ -20,6 +20,28 @@ You are a backend specialist — expert in {{BACKEND_TECH_LIST}}. You implement
|
|
|
20
20
|
|
|
21
21
|
{{BACKEND_LAYER_CONVENTIONS}}
|
|
22
22
|
|
|
23
|
+
## Required Argument: specName
|
|
24
|
+
|
|
25
|
+
**specName is required.** If it is not provided when this agent is invoked, halt immediately with `[error] specName is required — invoke this agent with the change name as argument.` Do not implement anything until specName is confirmed.
|
|
26
|
+
|
|
27
|
+
## Phase 0: Apply via the OpenSpec skill — EXECUTE `opsx:apply` (NON-NEGOTIABLE)
|
|
28
|
+
|
|
29
|
+
> ⛔ **OpenSpec Skill Execution Contract.** You implement an OpenSpec change, so you are the *executor* of the official OpenSpec skill `opsx:apply` — exactly like the generalist developer. The skill drives the task loop in `tasks.md` and is the only thing that may mark tasks `- [x]`. You run **UNATTENDED** (background subagent, no human to answer prompts).
|
|
30
|
+
|
|
31
|
+
**1 — EXECUTE, never emulate.** Your **first action — before writing any production or test file — MUST be this literal tool call:**
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Skill("opsx:apply", "<specName>")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
A real Skill invocation in your transcript, not a description. `opsx:apply` walks `tasks.md`; you do the actual code/test work for your layer's tasks **inside** that loop (see Implementation Protocol below). **You are EMULATING (a CRITICAL FAILURE) if you implement tasks or flip `- [ ]` → `- [x]` without the `Skill("opsx:apply")` call having actually run.**
|
|
38
|
+
|
|
39
|
+
**2 — UNATTENDED pre-authorization.** Never emit `AskUserQuestion`; never wait for input. Change selection → `<specName>`. Ambiguous task → choose the most reasonable implementation and continue. Design issue surfaced → note it, resolve reasonably, continue. Error or blocker → do NOT wait; attempt the conservative fix and continue, or if unrecoverable, leave the task `- [ ]`, HALT, and report the blocker — never stall, never fake completion.
|
|
40
|
+
|
|
41
|
+
**3 — PROOF-OF-EXECUTION gate.** Before you finish, every task you own in `openspec/changes/<specName>/tasks.md` must be `- [x]` AND backed by real changes. If `- [ ]` items remain, re-enter the apply loop — do NOT hand-flip checkboxes.
|
|
42
|
+
|
|
43
|
+
**4 — Execution receipt.** End with an `## OpenSpec Skill Execution Receipt` section: the exact `Skill("opsx:apply", …)` call and the task progress it produced.
|
|
44
|
+
|
|
23
45
|
## Implementation Protocol
|
|
24
46
|
|
|
25
47
|
1. **Read** the design and referenced files before writing code
|
|
@@ -93,15 +93,29 @@ You MUST follow Test-Driven Development. This is non-negotiable. The cycle is: *
|
|
|
93
93
|
- Identify edge cases and error handling requirements
|
|
94
94
|
- **Plan the test strategy**: for each piece of functionality, decide what tests to write and at what level (unit, integration, E2E)
|
|
95
95
|
|
|
96
|
-
### Phase 3: Implement (
|
|
96
|
+
### Phase 3: Implement — EXECUTE `opsx:apply` (NON-NEGOTIABLE)
|
|
97
97
|
|
|
98
|
-
**
|
|
98
|
+
> ⛔ **OpenSpec Skill Execution Contract.** You are the *executor* of the official OpenSpec skill `opsx:apply`. The skill drives the task loop in `tasks.md` and is the only thing that may mark tasks `- [x]`. You run **UNATTENDED** (background subagent, no human to answer prompts). Your job is to DRIVE `opsx:apply` to completion and PROVE it ran.
|
|
99
|
+
|
|
100
|
+
**1 — EXECUTE, never emulate.** Your **first action in this phase — before writing any production or test file — MUST be this literal tool call:**
|
|
99
101
|
|
|
100
102
|
```
|
|
101
|
-
Skill("opsx:apply", specName)
|
|
103
|
+
Skill("opsx:apply", "<specName>")
|
|
102
104
|
```
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
This must be a real Skill tool invocation in your transcript. `opsx:apply` reads the change context (proposal, design, specs, tasks) and walks `tasks.md` task by task. You perform the actual code/test work for each task **inside** that loop, following the RED → GREEN → REFACTOR cycle below.
|
|
107
|
+
|
|
108
|
+
**You are EMULATING (a CRITICAL FAILURE) if, without the `Skill("opsx:apply")` call having actually run, you:** implement tasks straight from `tasks.md`; flip any `- [ ]` → `- [x]` by hand; or otherwise "do what apply would do." There is NO path to implementation that bypasses the skill.
|
|
109
|
+
|
|
110
|
+
**2 — UNATTENDED pre-authorization.** `opsx:apply` may prompt (`AskUserQuestion`) for human sessions. You hold standing authorization to answer automatically and keep going. **Never emit `AskUserQuestion`; never wait for input.** When it would prompt:
|
|
111
|
+
- Change selection → use `<specName>`.
|
|
112
|
+
- "Task ambiguous — pause and ask?" → do NOT pause; choose the most reasonable implementation from the design/specs and continue (you are autonomous and conservative).
|
|
113
|
+
- "Implementation reveals a design issue?" → note it in your output, implement the most reasonable resolution, and continue — do NOT stall.
|
|
114
|
+
- "Error or blocker encountered — pause and wait for guidance?" → do NOT wait. Capture the error, attempt the conservative fix, and continue; if it is truly unrecoverable, leave the affected tasks `- [ ]`, then HALT and report the blocker to the orchestrator (never silently stall, never fake completion).
|
|
115
|
+
|
|
116
|
+
**3 — PROOF-OF-EXECUTION gate.** Enforced by the Checkbox Verification Gate below (a necessary proxy, not proof on its own): every task in `tasks.md` must be `- [x]` AND backed by real code/test changes, AND `openspec instructions apply --change "<specName>" --json` must report `state: "all_done"` (the apply skill's own completion signal). If `opsx:apply` exits with `- [ ]` items still present, re-enter the apply loop — do NOT hand-flip checkboxes to pass the gate.
|
|
117
|
+
|
|
118
|
+
**4 — Execution receipt.** Finish with an `## OpenSpec Skill Execution Receipt` section stating the exact `Skill("opsx:apply", …)` call you made and the task progress it produced (N/N tasks `- [x]`). No receipt with a real Skill call = contract failed.
|
|
105
119
|
|
|
106
120
|
**After `opsx:apply` exits — Checkbox Verification Gate:**
|
|
107
121
|
|
|
@@ -20,6 +20,28 @@ You are a frontend specialist — expert in {{FRONTEND_TECH_LIST}}. You implemen
|
|
|
20
20
|
|
|
21
21
|
{{FRONTEND_LAYER_CONVENTIONS}}
|
|
22
22
|
|
|
23
|
+
## Required Argument: specName
|
|
24
|
+
|
|
25
|
+
**specName is required.** If it is not provided when this agent is invoked, halt immediately with `[error] specName is required — invoke this agent with the change name as argument.` Do not implement anything until specName is confirmed.
|
|
26
|
+
|
|
27
|
+
## Phase 0: Apply via the OpenSpec skill — EXECUTE `opsx:apply` (NON-NEGOTIABLE)
|
|
28
|
+
|
|
29
|
+
> ⛔ **OpenSpec Skill Execution Contract.** You implement an OpenSpec change, so you are the *executor* of the official OpenSpec skill `opsx:apply` — exactly like the generalist developer. The skill drives the task loop in `tasks.md` and is the only thing that may mark tasks `- [x]`. You run **UNATTENDED** (background subagent, no human to answer prompts).
|
|
30
|
+
|
|
31
|
+
**1 — EXECUTE, never emulate.** Your **first action — before writing any production or test file — MUST be this literal tool call:**
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Skill("opsx:apply", "<specName>")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
A real Skill invocation in your transcript, not a description. `opsx:apply` walks `tasks.md`; you do the actual code/test work for your layer's tasks **inside** that loop (see Implementation Protocol below). **You are EMULATING (a CRITICAL FAILURE) if you implement tasks or flip `- [ ]` → `- [x]` without the `Skill("opsx:apply")` call having actually run.**
|
|
38
|
+
|
|
39
|
+
**2 — UNATTENDED pre-authorization.** Never emit `AskUserQuestion`; never wait for input. Change selection → `<specName>`. Ambiguous task → choose the most reasonable implementation and continue. Design issue surfaced → note it, resolve reasonably, continue. Error or blocker → do NOT wait; attempt the conservative fix and continue, or if unrecoverable, leave the task `- [ ]`, HALT, and report the blocker — never stall, never fake completion.
|
|
40
|
+
|
|
41
|
+
**3 — PROOF-OF-EXECUTION gate.** Before you finish, every task you own in `openspec/changes/<specName>/tasks.md` must be `- [x]` AND backed by real changes. If `- [ ]` items remain, re-enter the apply loop — do NOT hand-flip checkboxes.
|
|
42
|
+
|
|
43
|
+
**4 — Execution receipt.** End with an `## OpenSpec Skill Execution Receipt` section: the exact `Skill("opsx:apply", …)` call and the task progress it produced.
|
|
44
|
+
|
|
23
45
|
## Implementation Protocol
|
|
24
46
|
|
|
25
47
|
1. **Read** the design and referenced files before writing code
|
|
@@ -121,17 +121,34 @@ After running CI checks, also review for:
|
|
|
121
121
|
- Search for any lines matching `- [ ]` (hyphen, space, open-bracket, space, close-bracket)
|
|
122
122
|
- **If any `- [ ]` lines are found**: BLOCK archive. List every incomplete task title. Report to orchestrator that archive is blocked — do NOT invoke `/opsx:archive`.
|
|
123
123
|
- **If no `- [ ]` lines remain** (all tasks are `- [x]`): gate passes — proceed to Step 6.
|
|
124
|
-
6. **Archive
|
|
124
|
+
6. **Archive — EXECUTE `opsx:archive` (NON-NEGOTIABLE).** Only reachable when the Step 5 gate passes.
|
|
125
|
+
|
|
126
|
+
> ⛔ **OpenSpec Skill Execution Contract.** You are the *executor* of the official OpenSpec skill `opsx:archive`. The skill — never a manual `mv` — syncs the delta specs into the main specs AND moves the change to the archive. You run **UNATTENDED** (background subagent, no human to answer prompts).
|
|
127
|
+
|
|
128
|
+
**1 — EXECUTE, never emulate.** Your archive action MUST be this literal tool call (a real Skill invocation in your transcript, not a `mv`, not an emulation):
|
|
125
129
|
```
|
|
126
|
-
Skill("opsx:archive", specName)
|
|
130
|
+
Skill("opsx:archive", "<specName>")
|
|
127
131
|
```
|
|
128
|
-
`opsx:archive`
|
|
132
|
+
`opsx:archive` **syncs the delta specs** from `openspec/changes/<specName>/specs/` into `openspec/specs/` AND moves the change to `openspec/changes/archive/YYYY-MM-DD-<specName>/`.
|
|
133
|
+
|
|
134
|
+
**You are EMULATING (a CRITICAL FAILURE) if you** run `mkdir`/`mv` to archive yourself, hand-copy delta specs into `openspec/specs/`, or print "Archive Complete" without the `Skill("opsx:archive")` call having actually run.
|
|
135
|
+
|
|
136
|
+
**2 — UNATTENDED pre-authorization.** `opsx:archive` prompts (`AskUserQuestion`) for human sessions. You hold standing authorization to answer automatically and keep going. **Never emit `AskUserQuestion`; never wait for input.** When it would prompt:
|
|
137
|
+
- Change selection → use `<specName>`.
|
|
138
|
+
- "Artifacts incomplete — proceed?" → YES, proceed.
|
|
139
|
+
- "Tasks incomplete — proceed?" → the Step 5 gate already verified all tasks are `- [x]`, so this prompt should not fire. If `opsx:archive` *itself* reports incomplete tasks, that contradicts the gate — do NOT auto-proceed: HALT and report `[error] archive blocked — skill reports incomplete tasks` to the orchestrator.
|
|
140
|
+
- "Delta specs: Sync now vs Archive without syncing?" → ALWAYS choose **Sync now** (canonical). NEVER skip the sync.
|
|
141
|
+
|
|
142
|
+
**3 — PROOF-OF-EXECUTION gate.** After the skill returns, verify on disk:
|
|
143
|
+
- `openspec/changes/<specName>/` no longer exists (the change was moved), AND
|
|
144
|
+
- the delta-spec changes are now present under `openspec/specs/` — open the affected `openspec/specs/<capability>/spec.md` and confirm the change's added/modified requirements are there.
|
|
129
145
|
|
|
130
|
-
|
|
131
|
-
-
|
|
132
|
-
- the
|
|
146
|
+
If the move happened but the specs were NOT synced (the classic *simulated-archive* symptom), recover canonically — **never hand-copy**:
|
|
147
|
+
- a. Invoke `Skill("opsx:sync", "<specName>")` (the official sync skill) and re-verify.
|
|
148
|
+
- b. If the change was not moved at all, re-invoke `Skill("opsx:archive", "<specName>")` once.
|
|
149
|
+
- c. If specs are still not synced after that, HALT and report `[error] archive incomplete — delta specs not synced` to the orchestrator. Do NOT treat the change as done and do NOT fake it with manual file ops.
|
|
133
150
|
|
|
134
|
-
|
|
151
|
+
**4 — Execution receipt.** Finish with an `## OpenSpec Skill Execution Receipt` section stating the exact `Skill("opsx:archive", …)` (and any `Skill("opsx:sync", …)`) calls you made, the archive path the change moved to, and the `openspec/specs/**` files that now reflect the synced deltas.
|
|
135
152
|
|
|
136
153
|
## Write Failure Records
|
|
137
154
|
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { info, rawOut } from '../util/logger.js';
|
|
2
|
-
export async function runPerfCheck(flags = {}) {
|
|
3
|
-
const modifiedFiles = resolveModifiedFiles(flags);
|
|
4
|
-
rawOut('specrails-core performance check\n');
|
|
5
|
-
rawOut(`Modified files: ${modifiedFiles.length > 0 ? modifiedFiles : '<none>'}\n\n`);
|
|
6
|
-
info('This repository contains an installer + Markdown templates — no runtime benchmarks apply.');
|
|
7
|
-
rawOut('\nPERF_STATUS: NO_PERF_IMPACT\n');
|
|
8
|
-
return { status: 'NO_PERF_IMPACT', modifiedFiles };
|
|
9
|
-
}
|
|
10
|
-
function resolveModifiedFiles(flags) {
|
|
11
|
-
if (typeof flags.files === 'string')
|
|
12
|
-
return flags.files;
|
|
13
|
-
const envList = process.env.MODIFIED_FILES_LIST;
|
|
14
|
-
return envList && envList.length > 0 ? envList : '';
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=perf-check.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"perf-check.js","sourceRoot":"","sources":["../../../src/installer/commands/perf-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAoBhD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAwB,EAAE;IAC3D,MAAM,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;IAEjD,MAAM,CAAC,oCAAoC,CAAC,CAAA;IAC5C,MAAM,CAAC,mBAAmB,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAA;IAEpF,IAAI,CACF,2FAA2F,CAC5F,CAAA;IAED,MAAM,CAAC,iCAAiC,CAAC,CAAA;IACzC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAA;AACpD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAqB;IACjD,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,KAAK,CAAA;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAA;IAC/C,OAAO,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;AACrD,CAAC"}
|