specrails-core 5.5.1 → 6.0.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.
Files changed (276) hide show
  1. package/README.md +27 -145
  2. package/bin/specrails-core.mjs +12 -554
  3. package/dist/agent-runtime/capabilities.js +0 -1
  4. package/dist/agent-runtime/cli-executor.d.ts +1 -1
  5. package/dist/agent-runtime/cli-executor.js +4 -3
  6. package/dist/agent-runtime/cli-process.js +0 -1
  7. package/dist/agent-runtime/cli.d.ts +8 -0
  8. package/dist/agent-runtime/cli.js +31 -5
  9. package/dist/agent-runtime/codex-schema.js +0 -1
  10. package/dist/agent-runtime/compact/architect.d.ts +3 -272
  11. package/dist/agent-runtime/compact/architect.js +8 -9
  12. package/dist/agent-runtime/compact/chat-client.d.ts +3 -3
  13. package/dist/agent-runtime/compact/chat-client.js +1 -2
  14. package/dist/agent-runtime/compact/developer.d.ts +3 -70
  15. package/dist/agent-runtime/compact/developer.js +13 -14
  16. package/dist/agent-runtime/compact/environment.d.ts +4 -5
  17. package/dist/agent-runtime/compact/environment.js +1 -2
  18. package/dist/agent-runtime/compact/exit-code-honesty.d.ts +2 -1
  19. package/dist/agent-runtime/compact/exit-code-honesty.js +0 -1
  20. package/dist/agent-runtime/compact/guarded-loop.d.ts +2 -18
  21. package/dist/agent-runtime/compact/guarded-loop.js +7 -8
  22. package/dist/agent-runtime/compact/prompt-inputs.d.ts +0 -2
  23. package/dist/agent-runtime/compact/prompt-inputs.js +1 -2
  24. package/dist/agent-runtime/compact/reviewer.d.ts +0 -13
  25. package/dist/agent-runtime/compact/reviewer.js +5 -6
  26. package/dist/agent-runtime/compact/step.d.ts +0 -1
  27. package/dist/agent-runtime/compact/step.js +1 -2
  28. package/dist/agent-runtime/compact/test-reachability.js +0 -1
  29. package/dist/agent-runtime/config.js +0 -1
  30. package/dist/agent-runtime/core-host.d.ts +1 -1
  31. package/dist/agent-runtime/core-host.js +5 -3
  32. package/dist/agent-runtime/durable-store.d.ts +0 -1
  33. package/dist/agent-runtime/durable-store.js +1 -2
  34. package/dist/agent-runtime/efficiency-summary.d.ts +2 -2
  35. package/dist/agent-runtime/efficiency-summary.js +1 -2
  36. package/dist/agent-runtime/efficiency-types.js +0 -1
  37. package/dist/agent-runtime/efficiency.js +0 -1
  38. package/dist/agent-runtime/evaluation-corpus.js +0 -1
  39. package/dist/agent-runtime/evaluation.d.ts +2 -1
  40. package/dist/agent-runtime/evaluation.js +1 -2
  41. package/dist/agent-runtime/executor-types.d.ts +1 -1
  42. package/dist/agent-runtime/executor-types.js +0 -1
  43. package/dist/agent-runtime/executors.js +0 -1
  44. package/dist/agent-runtime/gemini-policy.js +0 -1
  45. package/dist/agent-runtime/graph/artifacts.d.ts +1 -1
  46. package/dist/agent-runtime/graph/artifacts.js +11 -5
  47. package/dist/agent-runtime/graph/nodes.d.ts +1 -1
  48. package/dist/agent-runtime/graph/nodes.js +1 -2
  49. package/dist/agent-runtime/graph/review-policy.js +0 -1
  50. package/dist/agent-runtime/graph/roles.d.ts +2 -5
  51. package/dist/agent-runtime/graph/roles.js +2 -8
  52. package/dist/agent-runtime/graph/state.d.ts +1 -1
  53. package/dist/agent-runtime/graph/state.js +0 -1
  54. package/dist/agent-runtime/graph-checkpointer.d.ts +2 -1
  55. package/dist/agent-runtime/graph-checkpointer.js +0 -1
  56. package/dist/agent-runtime/guardrails.d.ts +3 -3
  57. package/dist/agent-runtime/guardrails.js +1 -2
  58. package/dist/agent-runtime/index.d.ts +2 -1
  59. package/dist/agent-runtime/index.js +2 -2
  60. package/dist/agent-runtime/kimi-acp.js +1 -2
  61. package/dist/agent-runtime/kimi-model.d.ts +6 -0
  62. package/dist/agent-runtime/kimi-model.js +12 -0
  63. package/dist/agent-runtime/openai-executor.d.ts +0 -9
  64. package/dist/agent-runtime/openai-executor.js +6 -7
  65. package/dist/agent-runtime/openspec-tool-server.js +1 -2
  66. package/dist/agent-runtime/openspec.d.ts +0 -2
  67. package/dist/agent-runtime/openspec.js +3 -7
  68. package/dist/agent-runtime/prompts.d.ts +4 -3
  69. package/dist/agent-runtime/prompts.js +0 -1
  70. package/dist/agent-runtime/provider-diagnostic.js +1 -2
  71. package/dist/agent-runtime/recovery.d.ts +46 -0
  72. package/dist/agent-runtime/recovery.js +169 -0
  73. package/dist/agent-runtime/repository-context.d.ts +1 -1
  74. package/dist/agent-runtime/repository-context.js +0 -1
  75. package/dist/agent-runtime/review-context.d.ts +1 -1
  76. package/dist/agent-runtime/review-context.js +0 -1
  77. package/dist/agent-runtime/role-routing.js +0 -1
  78. package/dist/agent-runtime/role-state.js +0 -1
  79. package/dist/agent-runtime/runtime-identity.js +1 -2
  80. package/dist/agent-runtime/tool-event.js +0 -1
  81. package/dist/agent-runtime/verification-plan.d.ts +5 -4
  82. package/dist/agent-runtime/verification-plan.js +1 -2
  83. package/dist/agent-runtime/workflow-types.js +0 -1
  84. package/dist/agent-runtime/workflow.js +0 -1
  85. package/dist/agent-runtime/workspace-tools.d.ts +2 -2
  86. package/dist/agent-runtime/workspace-tools.js +1 -2
  87. package/dist/installer/cli.d.ts +3 -32
  88. package/dist/installer/cli.js +26 -101
  89. package/dist/installer/commands/framework.d.ts +4 -3
  90. package/dist/installer/commands/framework.js +0 -1
  91. package/dist/installer/commands/init.d.ts +4 -25
  92. package/dist/installer/commands/init.js +5 -8
  93. package/dist/installer/phases/framework-lifecycle.d.ts +3 -17
  94. package/dist/installer/phases/framework-lifecycle.js +2 -3
  95. package/dist/installer/phases/install-config.d.ts +7 -8
  96. package/dist/installer/phases/install-config.js +2 -7
  97. package/dist/installer/phases/manifest.d.ts +6 -7
  98. package/dist/installer/phases/manifest.js +2 -7
  99. package/dist/installer/phases/prereqs.d.ts +6 -7
  100. package/dist/installer/phases/prereqs.js +4 -6
  101. package/dist/installer/phases/provider-detect.d.ts +6 -7
  102. package/dist/installer/phases/provider-detect.js +2 -4
  103. package/dist/installer/phases/scaffold.d.ts +9 -10
  104. package/dist/installer/phases/scaffold.js +82 -805
  105. package/dist/installer/util/errors.js +0 -1
  106. package/dist/installer/util/exec.d.ts +3 -2
  107. package/dist/installer/util/exec.js +0 -1
  108. package/dist/installer/util/fs.d.ts +0 -10
  109. package/dist/installer/util/fs.js +1 -2
  110. package/dist/installer/util/git.js +0 -1
  111. package/dist/installer/util/install-transaction.d.ts +2 -2
  112. package/dist/installer/util/install-transaction.js +1 -2
  113. package/dist/installer/util/logger.d.ts +1 -3
  114. package/dist/installer/util/logger.js +0 -1
  115. package/dist/installer/util/paths.js +0 -1
  116. package/dist/installer/util/registry.d.ts +4 -8
  117. package/dist/installer/util/registry.js +2 -3
  118. package/dist/{installer/runtime → pipeline}/pipeline-state.js +0 -3
  119. package/dist/shared/args.d.ts +18 -0
  120. package/dist/shared/args.js +53 -0
  121. package/integration-contract.json +10 -46
  122. package/package.json +3 -10
  123. package/templates/agents/sr-architect.md +15 -310
  124. package/templates/agents/sr-developer.md +15 -269
  125. package/templates/agents/sr-reviewer.md +13 -367
  126. package/templates/codex-skills/rails/sr-architect/SKILL.md +14 -308
  127. package/templates/codex-skills/rails/sr-developer/SKILL.md +14 -201
  128. package/templates/codex-skills/rails/sr-reviewer/SKILL.md +15 -289
  129. package/templates/kimi/specrails/run-skill.mjs +91 -2173
  130. package/bin/tui-installer.mjs +0 -430
  131. package/commands/doctor.md +0 -62
  132. package/dist/agent-runtime/capabilities.js.map +0 -1
  133. package/dist/agent-runtime/cli-executor.js.map +0 -1
  134. package/dist/agent-runtime/cli-process.js.map +0 -1
  135. package/dist/agent-runtime/cli.js.map +0 -1
  136. package/dist/agent-runtime/codex-schema.js.map +0 -1
  137. package/dist/agent-runtime/compact/architect.js.map +0 -1
  138. package/dist/agent-runtime/compact/chat-client.js.map +0 -1
  139. package/dist/agent-runtime/compact/developer.js.map +0 -1
  140. package/dist/agent-runtime/compact/environment.js.map +0 -1
  141. package/dist/agent-runtime/compact/exit-code-honesty.js.map +0 -1
  142. package/dist/agent-runtime/compact/guarded-loop.js.map +0 -1
  143. package/dist/agent-runtime/compact/prompt-inputs.js.map +0 -1
  144. package/dist/agent-runtime/compact/reviewer.js.map +0 -1
  145. package/dist/agent-runtime/compact/step.js.map +0 -1
  146. package/dist/agent-runtime/compact/test-reachability.js.map +0 -1
  147. package/dist/agent-runtime/config.js.map +0 -1
  148. package/dist/agent-runtime/core-host.js.map +0 -1
  149. package/dist/agent-runtime/durable-store.js.map +0 -1
  150. package/dist/agent-runtime/efficiency-summary.js.map +0 -1
  151. package/dist/agent-runtime/efficiency-types.js.map +0 -1
  152. package/dist/agent-runtime/efficiency.js.map +0 -1
  153. package/dist/agent-runtime/evaluation-corpus.js.map +0 -1
  154. package/dist/agent-runtime/evaluation.js.map +0 -1
  155. package/dist/agent-runtime/executor-types.js.map +0 -1
  156. package/dist/agent-runtime/executors.js.map +0 -1
  157. package/dist/agent-runtime/gemini-policy.js.map +0 -1
  158. package/dist/agent-runtime/graph/artifacts.js.map +0 -1
  159. package/dist/agent-runtime/graph/nodes.js.map +0 -1
  160. package/dist/agent-runtime/graph/review-policy.js.map +0 -1
  161. package/dist/agent-runtime/graph/roles.js.map +0 -1
  162. package/dist/agent-runtime/graph/state.js.map +0 -1
  163. package/dist/agent-runtime/graph-checkpointer.js.map +0 -1
  164. package/dist/agent-runtime/guardrails.js.map +0 -1
  165. package/dist/agent-runtime/index.js.map +0 -1
  166. package/dist/agent-runtime/kimi-acp.js.map +0 -1
  167. package/dist/agent-runtime/openai-executor.js.map +0 -1
  168. package/dist/agent-runtime/openspec-tool-server.js.map +0 -1
  169. package/dist/agent-runtime/openspec.js.map +0 -1
  170. package/dist/agent-runtime/prompts.js.map +0 -1
  171. package/dist/agent-runtime/provider-diagnostic.js.map +0 -1
  172. package/dist/agent-runtime/repository-context.js.map +0 -1
  173. package/dist/agent-runtime/review-context.js.map +0 -1
  174. package/dist/agent-runtime/role-routing.js.map +0 -1
  175. package/dist/agent-runtime/role-state.js.map +0 -1
  176. package/dist/agent-runtime/runtime-identity.js.map +0 -1
  177. package/dist/agent-runtime/tool-event.js.map +0 -1
  178. package/dist/agent-runtime/verification-plan.js.map +0 -1
  179. package/dist/agent-runtime/workflow-types.js.map +0 -1
  180. package/dist/agent-runtime/workflow.js.map +0 -1
  181. package/dist/agent-runtime/workspace-tools.js.map +0 -1
  182. package/dist/installer/cli.js.map +0 -1
  183. package/dist/installer/commands/doctor.d.ts +0 -27
  184. package/dist/installer/commands/doctor.js +0 -615
  185. package/dist/installer/commands/doctor.js.map +0 -1
  186. package/dist/installer/commands/framework.js.map +0 -1
  187. package/dist/installer/commands/init.js.map +0 -1
  188. package/dist/installer/commands/update.d.ts +0 -56
  189. package/dist/installer/commands/update.js +0 -257
  190. package/dist/installer/commands/update.js.map +0 -1
  191. package/dist/installer/commands/v5-migration.d.ts +0 -32
  192. package/dist/installer/commands/v5-migration.js +0 -133
  193. package/dist/installer/commands/v5-migration.js.map +0 -1
  194. package/dist/installer/phases/framework-lifecycle.js.map +0 -1
  195. package/dist/installer/phases/install-config.js.map +0 -1
  196. package/dist/installer/phases/manifest.js.map +0 -1
  197. package/dist/installer/phases/prereqs.js.map +0 -1
  198. package/dist/installer/phases/provider-detect.js.map +0 -1
  199. package/dist/installer/phases/scaffold.js.map +0 -1
  200. package/dist/installer/runtime/kimi.d.ts +0 -84
  201. package/dist/installer/runtime/kimi.js +0 -255
  202. package/dist/installer/runtime/kimi.js.map +0 -1
  203. package/dist/installer/runtime/pipeline-state.js.map +0 -1
  204. package/dist/installer/util/errors.js.map +0 -1
  205. package/dist/installer/util/exec.js.map +0 -1
  206. package/dist/installer/util/fs.js.map +0 -1
  207. package/dist/installer/util/git.js.map +0 -1
  208. package/dist/installer/util/install-transaction.js.map +0 -1
  209. package/dist/installer/util/logger.js.map +0 -1
  210. package/dist/installer/util/paths.js.map +0 -1
  211. package/dist/installer/util/prompts.d.ts +0 -23
  212. package/dist/installer/util/prompts.js +0 -49
  213. package/dist/installer/util/prompts.js.map +0 -1
  214. package/dist/installer/util/registry.js.map +0 -1
  215. package/dist/installer/util/template.d.ts +0 -23
  216. package/dist/installer/util/template.js +0 -60
  217. package/dist/installer/util/template.js.map +0 -1
  218. package/docs/README.md +0 -40
  219. package/docs/agent-runtime-efficiency.md +0 -65
  220. package/docs/agent-runtime.md +0 -347
  221. package/docs/agents.md +0 -315
  222. package/docs/changelog.md +0 -168
  223. package/docs/ci-cd.md +0 -60
  224. package/docs/concepts.md +0 -183
  225. package/docs/customization.md +0 -363
  226. package/docs/deployment.md +0 -234
  227. package/docs/getting-started.md +0 -122
  228. package/docs/installation.md +0 -395
  229. package/docs/local-tickets.md +0 -191
  230. package/docs/migration-guide.md +0 -140
  231. package/docs/playbook-oss-maintainer.md +0 -112
  232. package/docs/playbook-parallel-dev.md +0 -124
  233. package/docs/playbook-product-discovery.md +0 -115
  234. package/docs/plugin-architecture.md +0 -144
  235. package/docs/research/codex-compatibility-analysis.md +0 -365
  236. package/docs/research/mcp-feasibility-analysis.md +0 -382
  237. package/docs/testing/test-matrix-codex.md +0 -130
  238. package/docs/updating.md +0 -89
  239. package/docs/user-docs/cli-reference.md +0 -428
  240. package/docs/user-docs/codex-vs-claude-code.md +0 -23
  241. package/docs/user-docs/core-updates.md +0 -70
  242. package/docs/user-docs/faq.md +0 -146
  243. package/docs/user-docs/getting-started-codex.md +0 -194
  244. package/docs/user-docs/getting-started-kimi.md +0 -423
  245. package/docs/user-docs/installation.md +0 -237
  246. package/docs/user-docs/provider-pipelines.md +0 -96
  247. package/docs/user-docs/quick-start.md +0 -161
  248. package/docs/windows.md +0 -78
  249. package/docs/workflows.md +0 -463
  250. package/schemas/profile.v1.json +0 -207
  251. package/templates/claude-md/CLAUDE-quickstart.md +0 -54
  252. package/templates/claude-md/root.md +0 -50
  253. package/templates/codex-skills/batch-implement/SKILL.md +0 -38
  254. package/templates/codex-skills/implement/SKILL.md +0 -38
  255. package/templates/codex-skills/retry/SKILL.md +0 -16
  256. package/templates/commands/specrails/compat-check.md +0 -271
  257. package/templates/commands/specrails/doctor.md +0 -62
  258. package/templates/commands/specrails/explore-spec.md +0 -173
  259. package/templates/commands/specrails/health-check.md +0 -527
  260. package/templates/commands/specrails/memory-inspect.md +0 -261
  261. package/templates/commands/specrails/opsx-diff.md +0 -419
  262. package/templates/commands/specrails/propose-spec.md +0 -102
  263. package/templates/commands/specrails/refactor-recommender.md +0 -169
  264. package/templates/commands/specrails/telemetry.md +0 -552
  265. package/templates/commands/specrails/why.md +0 -96
  266. package/templates/gemini-commands/batch-implement.toml +0 -37
  267. package/templates/gemini-commands/implement.toml +0 -37
  268. package/templates/gemini-commands/retry.toml +0 -15
  269. package/templates/profiles/default.json +0 -14
  270. package/templates/profiles/kimi-default.json +0 -15
  271. package/templates/rules/layer.md +0 -8
  272. package/templates/runtime/provider-pipeline.md +0 -113
  273. package/templates/security/security-exemptions.yaml +0 -20
  274. package/templates/settings/confidence-config.json +0 -17
  275. package/templates/settings/settings.json +0 -15
  276. /package/dist/{installer/runtime → pipeline}/pipeline-state.d.ts +0 -0
@@ -4,16 +4,16 @@ import { unreachedTestFiles, unreachedTestsReason } from './test-reachability.js
4
4
  import path from 'node:path';
5
5
  import { AgentExecutionError } from '../executor-types.js';
6
6
  import { artifactPath } from '../openspec.js';
7
- import { readVerificationEvidence } from '../../installer/runtime/pipeline-state.js';
7
+ import { readVerificationEvidence } from '../../pipeline/pipeline-state.js';
8
8
  import { bounded } from './prompt-inputs.js';
9
9
  import { finalJson, on, openspecCall, strings, text, toolStep } from './step.js';
10
10
  /** Tool calls one task group may spend before it must report. */
11
- export const DEFAULT_TASK_TOOL_BUDGET = 25;
11
+ const DEFAULT_TASK_TOOL_BUDGET = 25;
12
12
  /** Frozen planning artifacts: the developer edits application code, never the plan. */
13
13
  const FROZEN_PATH = /(?:^|[\\/])openspec[\\/]/i;
14
14
  const DEVELOPER_TOOLS = ['list_files', 'read_file', 'read_lines', 'search_text', 'get_diff', 'write_file', 'apply_patch'];
15
15
  const stringList = { type: 'array', items: { type: 'string' } };
16
- export const TASK_RESULT_SCHEMA = { type: 'object', additionalProperties: false, required: ['summary', 'files', 'tests', 'verification', 'incomplete'], properties: { summary: { type: 'string' }, files: stringList, tests: stringList, verification: { type: 'string' }, incomplete: { type: 'array', items: { type: 'object', additionalProperties: false, required: ['task', 'reason'], properties: { task: { type: 'string' }, reason: { type: 'string' } } } } } };
16
+ const TASK_RESULT_SCHEMA = { type: 'object', additionalProperties: false, required: ['summary', 'files', 'tests', 'verification', 'incomplete'], properties: { summary: { type: 'string' }, files: stringList, tests: stringList, verification: { type: 'string' }, incomplete: { type: 'array', items: { type: 'object', additionalProperties: false, required: ['task', 'reason'], properties: { task: { type: 'string' }, reason: { type: 'string' } } } } } };
17
17
  /** Parses the `## N. Title` / `- [ ] N.M text` layout the OpenSpec tasks template prescribes. */
18
18
  export function parseTaskGroups(markdown) {
19
19
  const groups = [];
@@ -133,7 +133,7 @@ function findFiles(root, base, depth = 0) {
133
133
  return out;
134
134
  }
135
135
  /** Application source/test files under the roots (bounded), excluding plans, deps and dot dirs. */
136
- export function repositoryInventory(roots, limit = 60) {
136
+ function repositoryInventory(roots, limit = 60) {
137
137
  const out = [];
138
138
  const walk = (dir, rel, depth) => {
139
139
  if (depth > 6 || out.length >= limit)
@@ -247,7 +247,7 @@ export function foreignLanguageFile(roots, file, languages) {
247
247
  return `"${file}" is ${language}, but this repository is ${languages.primary}-only. Write the same behaviour in ${languages.primary} inside the existing modules; do not add a second language.`;
248
248
  }
249
249
  /** Existing test directories (relative, POSIX) among the conventional names, e.g. `tests`, `test`, `__tests__`, `spec`. */
250
- export function existingTestDirs(roots) {
250
+ function existingTestDirs(roots) {
251
251
  const names = ['tests', 'test', '__tests__', 'spec', 'specs'];
252
252
  return [...new Set(roots.flatMap(root => names.filter(name => { try {
253
253
  return statSync(path.join(root, name)).isDirectory();
@@ -317,7 +317,7 @@ export function locateNamedFile(roots, file) {
317
317
  return undefined;
318
318
  }
319
319
  /** Extra tool calls a correction group gets on top of the task budget: it must read AND patch, and the feedback is long. */
320
- export const CORRECTION_BUDGET_BONUS = 10;
320
+ const CORRECTION_BUDGET_BONUS = 10;
321
321
  /**
322
322
  * Source excerpts around every `file:line` the feedback names (Jest/Babel
323
323
  * `path/file.js: … (30:56)`, TS `file.ts(12,3)` / `file.ts:12:3`, mocha
@@ -369,9 +369,9 @@ export function feedbackExcerpts(feedback, roots, options = {}) {
369
369
  return chunks.join('\n\n');
370
370
  }
371
371
  /** An existing file this long is edited with apply_patch, never regenerated whole (observed: a 1.4k-line test rewritten twice in one group, ~25 minutes of generation). */
372
- export const REWRITE_MAX_LINES = 150;
372
+ const REWRITE_MAX_LINES = 150;
373
373
  /** Above this many lines, `read_file` answers with an outline (head + index of definitions) instead of the whole file. */
374
- export const OUTLINE_MIN_LINES = 400;
374
+ const OUTLINE_MIN_LINES = 400;
375
375
  const OUTLINE_HEAD_LINES = 120;
376
376
  const DEFINITION_LINE = /^\s*(?:(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s*\w+|(?:export\s+)?class\s+\w+|(?:export\s+)?(?:const|let|var)\s+\w+\s*=\s*(?:async\s*)?(?:function\b|\([^)]*\)\s*=>|\w+\s*=>)|(?:static\s+|async\s+|get\s+|set\s+)?[A-Za-z_$][\w$]*\s*\([^)]*\)\s*\{|(?:describe|it|test|suite|context)\s*\(|def\s+\w+|func\s+(?:\([^)]*\)\s*)?\w+|(?:pub\s+)?fn\s+\w+)/;
377
377
  /**
@@ -380,7 +380,7 @@ const DEFINITION_LINE = /^\s*(?:(?:export\s+)?(?:default\s+)?(?:async\s+)?functi
380
380
  * range it needs with read_lines instead of putting 15k tokens of test file
381
381
  * into the transcript on every read (observed: 4-minute prefills).
382
382
  */
383
- export function outlineLargeFile(file, content) {
383
+ function outlineLargeFile(file, content) {
384
384
  const lines = content.split('\n');
385
385
  if (lines.length <= OUTLINE_MIN_LINES)
386
386
  return undefined;
@@ -391,13 +391,13 @@ export function outlineLargeFile(file, content) {
391
391
  return JSON.stringify({ outline: true, path: file, totalLines: lines.length, head: lines.slice(0, OUTLINE_HEAD_LINES).join('\n'), definitions: index, note: `${file} has ${lines.length} lines; this is its first ${OUTLINE_HEAD_LINES} lines plus an index of definitions. Read only the range you need with read_lines(path, startLine, endLine); do not read the whole file.` });
392
392
  }
393
393
  /** Files a model writes to narrate its own work; never part of a task, always noise for the reviewer (observed: fix_summary.json, task-summary.json in the repository root). */
394
- export const NARRATION_FILE = /(?:^|\/)(?:[\w.-]*(?:summary|progress|scratch|handoff)[\w.-]*)\.(?:json|md|txt)$/i;
394
+ const NARRATION_FILE = /(?:^|\/)(?:[\w.-]*(?:summary|progress|scratch|handoff)[\w.-]*)\.(?:json|md|txt)$/i;
395
395
  /** Media/binary extensions a text-only tool can never produce correctly. */
396
396
  export const BINARY_ASSET = /\.(?:wav|mp3|ogg|flac|m4a|aac|png|jpe?g|gif|webp|bmp|ico|woff2?|ttf|otf|eot|mp4|webm|mov|zip|gz|tar|pdf|wasm)$/i;
397
397
  /** Extra write-only calls a task group gets when it spent its whole budget reading. */
398
- export const WRITE_EXTENSION_CALLS = 6;
398
+ const WRITE_EXTENSION_CALLS = 6;
399
399
  /** Tool calls the in-place fix round after a failed group check may spend. */
400
- export const GROUP_FIX_BUDGET = 20;
400
+ const GROUP_FIX_BUDGET = 20;
401
401
  /**
402
402
  * One bounded correction round for a group whose check just failed: the exact
403
403
  * output plus host-read excerpts around every reported file:line, the group's
@@ -465,7 +465,7 @@ async function fixGroupInPlace(env, group, output, budget, evidence, extraTools,
465
465
  return [...new Set(written)];
466
466
  }
467
467
  /** Test files among `reported` that the repository's own test command (per root) does not execute; empty when no command is detected. */
468
- export function unreachedGroupTests(roots, reported) {
468
+ function unreachedGroupTests(roots, reported) {
469
469
  return roots.flatMap(root => { const check = detectCheckCommand(root); return check ? unreachedTestFiles(root, [check], reported) : []; });
470
470
  }
471
471
  /** A source file that exists but carries no implementation: a handful of lines, a placeholder import, or only TODOs. */
@@ -820,4 +820,3 @@ export async function runCompactDeveloper(env, options = {}) {
820
820
  const structured = { summary: summaries.join('\n'), files: [...files], tests: [...tests], verification: verification.length ? verification.join('; ') : 'none', incomplete };
821
821
  return { text: JSON.stringify(structured), usage: env.client.usage, structured };
822
822
  }
823
- //# sourceMappingURL=developer.js.map
@@ -1,11 +1,11 @@
1
1
  import type { spawnSync } from 'node:child_process';
2
- export interface EnvironmentInstall {
2
+ interface EnvironmentInstall {
3
3
  ecosystem: 'node' | 'python' | 'go' | 'rust';
4
4
  root: string;
5
5
  command: string;
6
6
  args: string[];
7
7
  }
8
- export interface InstallOutcome extends EnvironmentInstall {
8
+ interface InstallOutcome extends EnvironmentInstall {
9
9
  ok: boolean;
10
10
  detail: string;
11
11
  }
@@ -17,8 +17,6 @@ export declare function suggestedPackages(output: string): string[];
17
17
  export declare function missingNodeDependencies(root: string): string[];
18
18
  /** The installs a repository root needs, judged from its manifests and the absence of their install output. */
19
19
  export declare function plannedInstalls(root: string, failureOutput?: string): EnvironmentInstall[];
20
- /** Rewrites an exact, unpublished version in package.json to `^<major>.0.0`; true when something changed. */
21
- export declare function relaxManifestPin(root: string, name: string, version: string): boolean;
22
20
  /** Runs each planned install once, bounded; never throws. */
23
21
  export declare function installEnvironment(roots: readonly string[], io?: {
24
22
  spawn?: typeof spawnSync;
@@ -37,7 +35,7 @@ export declare function detectCheckCommand(root: string): {
37
35
  command: string;
38
36
  args: string[];
39
37
  } | undefined;
40
- export interface GroupCheckOutcome {
38
+ interface GroupCheckOutcome {
41
39
  ran: boolean;
42
40
  ok: boolean;
43
41
  command?: string;
@@ -60,3 +58,4 @@ export declare function runGroupCheck(roots: readonly string[], io?: {
60
58
  text?: string;
61
59
  }) => void;
62
60
  }): GroupCheckOutcome;
61
+ export {};
@@ -89,7 +89,7 @@ export function plannedInstalls(root, failureOutput = '') {
89
89
  return plans;
90
90
  }
91
91
  /** Rewrites an exact, unpublished version in package.json to `^<major>.0.0`; true when something changed. */
92
- export function relaxManifestPin(root, name, version) {
92
+ function relaxManifestPin(root, name, version) {
93
93
  const file = path.join(root, 'package.json');
94
94
  let manifest;
95
95
  try {
@@ -210,4 +210,3 @@ export function runGroupCheck(roots, io = {}) {
210
210
  }
211
211
  return { ran: false, ok: true, output: '' };
212
212
  }
213
- //# sourceMappingURL=environment.js.map
@@ -1,4 +1,4 @@
1
- export interface ExitHonestyFinding {
1
+ interface ExitHonestyFinding {
2
2
  command: string;
3
3
  failures: number | null;
4
4
  sample: string;
@@ -6,3 +6,4 @@ export interface ExitHonestyFinding {
6
6
  /** A failure count in a runner summary, or a failure-marker line, despite exit 0. */
7
7
  export declare function exitCodeContradiction(exitCode: number | null, output: string): ExitHonestyFinding | null;
8
8
  export declare function exitHonestyReason(findings: ReadonlyArray<ExitHonestyFinding>): string;
9
+ export {};
@@ -75,4 +75,3 @@ export function exitHonestyReason(findings) {
75
75
  const parts = findings.map(item => `\`${item.command}\` exited 0 but its output reports ${item.failures !== null ? `${item.failures} failing test${item.failures === 1 ? '' : 's'}` : 'a failure'} (${JSON.stringify(item.sample)})`);
76
76
  return `The verification command passed by exit code while reporting failures: ${parts.join('; ')}. A test runner that does not exit non-zero on failure hides broken tests: make the harness set \`process.exitCode = 1\` (or throw) when any test fails, then fix the failing tests.`;
77
77
  }
78
- //# sourceMappingURL=exit-code-honesty.js.map
@@ -1,11 +1,7 @@
1
1
  import { type AgentEvent } from '../executor-types.js';
2
2
  import { type ChatClient, type ChatMessage } from './chat-client.js';
3
3
  export declare const DEFAULT_CONTEXT_WINDOW_TOKENS = 32768;
4
- /** Consecutive identical calls answered with an error instead of executing. */
5
- export declare const REPEAT_WARN_AT = 3;
6
- /** Total identical calls that abort the step. */
7
- export declare const REPEAT_ABORT_AT = 5;
8
- export interface ToolLoopOptions {
4
+ interface ToolLoopOptions {
9
5
  client: ChatClient;
10
6
  /** Mutated in place: assistant, tool and nudge messages are appended. */
11
7
  messages: ChatMessage[];
@@ -34,25 +30,12 @@ export interface ToolLoopOptions {
34
30
  extraCalls: number;
35
31
  };
36
32
  }
37
- /** Default output budget of one tool turn. A tool turn should emit a tool call or a short reply, so this is a runaway guard, not a ceiling for real work; a connection whose model thinks privately (that counts against `max_tokens`) raises it with `maxOutputTokens`. */
38
- export declare const TOOL_TURN_MAX_OUTPUT = 8192;
39
- /**
40
- * `max_tokens` counts INSIDE the context window (prompt + output ≤ window), so
41
- * a budget wider than what remains makes llama.cpp refuse the request
42
- * ("exceeds the available context size") instead of helping. Bound every
43
- * request to the room actually left; never below a minimal useful reply.
44
- */
45
- export declare function boundedOutputBudget(requested: number, contextWindowTokens: number, messages: readonly ChatMessage[]): number;
46
- /** Consecutive rewrites of one path (no other tool call between them) before the loop refuses the next one. */
47
- export declare const REWRITE_WARN_AT = 3;
48
33
  export interface ToolLoopResult {
49
34
  text: string;
50
35
  toolCalls: number;
51
36
  }
52
37
  /** Estimated tokens for the transcript: chars/4, which is what small local servers count against. */
53
38
  export declare function estimateTokens(messages: ChatMessage[]): number;
54
- /** One correct example the model can copy when its arguments were rejected. */
55
- export declare function toolExample(name: string): string;
56
39
  /** Schema-level argument repair: returns the error the model receives instead of executing. */
57
40
  export declare function validateToolArguments(name: string, raw: string, available: Set<string>): {
58
41
  args: Record<string, unknown>;
@@ -71,3 +54,4 @@ export declare function compactMessages(messages: ChatMessage[], contextWindowTo
71
54
  * context compaction against the provider's window.
72
55
  */
73
56
  export declare function runToolLoop(options: ToolLoopOptions): Promise<ToolLoopResult>;
57
+ export {};
@@ -4,15 +4,15 @@ import { AgentExecutionError } from '../executor-types.js';
4
4
  import { record } from './chat-client.js';
5
5
  export const DEFAULT_CONTEXT_WINDOW_TOKENS = 32_768;
6
6
  /** Consecutive identical calls answered with an error instead of executing. */
7
- export const REPEAT_WARN_AT = 3;
7
+ const REPEAT_WARN_AT = 3;
8
8
  /** Total identical calls that abort the step. */
9
- export const REPEAT_ABORT_AT = 5;
9
+ const REPEAT_ABORT_AT = 5;
10
10
  const COMPACTION_RATIO = 0.7;
11
11
  const PROTECTED_TAIL = 4;
12
12
  const PLACEHOLDER_QUERIES = new Set(['.', '*', '**', '.*', '..', '?', 'query', '<query>']);
13
13
  const NUDGE = 'Your reply was empty. Reply with the final result now, as requested; do not call tools.';
14
14
  /** Default output budget of one tool turn. A tool turn should emit a tool call or a short reply, so this is a runaway guard, not a ceiling for real work; a connection whose model thinks privately (that counts against `max_tokens`) raises it with `maxOutputTokens`. */
15
- export const TOOL_TURN_MAX_OUTPUT = 8192;
15
+ const TOOL_TURN_MAX_OUTPUT = 8192;
16
16
  /** Headroom kept between the transcript and the context window when bounding an output budget. */
17
17
  const OUTPUT_HEADROOM_TOKENS = 512;
18
18
  /**
@@ -21,7 +21,7 @@ const OUTPUT_HEADROOM_TOKENS = 512;
21
21
  * ("exceeds the available context size") instead of helping. Bound every
22
22
  * request to the room actually left; never below a minimal useful reply.
23
23
  */
24
- export function boundedOutputBudget(requested, contextWindowTokens, messages) {
24
+ function boundedOutputBudget(requested, contextWindowTokens, messages) {
25
25
  const remaining = contextWindowTokens - estimateTokens(messages) - OUTPUT_HEADROOM_TOKENS;
26
26
  return Math.max(256, Math.min(requested, remaining));
27
27
  }
@@ -29,7 +29,7 @@ const EFFORT_STEP_DOWN = { high: 'medium', medium: 'low' };
29
29
  /** Tools whose result is a pure function of the workspace: safe to answer a repeated call with a pointer to the earlier identical result. */
30
30
  const READ_TOOLS = new Set(['read_file', 'read_lines', 'search_text', 'get_diff', 'list_files']);
31
31
  /** Consecutive rewrites of one path (no other tool call between them) before the loop refuses the next one. */
32
- export const REWRITE_WARN_AT = 3;
32
+ const REWRITE_WARN_AT = 3;
33
33
  /** Whole-file rewrites only: iterating a file with apply_patch between reads is the normal edit flow. */
34
34
  const WRITE_TOOLS = new Set(['write_file']);
35
35
  /** The rewrite streak keys on the file NAME: a model alternating `tests/x.test.js` with an invented `repo/tests/x.test.js` (observed, 7 rewrites) is still rewriting one file. */
@@ -58,7 +58,7 @@ export function estimateTokens(messages) {
58
58
  return Math.ceil(messages.reduce((total, message) => total + JSON.stringify(message).length, 0) / 4);
59
59
  }
60
60
  /** One correct example the model can copy when its arguments were rejected. */
61
- export function toolExample(name) {
61
+ function toolExample(name) {
62
62
  switch (name) {
63
63
  case 'search_text': return '{"path":".","query":"functionName"}';
64
64
  case 'read_lines': return '{"path":"src/index.ts","startLine":1,"endLine":120}';
@@ -235,7 +235,7 @@ export async function runToolLoop(options) {
235
235
  options.onToolCall?.();
236
236
  calls.set(item.id, { name: item.name, args: item.arguments });
237
237
  options.onEvent?.(toolEvent(item.name, item.arguments));
238
- const key = item.name + '' + item.arguments.replace(/\s+/g, '');
238
+ const key = item.name + '\0' + item.arguments.replace(/\s+/g, '');
239
239
  consecutive = key === previous ? consecutive + 1 : 1;
240
240
  previous = key;
241
241
  const total = (totals.get(key) ?? 0) + 1;
@@ -317,4 +317,3 @@ export async function runToolLoop(options) {
317
317
  }
318
318
  throw new AgentExecutionError(`Agent exhausted ${options.maxTurns} turns without a final result`, 'max_turns', client.usage);
319
319
  }
320
- //# sourceMappingURL=guarded-loop.js.map
@@ -36,7 +36,5 @@ export interface PromptInputs {
36
36
  status: 'added' | 'changed' | 'deleted';
37
37
  }>;
38
38
  }
39
- /** Text of one `## Heading` section up to the next heading (or terminator), without the heading line. */
40
- export declare function section(prompt: string, heading: string): string;
41
39
  export declare function bounded(text: string, limit: number): string;
42
40
  export declare function extractPromptInputs(prompt: string): PromptInputs;
@@ -1,7 +1,7 @@
1
1
  import { RE_REVIEW_MARKER } from '../prompts.js';
2
2
  const STOP = /^(## |Planning policy:|Current frozen acceptance obligations)/;
3
3
  /** Text of one `## Heading` section up to the next heading (or terminator), without the heading line. */
4
- export function section(prompt, heading) {
4
+ function section(prompt, heading) {
5
5
  const lines = prompt.split('\n');
6
6
  const start = lines.findIndex(line => line.trim() === heading);
7
7
  if (start < 0)
@@ -56,4 +56,3 @@ export function extractPromptInputs(prompt) {
56
56
  reReviewChanges: parseReReviewChanges(prompt),
57
57
  };
58
58
  }
59
- //# sourceMappingURL=prompt-inputs.js.map
@@ -1,18 +1,5 @@
1
1
  import type { AgentResult } from '../executor-types.js';
2
2
  import { type CompactEnv } from './step.js';
3
- /** Tool calls the reviewer may spend inspecting beyond the supplied diff. */
4
- export declare const DEFAULT_REVIEW_TOOL_BUDGET = 15;
5
- /** A re-review only opens the changed files. */
6
- export declare const RE_REVIEW_TOOL_BUDGET = 6;
7
- /** Working-tree changes of every allowed root against HEAD, plus the content of new files, bounded. `only` restricts the diff and the new-file listing to those repository-relative paths (a re-review reads just what the fixer touched). */
8
- export declare function collectDiff(roots: string[], only?: readonly string[]): string;
9
- /** The gate thresholds the host rendered into the reviewer prompt (`score is at least N`, `aspect ≥ N`). */
10
- export declare function reviewGateThresholds(gate: string): {
11
- minScore: number;
12
- aspects: Record<string, number>;
13
- };
14
- /** Files named by the previous review's issues (`path: what must change` lines under `## Previous review`). */
15
- export declare function previousIssueFiles(feedback: string): string[];
16
3
  /**
17
4
  * The compact reviewer: the host supplies the diff and the frozen criteria, the
18
5
  * model inspects read-only within a small budget, and the verdict is forced
@@ -8,14 +8,14 @@ import { hasBinaryAssets } from './architect.js';
8
8
  import { bounded } from './prompt-inputs.js';
9
9
  import { finalJson, openspecCall, strings, text, toolStep } from './step.js';
10
10
  /** Tool calls the reviewer may spend inspecting beyond the supplied diff. */
11
- export const DEFAULT_REVIEW_TOOL_BUDGET = 15;
11
+ const DEFAULT_REVIEW_TOOL_BUDGET = 15;
12
12
  /** A re-review only opens the changed files. */
13
- export const RE_REVIEW_TOOL_BUDGET = 6;
13
+ const RE_REVIEW_TOOL_BUDGET = 6;
14
14
  const DIFF_LIMIT = 40 * 1024;
15
15
  const UNTRACKED_LIMIT = 8 * 1024;
16
16
  const MAX_UNTRACKED = 12;
17
17
  /** Working-tree changes of every allowed root against HEAD, plus the content of new files, bounded. `only` restricts the diff and the new-file listing to those repository-relative paths (a re-review reads just what the fixer touched). */
18
- export function collectDiff(roots, only) {
18
+ function collectDiff(roots, only) {
19
19
  // Pathspec magic stays enabled so openspec/ artifacts are excluded from the reviewed diff.
20
20
  const env = { ...Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.toUpperCase().startsWith('GIT_'))), GIT_OPTIONAL_LOCKS: '0' };
21
21
  const options = { encoding: 'utf8', env, windowsHide: true, timeout: 10_000, maxBuffer: 4 * 1024 * 1024 };
@@ -62,7 +62,7 @@ export function collectDiff(roots, only) {
62
62
  return sections.join('\n\n');
63
63
  }
64
64
  /** The gate thresholds the host rendered into the reviewer prompt (`score is at least N`, `aspect ≥ N`). */
65
- export function reviewGateThresholds(gate) {
65
+ function reviewGateThresholds(gate) {
66
66
  const minScore = Number(/score\` is at least (\d+)/.exec(gate)?.[1] ?? 0);
67
67
  const aspects = {};
68
68
  for (const match of gate.matchAll(/`([a-z_]+)` ≥ (\d+)/g))
@@ -70,7 +70,7 @@ export function reviewGateThresholds(gate) {
70
70
  return { minScore, aspects };
71
71
  }
72
72
  /** Files named by the previous review's issues (`path: what must change` lines under `## Previous review`). */
73
- export function previousIssueFiles(feedback) {
73
+ function previousIssueFiles(feedback) {
74
74
  const section = feedback.split('## Previous review')[1] ?? '';
75
75
  return [...new Set([...section.matchAll(/(?:^|[\s-])((?:[\w.-]+\/)*[\w.-]+\.(?:[cm]?[jt]sx?|py|go|rs|java|kt|swift|cs|rb|php|c|cc|cpp|h|hpp|vue|svelte|html|css|scss|json|ya?ml|md))(?=[\s:,;)]|$)/g)].map(match => match[1].replace(/\\/g, '/')))];
76
76
  }
@@ -175,4 +175,3 @@ export async function runCompactReviewer(env, options = {}) {
175
175
  };
176
176
  return { text: JSON.stringify(structured), usage: env.client.usage, structured };
177
177
  }
178
- //# sourceMappingURL=reviewer.js.map
@@ -26,7 +26,6 @@ export interface CompactEnv {
26
26
  }
27
27
  /** Shorthand for the guards: `on(env, 'empty-write')`. */
28
28
  export declare function on(env: Pick<CompactEnv, 'guardrails'>, id: GuardrailId): boolean;
29
- export declare const COMPACT_STANCE = "You are one step of a Specrails pipeline driven by a host program. Keep replies short and concrete. Never invent files, paths or commands: everything you state must come from the inputs or from tool results. When asked for JSON, reply with exactly one JSON object and nothing else.";
30
29
  /** One host-driven `openspec_workflow` call, visible in the host log like a model tool call. */
31
30
  export declare function openspecCall(env: CompactEnv, input: Parameters<OpenSpecTools['execute']>[0]): Promise<unknown>;
32
31
  /** A tool-less structured call with one tolerant retry; the object is validated by the caller. */
@@ -6,7 +6,7 @@ import { record } from './chat-client.js';
6
6
  import { runToolLoop } from './guarded-loop.js';
7
7
  /** Shorthand for the guards: `on(env, 'empty-write')`. */
8
8
  export function on(env, id) { return guardrailEnabled(env.guardrails, id); }
9
- export const COMPACT_STANCE = 'You are one step of a Specrails pipeline driven by a host program. Keep replies short and concrete. Never invent files, paths or commands: everything you state must come from the inputs or from tool results. When asked for JSON, reply with exactly one JSON object and nothing else.';
9
+ const COMPACT_STANCE = 'You are one step of a Specrails pipeline driven by a host program. Keep replies short and concrete. Never invent files, paths or commands: everything you state must come from the inputs or from tool results. When asked for JSON, reply with exactly one JSON object and nothing else.';
10
10
  /** One host-driven `openspec_workflow` call, visible in the host log like a model tool call. */
11
11
  export async function openspecCall(env, input) {
12
12
  env.onEvent?.(toolEvent('openspec_workflow', input));
@@ -133,4 +133,3 @@ export function strings(value, limit, each = 1000) {
133
133
  return Array.isArray(value) ? value.filter((item) => typeof item === 'string' && item.trim().length > 0).map(item => item.trim().slice(0, each)).slice(0, limit) : [];
134
134
  }
135
135
  export function text(value, fallback = '') { return typeof value === 'string' && value.trim() ? value.trim() : fallback; }
136
- //# sourceMappingURL=step.js.map
@@ -144,4 +144,3 @@ export function unreachedTestFiles(root, commands, reported) {
144
144
  export function unreachedTestsReason(files) {
145
145
  return `Test file${files.length === 1 ? '' : 's'} written by the developer ${files.length === 1 ? 'is' : 'are'} not executed by any verification command: ${files.join(', ')}. A test nobody runs proves nothing. Wire ${files.length === 1 ? 'it' : 'them'} into the repository's test command (for example the package.json "test" script) or propose a verificationCheck that runs ${files.length === 1 ? 'it' : 'them'}, then make ${files.length === 1 ? 'it' : 'them'} pass.`;
146
146
  }
147
- //# sourceMappingURL=test-reachability.js.map
@@ -290,4 +290,3 @@ export function normalizeRuntimeConfig(input, options) {
290
290
  };
291
291
  return config;
292
292
  }
293
- //# sourceMappingURL=config.js.map
@@ -1,4 +1,4 @@
1
- import { type PipelineContext } from '../installer/runtime/pipeline-state.js';
1
+ import { type PipelineContext } from '../pipeline/pipeline-state.js';
2
2
  import { type ExecutorRegistry } from './executors.js';
3
3
  import type { AgentEvent, RuntimeConfig, AgentEventRole } from './executor-types.js';
4
4
  import { parseAgentObject } from './graph/artifacts.js';
@@ -2,7 +2,7 @@ import { fingerprint } from './durable-store.js';
2
2
  import { prepareOpenSpec, roleOpenSpecContext } from './openspec.js';
3
3
  import { existsSync, readFileSync } from 'node:fs';
4
4
  import path from 'node:path';
5
- import { fingerprintCandidate, initializePipeline, inspectPipeline, pipelineStateDirectory, validatePipelineContext, validateVerificationRequest, } from '../installer/runtime/pipeline-state.js';
5
+ import { fingerprintCandidate, initializePipeline, inspectPipeline, pipelineStateDirectory, validatePipelineContext, validateVerificationRequest, } from '../pipeline/pipeline-state.js';
6
6
  import { normalizeRuntimeConfig } from './config.js';
7
7
  import { createExecutorRegistry } from './executors.js';
8
8
  import { archive, child, journal, parseAgentObject, SLUG } from './graph/artifacts.js';
@@ -114,7 +114,10 @@ export async function runCoreWorkflow(options) {
114
114
  grantedArchiveScope = archiveConsent();
115
115
  if (stepId === 'architect')
116
116
  return inspection.phases.architect.status === 'done' && inspection.resumePhase !== 'architect';
117
- if (stepId === 'verify' && checkpoint.status !== 'succeeded' && inspection.phases.archive.status !== 'done' && !(checkpoint.pendingApproval?.stepId === 'archive' && !options.approve?.includes('archive') && !checkpoint.pendingApproval.grantedAt))
117
+ // A failed deterministic archive does not itself stale verification. The
118
+ // receipt checks below still invalidate changed code, specs or environment.
119
+ const retryingArchive = checkpoint.nextStep === 'archive' && checkpoint.steps.archive?.status === 'failed';
120
+ if (stepId === 'verify' && !retryingArchive && checkpoint.status !== 'succeeded' && inspection.phases.archive.status !== 'done' && !(checkpoint.pendingApproval?.stepId === 'archive' && !options.approve?.includes('archive') && !checkpoint.pendingApproval.grantedAt))
118
121
  return false;
119
122
  if (stepId === 'verify')
120
123
  return _record.output?.valid !== false && inspection.verification.valid;
@@ -134,4 +137,3 @@ export async function runCoreWorkflow(options) {
134
137
  },
135
138
  });
136
139
  }
137
- //# sourceMappingURL=core-host.js.map
@@ -9,7 +9,6 @@ export interface WorkflowEnvelope {
9
9
  state: WorkflowState;
10
10
  graph?: SerializedGraphStore;
11
11
  }
12
- export declare const ENVELOPE_FORMAT = 2;
13
12
  /** Reject non-JSON data instead of silently changing the fingerprint on serialization. */
14
13
  export declare function fingerprint(value: unknown): string;
15
14
  export declare function readWorkflowEnvelope(directory: string, runId: string): Promise<WorkflowEnvelope | null>;
@@ -10,7 +10,7 @@ export class WorkflowStoreError extends Error {
10
10
  this.name = 'WorkflowStoreError';
11
11
  }
12
12
  }
13
- export const ENVELOPE_FORMAT = 2;
13
+ const ENVELOPE_FORMAT = 2;
14
14
  function errorCode(error) {
15
15
  return typeof error === 'object' && error !== null && 'code' in error ? String(error.code) : undefined;
16
16
  }
@@ -202,4 +202,3 @@ export async function acquireWorkflowLease(directory, runId) {
202
202
  await rm(lease, { recursive: true, force: true });
203
203
  };
204
204
  }
205
- //# sourceMappingURL=durable-store.js.map
@@ -1,4 +1,4 @@
1
- import { type PipelineContext, type PipelineCompletion } from '../installer/runtime/pipeline-state.js';
1
+ import { type PipelineContext, type PipelineCompletion } from '../pipeline/pipeline-state.js';
2
2
  import type { RuntimeConfig } from './executor-types.js';
3
3
  import type { WorkflowState } from './workflow-types.js';
4
4
  /** Compact derived view. Durable invocation/evidence IDs remain the accounting authority. */
@@ -21,7 +21,7 @@ export declare function efficiencySummary(state: WorkflowState, context: Pipelin
21
21
  runId: string;
22
22
  workflowVersion: string;
23
23
  technicalAcceptance: string;
24
- archive: import("../installer/runtime/pipeline-state.js").PhaseStatus;
24
+ archive: import("../pipeline/pipeline-state.js").PhaseStatus;
25
25
  delivery: "pending" | "complete" | "pending-host";
26
26
  roles: {
27
27
  role: "architect" | "developer" | "reviewer";
@@ -1,4 +1,4 @@
1
- import { readVerificationEvidence } from '../installer/runtime/pipeline-state.js';
1
+ import { readVerificationEvidence } from '../pipeline/pipeline-state.js';
2
2
  import { runtimeEfficiency } from './efficiency.js';
3
3
  /** Compact derived view. Durable invocation/evidence IDs remain the accounting authority. */
4
4
  export function efficiencySummary(state, context, config, completion, identity) {
@@ -49,4 +49,3 @@ export function efficiencySummary(state, context, config, completion, identity)
49
49
  metrics: runtimeEfficiency(state),
50
50
  };
51
51
  }
52
- //# sourceMappingURL=efficiency-summary.js.map
@@ -5,4 +5,3 @@ export function sumCacheUsage(values) {
5
5
  return Object.fromEntries(CACHE_TOKEN_KEYS.map(key => [key, values.some(value => value[key] == null)
6
6
  ? null : values.reduce((sum, value) => sum + (value[key] ?? 0), 0)]));
7
7
  }
8
- //# sourceMappingURL=efficiency-types.js.map
@@ -32,4 +32,3 @@ export function runtimeEfficiency(state) {
32
32
  const pending = state.history.some(attempt => attempt.pendingInvocations?.length);
33
33
  return { schemaVersion: 1, total: { ...totals(state.history), durationMs: state.usage.durationMs, inputTokens: pending ? null : state.usage.inputTokens, outputTokens: pending ? null : state.usage.outputTokens, costUsd: pending ? null : state.usage.costUsd }, phases };
34
34
  }
35
- //# sourceMappingURL=efficiency.js.map
@@ -5,4 +5,3 @@ export const EVALUATION_CORPUS = [
5
5
  { id: 'verification-correction', verification: 'assert.strictEqual(api.clamp(11, 0, 10), 10)', description: 'Clamp values to both boundaries, including an already valid value.', repositories: ['math'], source: 'exports.clamp = value => value', solution: 'exports.clamp = (value, min, max) => Math.min(max, Math.max(min, value))', defects: ['exports.clamp = (value, min, max) => Math.max(min, value)', 'exports.clamp = (value, min, max) => Math.min(max, value)'], oracle: 'assert.strictEqual(api.clamp(-1, 0, 10), 0); assert.strictEqual(api.clamp(11, 0, 10), 10); assert.strictEqual(api.clamp(5, 0, 10), 5);', correction: 'verification' },
6
6
  { id: 'review-correction', verification: 'assert.strictEqual(typeof api.unique, "function")', description: 'Deduplicate stable values while preserving the first occurrence order.', repositories: ['collections'], source: 'exports.unique = values => values', solution: 'exports.unique = values => [...new Set(values)]', defects: ['exports.unique = values => [...new Set(values)].sort()', 'exports.unique = values => values'], oracle: 'assert.deepStrictEqual(api.unique([3, 1, 3, 2, 1]), [3, 1, 2]); assert.deepStrictEqual(api.unique([]), []);', correction: 'review' },
7
7
  ];
8
- //# sourceMappingURL=evaluation-corpus.js.map
@@ -1,5 +1,5 @@
1
1
  import type { RuntimeConfig } from './executor-types.js';
2
- export interface EvaluationOptions {
2
+ interface EvaluationOptions {
3
3
  output: string;
4
4
  config?: RuntimeConfig;
5
5
  maxCostUsd?: number;
@@ -41,3 +41,4 @@ export declare function runEvaluation(options: EvaluationOptions): Promise<{
41
41
  reportedSpendUsd: number;
42
42
  observations: Record<string, unknown>[];
43
43
  }>;
44
+ export {};
@@ -8,7 +8,7 @@ import { fingerprint } from './durable-store.js';
8
8
  import { runCoreWorkflow, coreRuntimeIdentity } from './core-host.js';
9
9
  import { ExecutorRegistry } from './executors.js';
10
10
  import { OpenSpecTools } from './openspec.js';
11
- import { validatePipelineContext } from '../installer/runtime/pipeline-state.js';
11
+ import { validatePipelineContext } from '../pipeline/pipeline-state.js';
12
12
  import { runtimeEfficiency } from './efficiency.js';
13
13
  function oracle(test, file) {
14
14
  return spawnSync(process.execPath, ['-e', 'const assert = require("node:assert/strict"); const api = require(process.argv[1]);' + test.oracle, file], { encoding: 'utf8', timeout: 10000 }).status === 0;
@@ -168,4 +168,3 @@ export async function runEvaluation(options) {
168
168
  rmSync(root, { recursive: true, force: true });
169
169
  }
170
170
  }
171
- //# sourceMappingURL=evaluation.js.map
@@ -1,4 +1,4 @@
1
- import type { VerificationCommand } from '../installer/runtime/pipeline-state.js';
1
+ import type { VerificationCommand } from '../pipeline/pipeline-state.js';
2
2
  import type { CacheTokenUsage } from './efficiency-types.js';
3
3
  import type { GuardrailSettings } from './guardrails.js';
4
4
  export declare const DEFAULT_AGENT_TIMEOUT_MS: number;
@@ -31,4 +31,3 @@ export function validateAgentRequest(request) {
31
31
  if (request.signal?.aborted)
32
32
  throw new AgentExecutionError('Agent cancelled', 'aborted');
33
33
  }
34
- //# sourceMappingURL=executor-types.js.map
@@ -45,4 +45,3 @@ export function createExecutorRegistry(input, options = {}) {
45
45
  registry.register(id, executor);
46
46
  return registry;
47
47
  }
48
- //# sourceMappingURL=executors.js.map
@@ -33,4 +33,3 @@ export function assertGeminiAdminPolicyAvailable(options = {}) {
33
33
  if (entries.some(file => file.endsWith('.toml')))
34
34
  throw new AgentExecutionError('Gemini system policies disable per-run admin policy enforcement. Select another provider for architect/reviewer, or ask the system administrator to configure a compatible environment: ' + directory, 'provider_capability_unsupported');
35
35
  }
36
- //# sourceMappingURL=gemini-policy.js.map
@@ -1,4 +1,4 @@
1
- import { type PipelineContext, type PipelineState, type VerificationCommand } from '../../installer/runtime/pipeline-state.js';
1
+ import { type PipelineContext, type PipelineState, type VerificationCommand } from '../../pipeline/pipeline-state.js';
2
2
  import type { DesignConfidence } from './state.js';
3
3
  export declare const SLUG: RegExp;
4
4
  export declare function object(value: unknown): Record<string, unknown>;
@@ -2,7 +2,7 @@ import { artifactPath, hash, resolveOpenSpecCli, runOpenSpec } from '../openspec
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import path from 'node:path';
5
- import { checkArchive, pipelineStateDirectory, transitionPipeline, validateVerificationRequest, } from '../../installer/runtime/pipeline-state.js';
5
+ import { checkArchive, pipelineStateDirectory, transitionPipeline, validateVerificationRequest, } from '../../pipeline/pipeline-state.js';
6
6
  export const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
7
7
  export function object(value) {
8
8
  if (!value || typeof value !== 'object' || Array.isArray(value))
@@ -134,10 +134,17 @@ async function archiveWithOpenSpec(context, change, active, signal) {
134
134
  const source = artifactPath(context.artifactRoot, 'openspec');
135
135
  files(source); // Reject symlinks before copying or invoking the external CLI.
136
136
  cpSync(source, path.join(staging, 'openspec'), { recursive: true });
137
- await runOpenSpec(resolveOpenSpecCli(), staging, ['archive', change, '--yes'], signal);
138
- const archives = readdirSync(path.join(staging, 'openspec/changes/archive')).filter(name => name.endsWith('-' + change));
137
+ const output = await runOpenSpec(resolveOpenSpecCli(), staging, ['archive', change, '--yes'], signal);
138
+ const archiveRoot = path.join(staging, 'openspec/changes/archive');
139
+ const archives = existsSync(archiveRoot) ? readdirSync(archiveRoot).filter(name => name.endsWith('-' + change)) : [];
140
+ // OpenSpec can abort validation while exiting 0. Preserve its explanation;
141
+ // process success alone is not an archive receipt.
142
+ if (archives.length === 0)
143
+ throw new Error(`OpenSpec did not create an archive for ${change}. Repair the reported cause before resuming.\n${output.slice(-6000)}`);
139
144
  if (archives.length !== 1)
140
- throw new Error('OpenSpec archive destination is ambiguous');
145
+ throw new Error(`OpenSpec archive has multiple destinations for ${change}: ${archives.join(', ')}.\n${output.slice(-6000)}`);
146
+ if (existsSync(path.join(staging, 'openspec/changes', change)))
147
+ throw new Error(`OpenSpec left the active change in place; archive was not completed.\n${output.slice(-6000)}`);
141
148
  const destination = 'openspec/changes/archive/' + archives[0];
142
149
  if (existsSync(artifactPath(context.artifactRoot, destination)))
143
150
  throw new Error('OpenSpec archive destination already exists');
@@ -202,4 +209,3 @@ export async function archive(context, change, signal) {
202
209
  transitionPipeline(context, 'ci', 'skipped');
203
210
  }
204
211
  }
205
- //# sourceMappingURL=artifacts.js.map
@@ -1,5 +1,5 @@
1
1
  import { type OpenSpecRoleContext } from '../openspec.js';
2
- import { type AcceptanceReport, type PipelineContext } from '../../installer/runtime/pipeline-state.js';
2
+ import { type AcceptanceReport, type PipelineContext } from '../../pipeline/pipeline-state.js';
3
3
  import type { AgentEventRole, AgentResult, AgentRole, RuntimeConfig } from '../executor-types.js';
4
4
  import { type FrozenCriterion } from '../prompts.js';
5
5
  import type { WorkflowNode, WorkflowState } from '../workflow-types.js';