specrails-core 5.3.0 → 5.4.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 (117) hide show
  1. package/dist/agent-runtime/capabilities.d.ts +27 -0
  2. package/dist/agent-runtime/capabilities.js +73 -0
  3. package/dist/agent-runtime/capabilities.js.map +1 -0
  4. package/dist/agent-runtime/cli-executor.d.ts +9 -0
  5. package/dist/agent-runtime/cli-executor.js +100 -30
  6. package/dist/agent-runtime/cli-executor.js.map +1 -1
  7. package/dist/agent-runtime/cli.d.ts +1 -0
  8. package/dist/agent-runtime/cli.js +59 -11
  9. package/dist/agent-runtime/cli.js.map +1 -1
  10. package/dist/agent-runtime/codex-schema.d.ts +4 -0
  11. package/dist/agent-runtime/codex-schema.js +31 -0
  12. package/dist/agent-runtime/codex-schema.js.map +1 -0
  13. package/dist/agent-runtime/config.d.ts +4 -0
  14. package/dist/agent-runtime/config.js +110 -9
  15. package/dist/agent-runtime/config.js.map +1 -1
  16. package/dist/agent-runtime/core-host.d.ts +9 -1
  17. package/dist/agent-runtime/core-host.js +55 -20
  18. package/dist/agent-runtime/core-host.js.map +1 -1
  19. package/dist/agent-runtime/efficiency-summary.d.ts +67 -0
  20. package/dist/agent-runtime/efficiency-summary.js +52 -0
  21. package/dist/agent-runtime/efficiency-summary.js.map +1 -0
  22. package/dist/agent-runtime/efficiency-types.d.ts +60 -0
  23. package/dist/agent-runtime/efficiency-types.js +8 -0
  24. package/dist/agent-runtime/efficiency-types.js.map +1 -0
  25. package/dist/agent-runtime/efficiency.d.ts +5 -0
  26. package/dist/agent-runtime/efficiency.js +35 -0
  27. package/dist/agent-runtime/efficiency.js.map +1 -0
  28. package/dist/agent-runtime/evaluation-corpus.d.ts +13 -0
  29. package/dist/agent-runtime/evaluation-corpus.js +8 -0
  30. package/dist/agent-runtime/evaluation-corpus.js.map +1 -0
  31. package/dist/agent-runtime/evaluation.d.ts +43 -0
  32. package/dist/agent-runtime/evaluation.js +171 -0
  33. package/dist/agent-runtime/evaluation.js.map +1 -0
  34. package/dist/agent-runtime/executor-types.d.ts +35 -2
  35. package/dist/agent-runtime/executor-types.js.map +1 -1
  36. package/dist/agent-runtime/executors.d.ts +1 -0
  37. package/dist/agent-runtime/executors.js +4 -0
  38. package/dist/agent-runtime/executors.js.map +1 -1
  39. package/dist/agent-runtime/graph/artifacts.d.ts +8 -22
  40. package/dist/agent-runtime/graph/artifacts.js +99 -73
  41. package/dist/agent-runtime/graph/artifacts.js.map +1 -1
  42. package/dist/agent-runtime/graph/nodes.d.ts +3 -0
  43. package/dist/agent-runtime/graph/nodes.js +73 -26
  44. package/dist/agent-runtime/graph/nodes.js.map +1 -1
  45. package/dist/agent-runtime/graph/roles.d.ts +4 -1
  46. package/dist/agent-runtime/graph/roles.js +100 -36
  47. package/dist/agent-runtime/graph/roles.js.map +1 -1
  48. package/dist/agent-runtime/graph/state.d.ts +8 -0
  49. package/dist/agent-runtime/graph/state.js.map +1 -1
  50. package/dist/agent-runtime/index.d.ts +7 -1
  51. package/dist/agent-runtime/index.js +7 -1
  52. package/dist/agent-runtime/index.js.map +1 -1
  53. package/dist/agent-runtime/kimi-acp.d.ts +4 -0
  54. package/dist/agent-runtime/kimi-acp.js +20 -9
  55. package/dist/agent-runtime/kimi-acp.js.map +1 -1
  56. package/dist/agent-runtime/openai-executor.d.ts +8 -0
  57. package/dist/agent-runtime/openai-executor.js +28 -10
  58. package/dist/agent-runtime/openai-executor.js.map +1 -1
  59. package/dist/agent-runtime/openspec-tool-server.d.ts +1 -0
  60. package/dist/agent-runtime/openspec-tool-server.js +37 -0
  61. package/dist/agent-runtime/openspec-tool-server.js.map +1 -0
  62. package/dist/agent-runtime/openspec.d.ts +123 -0
  63. package/dist/agent-runtime/openspec.js +263 -0
  64. package/dist/agent-runtime/openspec.js.map +1 -0
  65. package/dist/agent-runtime/prompts.d.ts +5 -1
  66. package/dist/agent-runtime/prompts.js +59 -40
  67. package/dist/agent-runtime/prompts.js.map +1 -1
  68. package/dist/agent-runtime/provider-diagnostic.d.ts +2 -0
  69. package/dist/agent-runtime/provider-diagnostic.js +25 -0
  70. package/dist/agent-runtime/provider-diagnostic.js.map +1 -0
  71. package/dist/agent-runtime/repository-context.d.ts +25 -0
  72. package/dist/agent-runtime/repository-context.js +100 -0
  73. package/dist/agent-runtime/repository-context.js.map +1 -0
  74. package/dist/agent-runtime/review-context.d.ts +14 -0
  75. package/dist/agent-runtime/review-context.js +41 -0
  76. package/dist/agent-runtime/review-context.js.map +1 -0
  77. package/dist/agent-runtime/role-routing.d.ts +10 -0
  78. package/dist/agent-runtime/role-routing.js +29 -0
  79. package/dist/agent-runtime/role-routing.js.map +1 -0
  80. package/dist/agent-runtime/role-state.d.ts +19 -0
  81. package/dist/agent-runtime/role-state.js +24 -0
  82. package/dist/agent-runtime/role-state.js.map +1 -0
  83. package/dist/agent-runtime/runtime-identity.d.ts +11 -0
  84. package/dist/agent-runtime/runtime-identity.js +33 -0
  85. package/dist/agent-runtime/runtime-identity.js.map +1 -0
  86. package/dist/agent-runtime/tool-event.d.ts +3 -0
  87. package/dist/agent-runtime/tool-event.js +24 -0
  88. package/dist/agent-runtime/tool-event.js.map +1 -0
  89. package/dist/agent-runtime/verification-plan.d.ts +55 -0
  90. package/dist/agent-runtime/verification-plan.js +206 -0
  91. package/dist/agent-runtime/verification-plan.js.map +1 -0
  92. package/dist/agent-runtime/workflow-types.d.ts +17 -1
  93. package/dist/agent-runtime/workflow.js +28 -1
  94. package/dist/agent-runtime/workflow.js.map +1 -1
  95. package/dist/agent-runtime/workspace-tools.d.ts +4 -0
  96. package/dist/agent-runtime/workspace-tools.js +182 -20
  97. package/dist/agent-runtime/workspace-tools.js.map +1 -1
  98. package/dist/installer/phases/scaffold.js +39 -109
  99. package/dist/installer/phases/scaffold.js.map +1 -1
  100. package/dist/installer/runtime/pipeline-state.d.ts +142 -1
  101. package/dist/installer/runtime/pipeline-state.js +477 -28
  102. package/dist/installer/runtime/pipeline-state.js.map +1 -1
  103. package/docs/agent-runtime-efficiency.md +65 -0
  104. package/docs/agent-runtime.md +86 -15
  105. package/integration-contract.json +2 -1
  106. package/package.json +5 -2
  107. package/schemas/agent-runtime.schema.json +25 -3
  108. package/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
  109. package/templates/codex-skills/batch-implement/SKILL.md +33 -58
  110. package/templates/codex-skills/implement/SKILL.md +21 -124
  111. package/templates/codex-skills/retry/SKILL.md +8 -34
  112. package/templates/commands/specrails/batch-implement.md +21 -16
  113. package/templates/commands/specrails/implement.md +17 -276
  114. package/templates/commands/specrails/retry.md +6 -34
  115. package/templates/gemini-commands/batch-implement.toml +34 -28
  116. package/templates/gemini-commands/implement.toml +34 -55
  117. package/templates/gemini-commands/retry.toml +10 -16
@@ -0,0 +1,19 @@
1
+ import type { AgentRole } from './executor-types.js';
2
+ import type { RepositoryContextSnapshot } from './repository-context.js';
3
+ export interface RoleSession {
4
+ identity: string;
5
+ sessionId: string;
6
+ context: RepositoryContextSnapshot;
7
+ }
8
+ export interface RoleExecutionState {
9
+ sessions: Partial<Record<AgentRole, RoleSession>>;
10
+ routes: Partial<Record<AgentRole, {
11
+ tier: 'base' | 'escalation';
12
+ reason: string;
13
+ attemptId: string;
14
+ }>>;
15
+ }
16
+ /** Host-owned auxiliary state lives under the workflow's existing run lease.
17
+ * A corrupted packet fails explicitly; it is never used as missing context. */
18
+ export declare function readRoleState(directory: string): RoleExecutionState;
19
+ export declare function writeRoleState(directory: string, data: RoleExecutionState): void;
@@ -0,0 +1,24 @@
1
+ import { existsSync, readFileSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fingerprint } from './durable-store.js';
4
+ import { write } from './graph/artifacts.js';
5
+ /** Host-owned auxiliary state lives under the workflow's existing run lease.
6
+ * A corrupted packet fails explicitly; it is never used as missing context. */
7
+ export function readRoleState(directory) {
8
+ const file = path.join(directory, 'role-execution.json');
9
+ if (!existsSync(file))
10
+ return { sessions: {}, routes: {} };
11
+ if (statSync(file).size > 2 * 1024 * 1024)
12
+ throw new Error('Role execution state exceeds its size limit');
13
+ const envelope = JSON.parse(readFileSync(file, 'utf8'));
14
+ if (envelope.schemaVersion !== 1 || envelope.checksum !== fingerprint(envelope.data) || !envelope.data?.sessions || !envelope.data?.routes)
15
+ throw new Error('Role execution state failed its integrity check');
16
+ return envelope.data;
17
+ }
18
+ export function writeRoleState(directory, data) {
19
+ const content = JSON.stringify({ schemaVersion: 1, checksum: fingerprint(data), data }) + '\n';
20
+ if (Buffer.byteLength(content) > 2 * 1024 * 1024)
21
+ throw new Error('Role execution state exceeds its size limit');
22
+ write(path.join(directory, 'role-execution.json'), content);
23
+ }
24
+ //# sourceMappingURL=role-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-state.js","sourceRoot":"","sources":["../../src/agent-runtime/role-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAa5C;+EAC+E;AAC/E,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;IACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAC1D,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IACzG,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,aAAa,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,KAAK,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IAC9M,OAAO,QAAQ,CAAC,IAA0B,CAAA;AAC5C,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,IAAwB;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IAC9F,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;IAChH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7D,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface RuntimeIdentity {
2
+ packageVersion: string;
3
+ workflowVersion: string;
4
+ instructionsVersion: string;
5
+ packageIntegrity: string;
6
+ apiVersion: 1;
7
+ }
8
+ /** Hash the executable package, not a mutable path or its advertised version.
9
+ * Dependencies are retained/verified by the host package snapshot separately. */
10
+ export declare function runtimePackageIntegrity(root?: string): string;
11
+ export declare function sameRuntimeIdentity(left: RuntimeIdentity, right: RuntimeIdentity): boolean;
@@ -0,0 +1,33 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ /** Hash the executable package, not a mutable path or its advertised version.
6
+ * Dependencies are retained/verified by the host package snapshot separately. */
7
+ export function runtimePackageIntegrity(root = fileURLToPath(new URL('../../', import.meta.url))) {
8
+ const hash = createHash('sha256');
9
+ const visit = (relative) => {
10
+ const file = path.join(root, relative);
11
+ const stat = lstatSync(file);
12
+ if (stat.isSymbolicLink())
13
+ throw new Error('Runtime package contains an unsupported symbolic link: ' + relative);
14
+ if (stat.isDirectory()) {
15
+ for (const name of readdirSync(file).sort())
16
+ visit(path.posix.join(relative, name));
17
+ }
18
+ else if (stat.isFile()) {
19
+ hash.update(JSON.stringify([relative, stat.size])).update('\0').update(readFileSync(file)).update('\0');
20
+ }
21
+ else
22
+ throw new Error('Runtime package contains a nonregular file: ' + relative);
23
+ };
24
+ for (const entry of ['package.json', 'dist', 'bin', 'templates', 'schemas', 'commands', 'integration-contract.json', 'pinned-versions.json']) {
25
+ if (existsSync(path.join(root, entry)))
26
+ visit(entry);
27
+ }
28
+ return 'sha256:' + hash.digest('hex');
29
+ }
30
+ export function sameRuntimeIdentity(left, right) {
31
+ return ['packageVersion', 'workflowVersion', 'instructionsVersion', 'packageIntegrity', 'apiVersion'].every(key => left[key] === right[key]);
32
+ }
33
+ //# sourceMappingURL=runtime-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-identity.js","sourceRoot":"","sources":["../../src/agent-runtime/runtime-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AASxC;iFACiF;AACjF,MAAM,UAAU,uBAAuB,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAQ,EAAE;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,IAAI,CAAC,cAAc,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,GAAG,QAAQ,CAAC,CAAA;QAChH,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;QACrF,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACzG,CAAC;;YAAM,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,QAAQ,CAAC,CAAA;IACnF,CAAC,CAAA;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,2BAA2B,EAAE,sBAAsB,CAAC,EAAE,CAAC;QAC7I,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAqB,EAAE,KAAsB;IAC/E,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAA4B,CAAC,KAAK,KAAK,CAAC,GAA4B,CAAC,CAAC,CAAA;AAChM,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AgentEvent } from './executor-types.js';
2
+ /** Short, human-readable tool activity for host logs; never a transcript. */
3
+ export declare function toolEvent(tool: string, input: unknown): AgentEvent;
@@ -0,0 +1,24 @@
1
+ function object(value) { return value && typeof value === 'object' && !Array.isArray(value) ? value : {}; }
2
+ function shorten(value, limit = 160) {
3
+ if (typeof value !== 'string' || !value.trim())
4
+ return undefined;
5
+ const single = value.replace(/\s+/g, ' ').trim();
6
+ return single.length > limit ? single.slice(0, limit - 1) + '…' : single;
7
+ }
8
+ /** Short, human-readable tool activity for host logs; never a transcript. */
9
+ export function toolEvent(tool, input) {
10
+ if (typeof input === 'string') {
11
+ try {
12
+ input = JSON.parse(input);
13
+ }
14
+ catch {
15
+ input = {};
16
+ }
17
+ }
18
+ const args = object(input);
19
+ const detail = shorten(args.file_path ?? args.path ?? (Array.isArray(args.paths) ? args.paths[0] : undefined) ?? args.command ?? args.pattern ?? args.query ?? args.notebook_path ?? args.url ?? (typeof args.action === 'string' ? [args.action, args.artifact].filter(Boolean).join(' ') : undefined));
20
+ const targetPaths = [args.file_path, args.path, args.notebook_path, ...(Array.isArray(args.paths) ? args.paths : [])].filter((value) => typeof value === 'string' && value.length > 0);
21
+ const cwd = args.workdir ?? args.cwd;
22
+ return { kind: 'tool-start', tool, ...(detail ? { detail } : {}), ...(targetPaths.length ? { targetPaths } : {}), ...(typeof cwd === 'string' ? { cwd } : {}) };
23
+ }
24
+ //# sourceMappingURL=tool-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-event.js","sourceRoot":"","sources":["../../src/agent-runtime/tool-event.ts"],"names":[],"mappings":"AACA,SAAS,MAAM,CAAC,KAAc,IAA6B,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAgC,CAAC,CAAC,CAAC,EAAE,CAAA,CAAC,CAAC;AACvK,SAAS,OAAO,CAAC,KAAc,EAAE,KAAK,GAAG,GAAG;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,OAAO,SAAS,CAAA;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAChD,OAAO,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAA;AAC1E,CAAC;AACD,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAc;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAAC,IAAI,CAAC;YAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,KAAK,GAAG,EAAE,CAAA;QAAC,CAAC;IAAC,CAAC;IACzF,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;IACxS,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACvM,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAA;IACpC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;AACjK,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { type PipelineContext, type VerificationCommand } from '../installer/runtime/pipeline-state.js';
2
+ export interface ProposedCheck {
3
+ kind: 'command' | 'harness';
4
+ key: string;
5
+ repositoryId: string;
6
+ label: string;
7
+ command: string;
8
+ args: string[];
9
+ cwd?: string;
10
+ timeoutMs?: number;
11
+ entrypoint?: string;
12
+ files?: Array<{
13
+ path: string;
14
+ content: string;
15
+ }>;
16
+ }
17
+ export interface HarnessSource {
18
+ path: string;
19
+ hash: string;
20
+ byteCount: number;
21
+ }
22
+ export interface PlanEntry {
23
+ id: string;
24
+ key: string;
25
+ label: string;
26
+ origins: Array<'host' | 'architect' | 'developer'>;
27
+ command: VerificationCommand;
28
+ harness?: {
29
+ hash: string;
30
+ entrypoint: string;
31
+ sources: HarnessSource[];
32
+ };
33
+ }
34
+ export interface VerificationPlan {
35
+ schemaVersion: 1;
36
+ runId: string;
37
+ revision: number;
38
+ planHash: string;
39
+ integrity: string;
40
+ scopeHash: string;
41
+ executionPolicy: {
42
+ maxConcurrency: number;
43
+ };
44
+ baseline: PlanEntry[];
45
+ developer: PlanEntry[];
46
+ entries: PlanEntry[];
47
+ }
48
+ /** All declarations are validated before any source is materialized. */
49
+ export declare function validateProposedChecks(context: PipelineContext, raw: unknown): ProposedCheck[];
50
+ export declare function readVerificationPlan(context: PipelineContext): VerificationPlan | null;
51
+ export declare function initializeVerificationPlan(context: PipelineContext, host: VerificationCommand[], architect: VerificationCommand[], maxConcurrency?: number): VerificationPlan;
52
+ export declare function addDeveloperChecks(context: PipelineContext, proposals: ProposedCheck[]): VerificationPlan;
53
+ export declare function expandedPlanCommands(context: PipelineContext, plan: VerificationPlan): VerificationCommand[];
54
+ /** Bind the exact manifest and every source to lifecycle gates. */
55
+ export declare function bindPlan(context: PipelineContext, plan: VerificationPlan): void;
@@ -0,0 +1,206 @@
1
+ import { existsSync, readFileSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import { bindVerificationPlan, pipelineStateDirectory, validateVerificationRequest } from '../installer/runtime/pipeline-state.js';
5
+ import { fingerprint } from './durable-store.js';
6
+ import { child, write } from './graph/artifacts.js';
7
+ const SAFE_ID = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
8
+ const bytesHash = (text) => createHash('sha256').update(text).digest('hex');
9
+ function text(value, field, limit) {
10
+ if (typeof value !== 'string' || !value.trim() || value.includes('\0') || value.length > limit)
11
+ throw new Error('Invalid verification proposal ' + field);
12
+ return value;
13
+ }
14
+ function sourcePath(value) {
15
+ const file = text(value, 'file path', 1024);
16
+ if (/^[a-z]:/i.test(file) || path.isAbsolute(file) || file.includes('\\') || /[\x00-\x1f\x7f]/.test(file) || file.split('/').some(part => !part || part === '.' || part === '..' || /[. ]$/.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part)))
17
+ throw new Error('Invalid verification proposal file path');
18
+ return file;
19
+ }
20
+ /** All declarations are validated before any source is materialized. */
21
+ export function validateProposedChecks(context, raw) {
22
+ if (raw === undefined)
23
+ return [];
24
+ if (!Array.isArray(raw) || raw.length > 20)
25
+ throw new Error('Invalid verificationChecks: expected at most 20 checks');
26
+ let bytes = 0;
27
+ const keys = new Set();
28
+ return raw.map(value => {
29
+ if (!value || typeof value !== 'object' || Array.isArray(value))
30
+ throw new Error('Invalid verification proposal');
31
+ const check = value;
32
+ for (const key of Object.keys(check))
33
+ if (!['kind', 'key', 'repositoryId', 'label', 'command', 'args', 'cwd', 'timeoutMs', 'entrypoint', 'files'].includes(key))
34
+ throw new Error('Invalid verification proposal field: ' + key);
35
+ if (!['command', 'harness'].includes(String(check.kind)) || typeof check.key !== 'string' || !SAFE_ID.test(check.key) || keys.has(check.key))
36
+ throw new Error('Invalid or duplicate verification proposal key/kind');
37
+ keys.add(check.key);
38
+ text(check.label, 'label', 256);
39
+ text(check.command, 'command', 4096);
40
+ if (!Array.isArray(check.args) || check.args.length > 128 || check.args.some(arg => typeof arg !== 'string' || arg.includes('\0') || arg.length > 4096))
41
+ throw new Error('Invalid verification proposal args');
42
+ validateVerificationRequest(context, { kind: 'scoped', commands: [check] });
43
+ if (check.kind === 'command') {
44
+ if (check.entrypoint !== undefined || check.files !== undefined)
45
+ throw new Error('Invalid command proposal: harness fields are forbidden');
46
+ }
47
+ else {
48
+ const entrypoint = sourcePath(check.entrypoint);
49
+ if (!Array.isArray(check.files) || !check.files.length || check.files.length > 8)
50
+ throw new Error('Invalid harness files: expected 1–8 files');
51
+ const paths = new Set();
52
+ for (const raw of check.files) {
53
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
54
+ throw new Error('Invalid harness source');
55
+ const file = raw;
56
+ if (Object.keys(file).some(key => !['path', 'content'].includes(key)))
57
+ throw new Error('Invalid harness source fields');
58
+ const filePath = sourcePath(file.path);
59
+ if ([...paths].some(prior => prior === filePath.toLowerCase() || prior.startsWith(filePath.toLowerCase() + '/') || filePath.toLowerCase().startsWith(prior + '/')))
60
+ throw new Error('Duplicate harness source path');
61
+ paths.add(filePath.toLowerCase());
62
+ if (typeof file.content !== 'string')
63
+ throw new Error('Invalid harness source content');
64
+ const length = Buffer.byteLength(file.content);
65
+ if (length > 64 * 1024 || (bytes += length) > 256 * 1024)
66
+ throw new Error('Invalid harness source size');
67
+ }
68
+ if (!check.files.some(file => file.path === entrypoint))
69
+ throw new Error('Invalid harness entrypoint: source is missing');
70
+ }
71
+ return structuredClone(check);
72
+ });
73
+ }
74
+ function normalized(command) {
75
+ return JSON.parse(JSON.stringify({ ...command, args: [...command.args], cwd: command.cwd ?? '.', timeoutMs: command.timeoutMs ?? 15 * 60_000 }));
76
+ }
77
+ function entry(key, label, command, origin, harness) {
78
+ const definition = normalized(command);
79
+ delete definition.key;
80
+ delete definition.label;
81
+ return { key, label, command: definition, origins: [origin], ...(harness ? { harness } : {}), id: fingerprint({ key, command: definition, harness: harness ?? null }) };
82
+ }
83
+ function mergePolicy(left, right) {
84
+ return {
85
+ reuse: left?.reuse === 'snapshot-local' && right?.reuse === 'snapshot-local' ? 'snapshot-local' : 'never',
86
+ deterministic: left?.deterministic === true && right?.deterministic === true,
87
+ readOnly: left?.readOnly === true && right?.readOnly === true,
88
+ inputs: [...new Set([...(left?.inputs ?? []), ...(right?.inputs ?? [])])].sort(),
89
+ toolchainInputs: [...new Set([...(left?.toolchainInputs ?? []), ...(right?.toolchainInputs ?? [])])].sort(),
90
+ ...(left?.independentGroup && left.independentGroup === right?.independentGroup && left.resources && right.resources ? { independentGroup: left.independentGroup, resources: [...new Set([...left.resources, ...right.resources])].sort() } : {}),
91
+ };
92
+ }
93
+ function coalesce(entries) {
94
+ const results = new Map();
95
+ for (const item of entries) {
96
+ const { policy: _policy, ...command } = item.command;
97
+ const semantic = fingerprint({ command, harness: item.harness ?? null });
98
+ const old = results.get(semantic);
99
+ if (!old) {
100
+ results.set(semantic, structuredClone(item));
101
+ continue;
102
+ }
103
+ if (item.origins.some(origin => origin !== 'developer'))
104
+ old.command.policy = mergePolicy(old.command.policy, item.command.policy);
105
+ old.origins = [...new Set([...old.origins, ...item.origins])];
106
+ }
107
+ return [...results.values()];
108
+ }
109
+ function planFile(context) { return child(pipelineStateDirectory(context), 'verification/plan.json'); }
110
+ export function readVerificationPlan(context) {
111
+ const file = planFile(context);
112
+ if (!existsSync(file))
113
+ return null;
114
+ if (statSync(file).size > 2 * 1024 * 1024)
115
+ throw new Error('Verification plan exceeds its size limit');
116
+ const value = JSON.parse(readFileSync(file, 'utf8'));
117
+ const { integrity, ...payload } = value;
118
+ if (integrity !== fingerprint(payload))
119
+ throw new Error('Verification plan failed its integrity check');
120
+ if (value.scopeHash !== fingerprint(context) || value.schemaVersion !== 1 || value.runId !== context.runId || !Array.isArray(value.baseline) || !Array.isArray(value.developer) || !Array.isArray(value.entries) || value.entries.length > 100 || value.planHash !== fingerprint({ policyVersion: 1, scopeHash: value.scopeHash, executionPolicy: value.executionPolicy, entries: value.entries }))
121
+ throw new Error('Verification plan failed its integrity check');
122
+ return value;
123
+ }
124
+ export function initializeVerificationPlan(context, host, architect, maxConcurrency = 1) {
125
+ const previous = readVerificationPlan(context);
126
+ const baseline = [['host', host], ['architect', architect]].flatMap(([origin, commands]) => commands.map((command, i) => entry(`${origin}:${command.key ?? `${i}-${fingerprint(normalized(command)).slice(0, 12)}`}`, command.label ?? [command.command, ...command.args].join(' ').slice(0, 256), command, origin)));
127
+ if (!Number.isSafeInteger(maxConcurrency) || maxConcurrency < 1 || maxConcurrency > 4)
128
+ throw new Error('Invalid verification concurrency');
129
+ if (previous && fingerprint(previous.baseline) !== fingerprint(baseline))
130
+ throw new Error('Verification baseline is immutable');
131
+ return savePlan(context, baseline, previous?.developer ?? [], previous, { maxConcurrency });
132
+ }
133
+ function buildPlan(context, baseline, developer, previous, executionPolicy = previous?.executionPolicy ?? { maxConcurrency: 1 }) {
134
+ const entries = coalesce([...baseline, ...developer]);
135
+ if (entries.length > 100)
136
+ throw new Error('Invalid verification plan: maximum 100 effective checks');
137
+ const scopeHash = fingerprint(context);
138
+ const planHash = fingerprint({ policyVersion: 1, scopeHash, executionPolicy, entries });
139
+ const payload = { schemaVersion: 1, runId: context.runId, revision: (previous?.revision ?? 0) + (previous?.planHash === planHash ? 0 : 1), planHash, scopeHash, executionPolicy, baseline, developer, entries };
140
+ const plan = { ...payload, integrity: fingerprint(payload) };
141
+ const serialized = JSON.stringify(plan) + '\n';
142
+ if (Buffer.byteLength(serialized) > 2 * 1024 * 1024)
143
+ throw new Error('Verification plan exceeds 2 MiB');
144
+ return plan;
145
+ }
146
+ function savePlan(context, baseline, developer, previous, executionPolicy = previous?.executionPolicy ?? { maxConcurrency: 1 }) {
147
+ const plan = buildPlan(context, baseline, developer, previous, executionPolicy);
148
+ write(planFile(context), JSON.stringify(plan) + '\n');
149
+ return plan;
150
+ }
151
+ export function addDeveloperChecks(context, proposals) {
152
+ const previous = readVerificationPlan(context);
153
+ if (!previous)
154
+ throw new Error('Verification baseline is unavailable');
155
+ const checked = validateProposedChecks(context, proposals);
156
+ const developer = new Map(previous.developer.map(item => [item.key, item]));
157
+ const sources = [];
158
+ for (const check of checked) {
159
+ const command = { repositoryId: check.repositoryId, command: check.command, args: check.args, ...(check.cwd === undefined ? {} : { cwd: check.cwd }), ...(check.timeoutMs === undefined ? {} : { timeoutMs: check.timeoutMs }) };
160
+ const files = check.files?.slice().sort((a, b) => a.path.localeCompare(b.path)).map(file => ({ path: file.path, hash: bytesHash(file.content), byteCount: Buffer.byteLength(file.content) }));
161
+ const harness = files ? { hash: fingerprint(files), entrypoint: check.entrypoint, sources: files } : undefined;
162
+ const item = entry('dev:' + check.key, check.label, command, 'developer', harness);
163
+ developer.set(item.key, item);
164
+ for (const file of check.files ?? [])
165
+ sources.push({ file: child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${harness.hash}/${file.path}`), content: file.content });
166
+ }
167
+ const plan = buildPlan(context, previous.baseline, [...developer.values()], previous);
168
+ // An interrupted write cannot activate a partial harness. Old immutable
169
+ // revisions remain readable; only the new manifest changes the active plan.
170
+ for (const source of sources) {
171
+ if (existsSync(source.file) && readFileSync(source.file, 'utf8') !== source.content)
172
+ throw new Error('Immutable verification source changed');
173
+ }
174
+ for (const source of sources) {
175
+ if (!existsSync(source.file))
176
+ write(source.file, source.content);
177
+ }
178
+ write(planFile(context), JSON.stringify(plan) + '\n');
179
+ return plan;
180
+ }
181
+ export function expandedPlanCommands(context, plan) {
182
+ return plan.entries.map(item => {
183
+ if (!item.harness)
184
+ return { ...item.command, key: item.id, label: item.label };
185
+ const repository = context.repositories.find(repo => repo.id === item.command.repositoryId);
186
+ if (!repository)
187
+ throw new Error('Harness repository is no longer admitted');
188
+ for (const source of item.harness.sources) {
189
+ const file = child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${item.harness.hash}/${source.path}`);
190
+ if (bytesHash(readFileSync(file, 'utf8')) !== source.hash)
191
+ throw new Error('Verification harness source changed');
192
+ }
193
+ const entrypoint = child(pipelineStateDirectory(context), `verification/harnesses/${item.id}/${item.harness.hash}/${item.harness.entrypoint}`);
194
+ return { ...item.command, key: item.id, label: item.label, args: [...item.command.args, entrypoint], env: { SPECRAILS_CHECK_REPO_ROOT: repository.path } };
195
+ });
196
+ }
197
+ /** Bind the exact manifest and every source to lifecycle gates. */
198
+ export function bindPlan(context, plan) {
199
+ const files = [{ path: 'verification/plan.json', hash: bytesHash(readFileSync(planFile(context), 'utf8')) }];
200
+ for (const item of plan.entries)
201
+ for (const source of item.harness?.sources ?? []) {
202
+ files.push({ path: `verification/harnesses/${item.id}/${item.harness.hash}/${source.path}`, hash: source.hash });
203
+ }
204
+ bindVerificationPlan(context, plan.planHash, files);
205
+ }
206
+ //# sourceMappingURL=verification-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-plan.js","sourceRoot":"","sources":["../../src/agent-runtime/verification-plan.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { AnnotationRoot } from '@langchain/langgraph';
2
+ import type { ProviderInvocation } from './efficiency-types.js';
2
3
  /** JSON-only contracts keep checkpoints portable and independent of executors. */
3
4
  export type JsonValue = null | boolean | number | string | JsonValue[] | {
4
5
  [key: string]: JsonValue;
@@ -62,10 +63,18 @@ export interface WorkflowStepContext {
62
63
  interrupt<R extends InterruptResume = InterruptResume>(request: InterruptRequest): R;
63
64
  /** Account provider spend as soon as it is known; a later pause or failure keeps it. */
64
65
  reportUsage(usage: StepUsage): void;
66
+ /** Persist a completed provider call with its already-reported usage. Optional for custom hosts. */
67
+ reportEfficiencyActivity?(kind: string, payload: Record<string, string | number | null>): Promise<void>;
68
+ reportInvocationStarted?(invocation: Omit<import('./efficiency-types.js').PendingProviderInvocation, 'invocationId' | 'ordinal'>): Promise<{
69
+ invocationId: string;
70
+ ordinal: number;
71
+ }>;
72
+ reportInvocation?(invocation: ProviderInvocation): Promise<void>;
65
73
  /** Budget left for the next provider call, after everything reported so far. */
66
74
  remainingBudget(): {
67
75
  maxTokens?: number;
68
76
  maxCostUsd?: number;
77
+ maxDurationMs?: number;
69
78
  };
70
79
  }
71
80
  export interface WorkflowNode<S extends Record<string, unknown>> {
@@ -115,6 +124,8 @@ export interface StepAttemptRecord {
115
124
  output?: JsonValue;
116
125
  error?: string;
117
126
  usage?: StepUsage;
127
+ pendingInvocations?: import('./efficiency-types.js').PendingProviderInvocation[];
128
+ invocations?: ProviderInvocation[];
118
129
  }
119
130
  export interface WorkflowEvent {
120
131
  id: string;
@@ -123,7 +134,12 @@ export interface WorkflowEvent {
123
134
  /** Trace correlation: the run's trace and the attempt span this event belongs to. */
124
135
  traceId: string;
125
136
  spanId?: string;
126
- type: 'workflow_started' | 'workflow_resumed' | 'workflow_invalidated' | 'workflow_succeeded' | 'workflow_failed' | 'workflow_blocked' | 'workflow_paused' | 'workflow_cancelled' | 'step_started' | 'step_succeeded' | 'step_failed' | 'step_blocked' | 'step_paused' | 'step_interrupted';
137
+ efficiencyActivity?: {
138
+ kind: string;
139
+ payload: Record<string, string | number | null>;
140
+ };
141
+ efficiency?: ProviderInvocation;
142
+ type: 'efficiency_updated' | 'workflow_started' | 'workflow_resumed' | 'workflow_invalidated' | 'workflow_succeeded' | 'workflow_failed' | 'workflow_blocked' | 'workflow_paused' | 'workflow_cancelled' | 'step_started' | 'step_succeeded' | 'step_failed' | 'step_blocked' | 'step_paused' | 'step_interrupted';
127
143
  timestamp: string;
128
144
  stepId?: string;
129
145
  attemptId?: string;
@@ -271,7 +271,12 @@ export async function runWorkflow(options) {
271
271
  }
272
272
  let forkTarget;
273
273
  if (invalid.size) {
274
- const first = Math.min(...Array.from(invalid, id => ids.indexOf(id)));
274
+ let first = Math.min(...Array.from(invalid, id => ids.indexOf(id)));
275
+ // A stale later receipt must never jump over an unfinished correction.
276
+ // This also repairs checkpoints whose previous resume chose that receipt.
277
+ const unfinished = ids.findIndex((id, index) => index < first && ['blocked', 'failed'].includes(state.steps[id].status));
278
+ if (unfinished >= 0)
279
+ first = unfinished;
275
280
  for (const id of ids.slice(first))
276
281
  resetRecord(state, id);
277
282
  forkTarget = ids[first];
@@ -391,7 +396,29 @@ export async function runWorkflow(options) {
391
396
  return interrupt(request);
392
397
  },
393
398
  reportUsage: usage => { validateUsage(usage); accountUsage(state, usage); reported = addUsage(reported ?? { costUsd: 0, inputTokens: 0, outputTokens: 0 }, usage); },
399
+ reportEfficiencyActivity: async (kind, payload) => { await commit({ type: 'efficiency_updated', stepId: id, attemptId, efficiencyActivity: { kind, payload } }); },
400
+ reportInvocationStarted: async (invocation) => {
401
+ const ordinal = (history.invocations?.length ?? 0) + (history.pendingInvocations?.length ?? 0) + 1;
402
+ const identity = { invocationId: `${attemptId}:call:${ordinal}`, ordinal };
403
+ (history.pendingInvocations ??= []).push({ ...clone(invocation), ...identity });
404
+ await persist();
405
+ return identity;
406
+ },
407
+ reportInvocation: async (invocation) => {
408
+ validateUsage(invocation.usage);
409
+ if (!Number.isFinite(invocation.durationMs) || invocation.durationMs < 0 || !Number.isSafeInteger(invocation.toolCalls) || invocation.toolCalls < 0)
410
+ throw new TypeError('Invalid invocation measurement');
411
+ if (invocation.invocationId && history.invocations?.some(item => item.invocationId === invocation.invocationId))
412
+ return;
413
+ (history.invocations ??= []).push(clone(invocation));
414
+ if (invocation.invocationId)
415
+ history.pendingInvocations = history.pendingInvocations?.filter(item => item.invocationId !== invocation.invocationId);
416
+ if (reported)
417
+ history.usage = reported;
418
+ await commit({ type: 'efficiency_updated', stepId: id, attemptId, efficiency: clone(invocation) });
419
+ },
394
420
  remainingBudget: () => ({
421
+ ...(state.budget.maxDurationMs === undefined ? {} : { maxDurationMs: Math.max(0, state.budget.maxDurationMs - state.usage.durationMs - (performance.now() - elapsedMark)) }),
395
422
  ...(state.budget.maxTokens === undefined ? {} : { maxTokens: Math.max(0, state.budget.maxTokens - state.usage.knownTokens) }),
396
423
  ...(state.budget.maxCostUsd === undefined ? {} : { maxCostUsd: Math.max(0, state.budget.maxCostUsd - state.usage.knownCostUsd) }),
397
424
  }),