@lazyingart/agintiflow 0.20.242 → 0.20.243

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.
@@ -10,6 +10,15 @@ Simple questions should stay on the fast path. A deep-research run spends more
10
10
  queries and model calls only when breadth, verification, and traceability add
11
11
  real value.
12
12
 
13
+ For a request that combines local workspace evidence with web research, the
14
+ outer agent first receives normal inspection tools. After it has read two
15
+ relevant files, or read one file plus inspected/searched the project, the next
16
+ research turn is constrained to `deep_research` and `finish`. This keeps local
17
+ notes authoritative without letting an agent silently replace a requested
18
+ multi-source review with ad hoc browsing. Tool history is scoped to the newest
19
+ genuine user request, so a completed research call from an older task does not
20
+ suppress a later correction or refresh.
21
+
13
22
  ## Architecture
14
23
 
15
24
  The implementation follows the strongest production patterns without making
@@ -205,7 +214,10 @@ To resume a partial or completed same-query run, pass the returned
205
214
  `refresh=true` is explicit. A transient run that retrieved zero allowed sources
206
215
  is marked failed, preserves its attempts, and retries retrieval on resume
207
216
  instead of caching an empty report as success. Checkpoint schema changes
208
- invalidate old cached runs automatically.
217
+ invalidate old cached runs automatically. The public tool result also carries
218
+ the research schema version; the outer session reuses a completed result only
219
+ when that version matches the installed engine. Versionless or older retained
220
+ results are refreshed instead of being presented as current evidence.
209
221
 
210
222
  `outputPath` is optional and must name a Markdown file inside the active
211
223
  workspace. Repository internals such as `.git`, dependency trees such as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.242",
3
+ "version": "0.20.243",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
6
6
  "license": "Apache-2.0",
@@ -66,6 +66,7 @@
66
66
  "scripts/supervision-ledger.js",
67
67
  "scripts/smoke-supervision-ledger.js",
68
68
  "scripts/smoke-integration-production-mount.js",
69
+ "scripts/smoke-integration-production-runtime-bundle.js",
69
70
  "scripts/smoke-integration-storage-authority.js",
70
71
  "scripts/smoke-integration-retained-durable-common.js",
71
72
  "scripts/smoke-integration-retained-file-lock.js",
@@ -203,6 +204,7 @@
203
204
  "supervision:ledger": "node scripts/supervision-ledger.js",
204
205
  "smoke:supervision-ledger": "node scripts/smoke-supervision-ledger.js",
205
206
  "smoke:integration-production-mount": "node scripts/smoke-integration-production-mount.js",
207
+ "smoke:integration-production-runtime-bundle": "node scripts/smoke-integration-production-runtime-bundle.js",
206
208
  "smoke:integration-storage-authority": "node scripts/smoke-integration-storage-authority.js",
207
209
  "smoke:integration-retained-durable-common": "node scripts/smoke-integration-retained-durable-common.js",
208
210
  "smoke:integration-retained-file-lock": "node scripts/smoke-integration-retained-file-lock.js",
@@ -219,7 +221,7 @@
219
221
  "storage:migrate": "node bin/aginti-cli.js storage migrate",
220
222
  "publish:env": "node scripts/npm-publish-from-env.js publish --access public",
221
223
  "publish:env:whoami": "node scripts/npm-publish-from-env.js whoami",
222
- "test": "npm run check && npm run smoke:integration-production-mount && npm run smoke:integration-storage-authority && npm run smoke:integration-retained-durable-common && npm run smoke:integration-retained-file-lock && npm run smoke:integration-retained-event-ledger && npm run smoke:integration-retained-event-ledger-bundle && npm run smoke:integration-retained-repository-kernel && npm run smoke:integration-retained-session-state-store && npm run smoke:integration-retained-native-session-repository-state && npm run smoke:integration-retained-native-execution-evidence && npm run smoke:integration-retained-runtime-repository-surface && npm run smoke:integration-retained-runtime-repository-phase-b && npm run smoke:integration-runtime-repository-contract && npm run smoke:integration-runtime-authority && npm run smoke:localllm-provider && npm run smoke:localllm-model-tiers && npm run smoke:localllm-code-routing && npm run smoke:local-failure-recovery && npm run smoke:localllm-auto-max && npm run smoke:local-resource-policy && npm run smoke:context-budget-recovery && npm run smoke:session-runtime && npm run smoke:runtime-core && npm run smoke:progressive-tools && npm run smoke:truthful-completion && npm run smoke:document-artifact-quality && npm run smoke:writing-specialist-routing && npm run eval:local-first-agent && npm run eval:provider-attribution && npm run smoke:runtime-compat && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:math-rendering && npm run smoke:web-ui && npm run smoke:web-autostart && npm run smoke:webapp-command && npm run smoke:web-port-fallback && npm run smoke:docker-command && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:execution-policy && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:deep-research && npm run smoke:public-research && npm run smoke:safe-chat && npm run smoke:auth && npm run smoke:agentlink && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:mcp && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:supervision-ledger && npm run smoke:tmux-tools && npm run smoke:long-jobs && npm run smoke:run-stdin && npm run smoke:cli-chat && npm run smoke:inbox",
224
+ "test": "npm run check && npm run smoke:integration-production-mount && npm run smoke:integration-production-runtime-bundle && npm run smoke:integration-storage-authority && npm run smoke:integration-retained-durable-common && npm run smoke:integration-retained-file-lock && npm run smoke:integration-retained-event-ledger && npm run smoke:integration-retained-event-ledger-bundle && npm run smoke:integration-retained-repository-kernel && npm run smoke:integration-retained-session-state-store && npm run smoke:integration-retained-native-session-repository-state && npm run smoke:integration-retained-native-execution-evidence && npm run smoke:integration-retained-runtime-repository-surface && npm run smoke:integration-retained-runtime-repository-phase-b && npm run smoke:integration-runtime-repository-contract && npm run smoke:integration-runtime-authority && npm run smoke:localllm-provider && npm run smoke:localllm-model-tiers && npm run smoke:localllm-code-routing && npm run smoke:local-failure-recovery && npm run smoke:localllm-auto-max && npm run smoke:local-resource-policy && npm run smoke:context-budget-recovery && npm run smoke:session-runtime && npm run smoke:runtime-core && npm run smoke:progressive-tools && npm run smoke:truthful-completion && npm run smoke:document-artifact-quality && npm run smoke:writing-specialist-routing && npm run eval:local-first-agent && npm run eval:provider-attribution && npm run smoke:runtime-compat && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:math-rendering && npm run smoke:web-ui && npm run smoke:web-autostart && npm run smoke:webapp-command && npm run smoke:web-port-fallback && npm run smoke:docker-command && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:execution-policy && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:deep-research && npm run smoke:public-research && npm run smoke:safe-chat && npm run smoke:auth && npm run smoke:agentlink && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:mcp && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:supervision-ledger && npm run smoke:tmux-tools && npm run smoke:long-jobs && npm run smoke:run-stdin && npm run smoke:cli-chat && npm run smoke:inbox",
223
225
  "pack:dry-run": "npm pack --dry-run",
224
226
  "smoke:capabilities": "node scripts/smoke-capabilities.js"
225
227
  },
@@ -3,7 +3,7 @@ import fs from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
 
6
- import { auditResearchSynthesis, deepResearch } from "../src/deep-research.js";
6
+ import { auditResearchSynthesis, deepResearch, RESEARCH_VERSION } from "../src/deep-research.js";
7
7
  import { checkToolUse } from "../src/guardrails.js";
8
8
  import { flushHousekeeping } from "../src/housekeeping.js";
9
9
  import { requestNextStep, toolChoiceForProvider } from "../src/model-client.js";
@@ -59,6 +59,50 @@ async function main() {
59
59
  !shouldStartWithDeepResearch(localEvidenceGoal),
60
60
  "local-source research incorrectly forced deep_research before workspace inspection"
61
61
  );
62
+ const inspectedLocalEvidenceMessages = [
63
+ { role: "user", content: localEvidenceGoal },
64
+ {
65
+ role: "assistant",
66
+ tool_calls: [{ id: "inspect-notes", function: { name: "read_file", arguments: '{"path":"PROJECT_NOTES.md"}' } }],
67
+ },
68
+ {
69
+ role: "assistant",
70
+ tool_calls: [{ id: "inspect-sources", function: { name: "read_file", arguments: '{"path":"sources.json"}' } }],
71
+ },
72
+ ];
73
+ assert(
74
+ shouldStartWithDeepResearch(localEvidenceGoal, inspectedLocalEvidenceMessages),
75
+ "local-source research did not enter bounded deep research after workspace inspection"
76
+ );
77
+ assert(
78
+ !shouldStartWithDeepResearch(localEvidenceGoal, [
79
+ ...inspectedLocalEvidenceMessages,
80
+ {
81
+ role: "assistant",
82
+ tool_calls: [{ id: "current-research", function: { name: "deep_research", arguments: "{}" } }],
83
+ },
84
+ ]),
85
+ "the current request repeated deep research after already requesting it"
86
+ );
87
+ assert(
88
+ shouldStartWithDeepResearch(localEvidenceGoal, [
89
+ ...inspectedLocalEvidenceMessages,
90
+ {
91
+ role: "assistant",
92
+ tool_calls: [{ id: "old-research", function: { name: "deep_research", arguments: "{}" } }],
93
+ },
94
+ { role: "user", content: "Refresh this evidence review because the current report quality is not acceptable." },
95
+ {
96
+ role: "assistant",
97
+ tool_calls: [{ id: "refresh-report", function: { name: "read_file", arguments: '{"path":"agent-reliability-evidence-review.md"}' } }],
98
+ },
99
+ {
100
+ role: "assistant",
101
+ tool_calls: [{ id: "refresh-sources", function: { name: "read_file", arguments: '{"path":"sources.json"}' } }],
102
+ },
103
+ ]),
104
+ "a completed research call from an older user intent suppressed a fresh bounded research pass"
105
+ );
62
106
  assert(
63
107
  shouldStartWithDeepResearch("Write a deep web research report comparing three primary papers."),
64
108
  "standalone deep research no longer starts with the bounded research workflow"
@@ -509,6 +553,7 @@ async function main() {
509
553
  },
510
554
  store
511
555
  );
556
+ assert(research.version === RESEARCH_VERSION, "deep research did not expose its result-schema version");
512
557
  assert(research.ok && research.sourceCount === 2, `deep research failed: ${research.error || "unknown"}`);
513
558
  assert(
514
559
  researchSearchProviders.length === 2 && researchSearchProviders.every((provider) => provider === "multi"),
@@ -4,6 +4,7 @@ import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { runAgent } from "../src/agent-runner.js";
7
+ import { RESEARCH_VERSION } from "../src/deep-research.js";
7
8
  import { resolveRuntimeConfig } from "../src/config.js";
8
9
  import { classifyCommand, evaluateCommandPolicy } from "../src/command-policy.js";
9
10
  import {
@@ -4338,6 +4339,7 @@ try {
4338
4339
  {
4339
4340
  ok: true,
4340
4341
  toolName: "deep_research",
4342
+ version: RESEARCH_VERSION,
4341
4343
  researchId: "research-one",
4342
4344
  status: "completed",
4343
4345
  reportPath: path.join(workspace, "report.md"),
@@ -4354,6 +4356,16 @@ try {
4354
4356
  reusedResearch?.duplicateSuppressed && reusedResearch.reportPath === path.join(workspace, "report.md"),
4355
4357
  "same-goal deep research did not reuse an already completed exact report"
4356
4358
  );
4359
+ completedResearchState.meta.completedDeepResearch[0].result.version = RESEARCH_VERSION - 1;
4360
+ assert(
4361
+ completedDeepResearchReuse(
4362
+ completedResearchState,
4363
+ { query: "A model-expanded query", outputPath: "report.md", refresh: true },
4364
+ { commandCwd: workspace }
4365
+ ) === null,
4366
+ "a stale deep-research engine result was reused after the report contract changed"
4367
+ );
4368
+ completedResearchState.meta.completedDeepResearch[0].result.version = RESEARCH_VERSION;
4357
4369
  completedResearchState.meta.goalContract = { revision: 2, currentHash: "goal-two" };
4358
4370
  assert(
4359
4371
  completedDeepResearchReuse(
@@ -547,6 +547,7 @@ async function verifyPackagedBinAndScriptClosure() {
547
547
  "scripts/eval-provider-attribution.js",
548
548
  "scripts/smoke-context-budget-recovery.js",
549
549
  "scripts/smoke-integration-production-mount.js",
550
+ "scripts/smoke-integration-production-runtime-bundle.js",
550
551
  ]) {
551
552
  assert.equal(packageJson.files.includes(requiredFile), true);
552
553
  }
@@ -1087,6 +1088,38 @@ async function main() {
1087
1088
  "INTEGRATION_CREDENTIAL_SOURCE_FORBIDDEN"
1088
1089
  );
1089
1090
 
1091
+ let cliCheckOutput = "";
1092
+ await withCanonicalCredentialFixture(async () => {
1093
+ const summary = await integrationCliMain(["check", "--config", configPath], {
1094
+ env: { CREDENTIALS_DIRECTORY: INTEGRATION_SYSTEMD_CREDENTIALS_DIRECTORY },
1095
+ stdout: { write(chunk) { cliCheckOutput += String(chunk); } },
1096
+ });
1097
+ assert.equal(summary.status, "checked-disabled");
1098
+ assert.equal(summary.capability?.enabled, false);
1099
+ assert.equal(summary.implementationReady, false);
1100
+ assert.equal(typeof summary.runtimeBundle?.healthy, "boolean");
1101
+ assert.equal(summary.runtimeBundle?.implementationReady, false);
1102
+ assert.equal(summary.runtimeBundle?.capabilityEnabled, false);
1103
+ assert.equal(summary.runtimeBundle?.httpServingEnabled, false);
1104
+ if (summary.runtimeBundle.healthy) {
1105
+ assert.equal(summary.runtimeBundle.firstBlocker?.component, "idempotencyStore");
1106
+ assert.equal(
1107
+ summary.runtimeBundle.firstBlocker?.code,
1108
+ "INTEGRATION_DESCRIPTOR_BOUND_IDEMPOTENCY_UNAVAILABLE"
1109
+ );
1110
+ } else {
1111
+ assert.equal(summary.runtimeBundle.firstBlocker?.component, "storageAuthority");
1112
+ assert.match(
1113
+ summary.runtimeBundle.firstBlocker?.code || "",
1114
+ /^INTEGRATION_STORAGE_/u
1115
+ );
1116
+ }
1117
+ assert.deepEqual(
1118
+ JSON.parse(cliCheckOutput.trim()),
1119
+ JSON.parse(JSON.stringify(summary))
1120
+ );
1121
+ });
1122
+
1090
1123
  const cliServePort = await unusedLoopbackPort();
1091
1124
  const cliServeConfigPath = path.join(tempRoot, "integration-serve.json");
1092
1125
  await fs.writeFile(
@@ -0,0 +1,398 @@
1
+ #!/usr/bin/env node
2
+ import assert from "node:assert/strict";
3
+ import fs from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import {
7
+ INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_HEALTH_VERSION,
8
+ INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_LIMITATIONS,
9
+ INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_VERSION,
10
+ checkIntegrationProductionRuntimeBundle,
11
+ integrationProductionRuntimeBundlePaths,
12
+ openIntegrationProductionRuntimeBundle,
13
+ preflightIntegrationProductionRuntimeBundle,
14
+ } from "../src/integration-production-runtime-bundle.js";
15
+ import { contractDigest } from "../src/integration-policy.js";
16
+
17
+ const UID = process.getuid();
18
+ const GID = process.getgid();
19
+
20
+ async function expectCode(action, expectedCode) {
21
+ let captured = null;
22
+ try {
23
+ await action();
24
+ } catch (error) {
25
+ captured = error;
26
+ }
27
+ assert(captured, `Expected ${expectedCode}`);
28
+ assert.equal(captured.publicCode || captured.code, expectedCode, captured.stack || captured.message);
29
+ }
30
+
31
+ async function expectNoUnhandledRejections(action) {
32
+ const unhandled = [];
33
+ const onUnhandled = (reason) => unhandled.push(reason);
34
+ process.on("unhandledRejection", onUnhandled);
35
+ try {
36
+ await action();
37
+ await new Promise((resolve) => setImmediate(resolve));
38
+ } finally {
39
+ process.removeListener("unhandledRejection", onUnhandled);
40
+ }
41
+ assert.deepEqual(unhandled, []);
42
+ }
43
+
44
+ async function ensureOwnerDirectory(directoryPath) {
45
+ await fs.mkdir(directoryPath, { recursive: true, mode: 0o700 });
46
+ await fs.chmod(directoryPath, 0o700);
47
+ await fs.chown(directoryPath, UID, GID);
48
+ }
49
+
50
+ async function ensureLockFile(filePath) {
51
+ try {
52
+ await fs.writeFile(filePath, "", { flag: "wx", mode: 0o600 });
53
+ } catch (error) {
54
+ if (error?.code !== "EEXIST") throw error;
55
+ }
56
+ await fs.chmod(filePath, 0o600);
57
+ await fs.chown(filePath, UID, GID);
58
+ }
59
+
60
+ async function provisionRuntimeRoot(stateRoot, { omitEventLock = false } = {}) {
61
+ const paths = integrationProductionRuntimeBundlePaths(stateRoot);
62
+ for (const directoryPath of [
63
+ paths.stateRoot,
64
+ path.dirname(paths.repository),
65
+ paths.repository,
66
+ paths.sessions,
67
+ paths.workspace,
68
+ paths.eventLedger,
69
+ paths.idempotency,
70
+ ]) {
71
+ await ensureOwnerDirectory(directoryPath);
72
+ }
73
+ await ensureLockFile(paths.repositoryLock);
74
+ await ensureLockFile(paths.sessionLock);
75
+ if (!omitEventLock) await ensureLockFile(paths.eventLedgerLock);
76
+ return paths;
77
+ }
78
+
79
+ async function inventory(stateRoot) {
80
+ const names = await fs.readdir(stateRoot, { recursive: true });
81
+ return names.map((name) => String(name)).sort();
82
+ }
83
+
84
+ function assertEvidenceDigest(evidence) {
85
+ const { digest, ...unsigned } = evidence;
86
+ assert.equal(digest, contractDigest(unsigned));
87
+ }
88
+
89
+ async function run() {
90
+ const missingRoot = path.join(
91
+ os.tmpdir(),
92
+ `aginti-production-runtime-bundle-missing-${process.pid}-${Date.now()}`
93
+ );
94
+ const missing = await checkIntegrationProductionRuntimeBundle({ stateRoot: missingRoot });
95
+ assert.equal(missing.schemaVersion, INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_HEALTH_VERSION);
96
+ assert.equal(missing.healthy, false);
97
+ assert.equal(missing.implementationReady, false);
98
+ assert.equal(missing.capabilityEnabled, false);
99
+ assert.equal(missing.httpServingEnabled, false);
100
+ assert.equal(missing.firstBlocker.component, "storageAuthority");
101
+ assert.equal(missing.firstBlocker.code, "INTEGRATION_STORAGE_UNAVAILABLE");
102
+ assert.equal(missing.blockers[1].component, "idempotencyStore");
103
+ assertEvidenceDigest(missing);
104
+
105
+ let proxyTrapCalls = 0;
106
+ const proxiedInput = new Proxy(Object.freeze({ stateRoot: missingRoot }), {
107
+ get() {
108
+ proxyTrapCalls += 1;
109
+ throw new Error("bundle input get trap must not run");
110
+ },
111
+ ownKeys() {
112
+ proxyTrapCalls += 1;
113
+ throw new Error("bundle input ownKeys trap must not run");
114
+ },
115
+ });
116
+ await expectCode(
117
+ () => openIntegrationProductionRuntimeBundle(proxiedInput),
118
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
119
+ );
120
+ assert.equal(proxyTrapCalls, 0);
121
+ const revocable = Proxy.revocable(Object.freeze({ stateRoot: missingRoot }), {});
122
+ revocable.revoke();
123
+ await expectCode(
124
+ () => openIntegrationProductionRuntimeBundle(revocable.proxy),
125
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
126
+ );
127
+
128
+ let accessorCalls = 0;
129
+ const accessorInput = {};
130
+ Object.defineProperty(accessorInput, "stateRoot", {
131
+ configurable: true,
132
+ enumerable: true,
133
+ get() {
134
+ accessorCalls += 1;
135
+ return missingRoot;
136
+ },
137
+ });
138
+ await expectCode(
139
+ () => openIntegrationProductionRuntimeBundle(accessorInput),
140
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
141
+ );
142
+ assert.equal(accessorCalls, 0);
143
+ await expectCode(
144
+ () => openIntegrationProductionRuntimeBundle(Object.create({ stateRoot: missingRoot })),
145
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
146
+ );
147
+ await expectNoUnhandledRejections(async () => {
148
+ const rejectedInput = Promise.reject(new Error("already rejected bundle input"));
149
+ await expectCode(
150
+ () => openIntegrationProductionRuntimeBundle(rejectedInput),
151
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
152
+ );
153
+ const rejectedStateRoot = Promise.reject(new Error("already rejected stateRoot"));
154
+ await expectCode(
155
+ () => openIntegrationProductionRuntimeBundle({ stateRoot: rejectedStateRoot }),
156
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
157
+ );
158
+ const rejectedOpenExtra = Promise.reject(new Error("already rejected open extra"));
159
+ await expectCode(
160
+ () => openIntegrationProductionRuntimeBundle({ stateRoot: missingRoot }, rejectedOpenExtra),
161
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
162
+ );
163
+ const rejectedPreflightExtra = Promise.reject(new Error("already rejected preflight extra"));
164
+ await expectCode(
165
+ () => preflightIntegrationProductionRuntimeBundle({ stateRoot: missingRoot }, rejectedPreflightExtra),
166
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
167
+ );
168
+ const rejectedCheckExtra = Promise.reject(new Error("already rejected check extra"));
169
+ await expectCode(
170
+ () => checkIntegrationProductionRuntimeBundle({ stateRoot: missingRoot }, rejectedCheckExtra),
171
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
172
+ );
173
+ const rejectedPathsExtra = Promise.reject(new Error("already rejected paths extra"));
174
+ await expectCode(
175
+ () => integrationProductionRuntimeBundlePaths(missingRoot, rejectedPathsExtra),
176
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
177
+ );
178
+ });
179
+
180
+ const nonDirectoryRoot = await fs.mkdtemp(
181
+ path.join(os.tmpdir(), "aginti-production-runtime-nondirectory-")
182
+ );
183
+ try {
184
+ const nonDirectory = path.join(nonDirectoryRoot, "not-a-directory");
185
+ await fs.writeFile(nonDirectory, "blocked", { mode: 0o600 });
186
+ const unavailable = await checkIntegrationProductionRuntimeBundle({
187
+ stateRoot: path.join(nonDirectory, "child"),
188
+ });
189
+ assert.equal(unavailable.healthy, false);
190
+ assert.equal(unavailable.firstBlocker.component, "storageAuthority");
191
+ assert.equal(unavailable.firstBlocker.code, "INTEGRATION_STORAGE_UNAVAILABLE");
192
+ if (UID !== 0) {
193
+ const deniedParent = path.join(nonDirectoryRoot, "denied");
194
+ await fs.mkdir(deniedParent, { mode: 0o700 });
195
+ await fs.chmod(deniedParent, 0o000);
196
+ try {
197
+ const denied = await checkIntegrationProductionRuntimeBundle({
198
+ stateRoot: path.join(deniedParent, "child"),
199
+ });
200
+ assert.equal(denied.healthy, false);
201
+ assert.equal(denied.firstBlocker.component, "storageAuthority");
202
+ assert.equal(denied.firstBlocker.code, "INTEGRATION_STORAGE_UNAVAILABLE");
203
+ } finally {
204
+ await fs.chmod(deniedParent, 0o700);
205
+ }
206
+ }
207
+ } finally {
208
+ await fs.rm(nonDirectoryRoot, { recursive: true, force: true });
209
+ }
210
+
211
+ const stateRoot = await fs.mkdtemp(path.join(os.tmpdir(), "aginti-production-runtime-bundle-"));
212
+ const poisonRoot = await fs.mkdtemp(path.join(os.tmpdir(), "aginti-production-runtime-poison-"));
213
+ const lockModeRoot = await fs.mkdtemp(path.join(os.tmpdir(), "aginti-production-runtime-lock-mode-"));
214
+ const lockReplacementRoot = await fs.mkdtemp(
215
+ path.join(os.tmpdir(), "aginti-production-runtime-lock-replacement-")
216
+ );
217
+ const failedRoot = await fs.mkdtemp(path.join(os.tmpdir(), "aginti-production-runtime-failed-"));
218
+ try {
219
+ const paths = await provisionRuntimeRoot(stateRoot);
220
+ assert.equal(paths.repository, path.join(stateRoot, "runtime-authority", "repository"));
221
+ assert.equal(paths.sessions, path.join(stateRoot, "runtime-authority", "sessions"));
222
+ assert.equal(paths.workspace, path.join(stateRoot, "runtime-authority", "workspace"));
223
+ assert.equal(paths.eventLedger, path.join(stateRoot, "event-ledger"));
224
+ assert.equal(paths.idempotency, path.join(stateRoot, "idempotency-store"));
225
+
226
+ const beforePreflight = await inventory(stateRoot);
227
+ const check = await checkIntegrationProductionRuntimeBundle({ stateRoot });
228
+ assert.equal(check.healthy, true);
229
+ assert.equal(check.implementationReady, false);
230
+ assert.equal(check.firstBlocker.component, "idempotencyStore");
231
+ assert.equal(
232
+ check.firstBlocker.code,
233
+ "INTEGRATION_DESCRIPTOR_BOUND_IDEMPOTENCY_UNAVAILABLE"
234
+ );
235
+ assert.equal(check.components.storageAuthority.descriptorBound, true);
236
+ assert.equal(check.components.repository.descriptorBound, true);
237
+ assert.equal(check.components.repository.runtimeFenceAcquired, false);
238
+ assert.equal(check.components.sessionState.descriptorBound, true);
239
+ assert.equal(check.components.sessionState.nativeWriteFenceBound, false);
240
+ assert.equal(check.components.eventLedger.runtimeAppendView, true);
241
+ assert.equal(check.components.eventLedger.sessionReadView, true);
242
+ assert.equal(check.components.idempotencyStore.namespaceDescriptorBound, true);
243
+ assert.equal(check.components.idempotencyStore.transactionalStore, false);
244
+ assert.equal(check.components.nativeExecutor.lexicalProofPresent, true);
245
+ assert.equal(check.components.nativeExecutor.retainedSessionStateBound, false);
246
+ assert.equal(check.components.nativeExecutor.artifactEvents, false);
247
+ assert.equal(check.components.sandbox.capabilityEnabled, false);
248
+ assert.equal(check.components.runtimeAuthority.composed, false);
249
+ assert.equal(check.components.sessionService.composed, false);
250
+ assertEvidenceDigest(check);
251
+ assert.deepEqual(await inventory(stateRoot), beforePreflight);
252
+
253
+ const directPreflight = await preflightIntegrationProductionRuntimeBundle({ stateRoot });
254
+ assert.equal(directPreflight.probe, "preflight");
255
+ assert.equal(directPreflight.healthy, true);
256
+ assert.equal(directPreflight.implementationReady, false);
257
+ assert.deepEqual(await inventory(stateRoot), beforePreflight);
258
+
259
+ const bundle = await openIntegrationProductionRuntimeBundle({ stateRoot });
260
+ assert.equal(Object.getPrototypeOf(bundle), null);
261
+ assert.equal(Object.isFrozen(bundle), true);
262
+ assert.equal(bundle.schemaVersion, INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_VERSION);
263
+ assert.equal(bundle.attestation.descriptorBound, true);
264
+ assert.equal(bundle.attestation.storageLifecycleOwned, true);
265
+ assert.equal(bundle.attestation.implementationReady, false);
266
+ assert.equal(bundle.attestation.capabilityEnabled, false);
267
+ assert.equal(bundle.attestation.httpServingEnabled, false);
268
+ assert.equal(bundle.attestation.runtimeActivated, false);
269
+ assert.equal(bundle.attestation.idempotencyProofDigest, "0".repeat(64));
270
+ assert.equal(bundle.attestation.blockers[0].component, "idempotencyStore");
271
+ assert.equal(bundle.attestation.limitations, INTEGRATION_PRODUCTION_RUNTIME_BUNDLE_LIMITATIONS);
272
+ assert.equal("start" in bundle, false);
273
+ assert.equal("serve" in bundle, false);
274
+ assert.equal("runtimeAuthority" in bundle, false);
275
+ assert.equal("sessionService" in bundle, false);
276
+ assert.throws(() => Object.defineProperty(bundle, "start", { value() {} }), TypeError);
277
+ await expectCode(() => bundle.health({}), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
278
+ await expectCode(() => bundle.preflight({}), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
279
+ await expectCode(() => bundle.close({}), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
280
+ await expectCode(() => bundle.isClosed({}), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
281
+ await expectNoUnhandledRejections(async () => {
282
+ const rejectedHealthExtra = Promise.reject(new Error("already rejected health extra"));
283
+ await expectCode(() => bundle.health(rejectedHealthExtra), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
284
+ const rejectedPreflightExtra = Promise.reject(new Error("already rejected preflight extra"));
285
+ await expectCode(
286
+ () => bundle.preflight(rejectedPreflightExtra),
287
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
288
+ );
289
+ const rejectedCloseExtra = Promise.reject(new Error("already rejected close extra"));
290
+ await expectCode(() => bundle.close(rejectedCloseExtra), "INTEGRATION_RUNTIME_BUNDLE_INVALID");
291
+ const rejectedClosedExtra = Promise.reject(new Error("already rejected isClosed extra"));
292
+ await expectCode(
293
+ () => bundle.isClosed(rejectedClosedExtra),
294
+ "INTEGRATION_RUNTIME_BUNDLE_INVALID"
295
+ );
296
+ });
297
+
298
+ const healthy = await bundle.health();
299
+ assert.equal(healthy.probe, "health");
300
+ assert.equal(healthy.status, "healthy-disabled");
301
+ assert.equal(healthy.healthy, true);
302
+ assert.equal(healthy.implementationReady, false);
303
+ assertEvidenceDigest(healthy);
304
+
305
+ const concurrentHealth = await Promise.all([
306
+ bundle.health(),
307
+ bundle.preflight(),
308
+ bundle.health(),
309
+ ]);
310
+ assert.deepEqual(
311
+ concurrentHealth.map((item) => item.healthy),
312
+ [true, true, true]
313
+ );
314
+
315
+ const racingProbe = bundle.health();
316
+ const racingClose = bundle.close();
317
+ await expectCode(() => racingProbe, "INTEGRATION_RUNTIME_BUNDLE_CLOSED");
318
+ assert.deepEqual(await racingClose, { closed: true, poisoned: false });
319
+ assert.equal(bundle.isClosed(), true);
320
+ assert.deepEqual(await bundle.close(), { closed: true, poisoned: false });
321
+ await expectCode(() => bundle.health(), "INTEGRATION_RUNTIME_BUNDLE_CLOSED");
322
+ await expectCode(() => bundle.preflight(), "INTEGRATION_RUNTIME_BUNDLE_CLOSED");
323
+
324
+ await provisionRuntimeRoot(poisonRoot);
325
+ const poisonedBundle = await openIntegrationProductionRuntimeBundle({ stateRoot: poisonRoot });
326
+ await fs.chmod(poisonRoot, 0o755);
327
+ await expectCode(() => poisonedBundle.health(), "INTEGRATION_STORAGE_POISONED");
328
+ await fs.chmod(poisonRoot, 0o700);
329
+ await expectCode(() => poisonedBundle.health(), "INTEGRATION_RUNTIME_BUNDLE_POISONED");
330
+ assert.deepEqual(await poisonedBundle.close(), { closed: true, poisoned: true });
331
+
332
+ const lockModePaths = await provisionRuntimeRoot(lockModeRoot);
333
+ const lockModeBundle = await openIntegrationProductionRuntimeBundle({ stateRoot: lockModeRoot });
334
+ await fs.chmod(lockModePaths.repositoryLock, 0o640);
335
+ await expectCode(() => lockModeBundle.health(), "INTEGRATION_STORAGE_LOCK_POISONED");
336
+ await fs.chmod(lockModePaths.repositoryLock, 0o600);
337
+ await expectCode(() => lockModeBundle.health(), "INTEGRATION_RUNTIME_BUNDLE_POISONED");
338
+ assert.deepEqual(await lockModeBundle.close(), { closed: true, poisoned: true });
339
+
340
+ const replacementPaths = await provisionRuntimeRoot(lockReplacementRoot);
341
+ const replacementBundle = await openIntegrationProductionRuntimeBundle({
342
+ stateRoot: lockReplacementRoot,
343
+ });
344
+ const displacedSessionLock = `${replacementPaths.sessionLock}.displaced`;
345
+ await fs.rename(replacementPaths.sessionLock, displacedSessionLock);
346
+ await ensureLockFile(replacementPaths.sessionLock);
347
+ await expectCode(
348
+ () => replacementBundle.health(),
349
+ "INTEGRATION_STORAGE_LOCK_POISONED"
350
+ );
351
+ await expectCode(
352
+ () => replacementBundle.preflight(),
353
+ "INTEGRATION_RUNTIME_BUNDLE_POISONED"
354
+ );
355
+ assert.deepEqual(await replacementBundle.close(), { closed: true, poisoned: true });
356
+
357
+ const failedPaths = await provisionRuntimeRoot(failedRoot, { omitEventLock: true });
358
+ await expectCode(
359
+ () => openIntegrationProductionRuntimeBundle({ stateRoot: failedRoot }),
360
+ "INTEGRATION_STORAGE_UNAVAILABLE"
361
+ );
362
+ await ensureLockFile(failedPaths.eventLedgerLock);
363
+ const recoveredFromFactoryFailure = await openIntegrationProductionRuntimeBundle({
364
+ stateRoot: failedRoot,
365
+ });
366
+ assert.equal((await recoveredFromFactoryFailure.health()).healthy, true);
367
+ await recoveredFromFactoryFailure.close();
368
+
369
+ const [cliSource, serverSource, bundleSource] = await Promise.all([
370
+ fs.readFile(new URL("../src/integration-cli.js", import.meta.url), "utf8"),
371
+ fs.readFile(new URL("../src/integration-server.js", import.meta.url), "utf8"),
372
+ fs.readFile(new URL("../src/integration-production-runtime-bundle.js", import.meta.url), "utf8"),
373
+ ]);
374
+ assert.match(cliSource, /checkIntegrationProductionRuntimeBundle/u);
375
+ assert.doesNotMatch(serverSource, /integration-production-runtime-bundle/u);
376
+ assert.doesNotMatch(
377
+ bundleSource,
378
+ /acquireRetainedIntegrationRuntimeRepositoryFence|createAgintiIntegrationRuntimeAuthority|createNativeIntegrationSessionService|createFileIntegrationIdempotencyStore/u
379
+ );
380
+ } finally {
381
+ await fs.chmod(poisonRoot, 0o700).catch(() => {});
382
+ await fs.rm(stateRoot, { recursive: true, force: true });
383
+ await fs.rm(poisonRoot, { recursive: true, force: true });
384
+ await fs.rm(lockModeRoot, { recursive: true, force: true });
385
+ await fs.rm(lockReplacementRoot, { recursive: true, force: true });
386
+ await fs.rm(failedRoot, { recursive: true, force: true });
387
+ }
388
+
389
+ process.stdout.write("integration production runtime bundle smoke: ok\n");
390
+ }
391
+
392
+ run().catch((error) => {
393
+ process.stderr.write(
394
+ `integration production runtime bundle smoke: failed (${String(error?.publicCode || error?.code || error?.name || "ERROR")})\n`
395
+ );
396
+ process.stderr.write(`${String(error?.stack || error?.message || error)}\n`);
397
+ process.exitCode = 1;
398
+ });
@@ -482,15 +482,20 @@ async function runCore() {
482
482
  const authorities = [];
483
483
  let consumerMocks = [];
484
484
  try {
485
- const [serverSource, runtimeSource, sessionSource] = await Promise.all([
485
+ const [serverSource, runtimeSource, sessionSource, productionBundleSource] = await Promise.all([
486
486
  fs.readFile(new URL("../src/integration-server.js", import.meta.url), "utf8"),
487
487
  fs.readFile(new URL("../src/integration-runtime-authority.js", import.meta.url), "utf8"),
488
488
  fs.readFile(new URL("../src/integration-session-service.js", import.meta.url), "utf8"),
489
+ fs.readFile(new URL("../src/integration-production-runtime-bundle.js", import.meta.url), "utf8"),
489
490
  ]);
490
491
  assert.match(serverSource, /export const INTEGRATION_MOUNT_CAPABILITY_ENABLED = false;/u);
491
492
  assert.equal(serverSource.includes("createRetainedIntegrationEventLedgerBundle"), false);
492
493
  assert.equal(runtimeSource.includes("createRetainedIntegrationEventLedgerBundle"), false);
493
494
  assert.equal(sessionSource.includes("createRetainedIntegrationEventLedgerBundle"), false);
495
+ assert.equal(productionBundleSource.includes("createRetainedIntegrationEventLedgerBundle"), true);
496
+ assert.match(productionBundleSource, /capabilityEnabled:\s*false/u);
497
+ assert.match(productionBundleSource, /httpServingEnabled:\s*false/u);
498
+ assert.match(productionBundleSource, /runtimeActivationIncluded:\s*false/u);
494
499
 
495
500
  const main = await openFixture(path.join(smokeRoot, "main"), "retained-ledger-bundle-main");
496
501
  authorities.push(main.authority);
@@ -791,6 +791,7 @@ async function runStaticBoundaryChecks(surface) {
791
791
  assert.match(config, /capability:\s*Object\.freeze\(\{ enabled: false \}\)/u);
792
792
  const sourceDirectory = fileURLToPath(new URL("../src/", import.meta.url));
793
793
  for (const consumerName of [
794
+ "integration-production-runtime-bundle.js",
794
795
  "integration-native-executor.js",
795
796
  "integration-runtime-authority.js",
796
797
  "integration-native-runtime-roots.js",
@@ -800,6 +801,18 @@ async function runStaticBoundaryChecks(surface) {
800
801
  "session-store.js",
801
802
  ]) {
802
803
  const consumer = await fs.readFile(path.join(sourceDirectory, consumerName), "utf8");
804
+ if (consumerName === "integration-production-runtime-bundle.js") {
805
+ assert.match(consumer, /capabilityEnabled:\s*false/u);
806
+ assert.match(consumer, /runtimeActivationIncluded:\s*false/u);
807
+ assert.match(consumer, /repositoryFenceAcquisitionIncluded:\s*false/u);
808
+ assert.match(consumer, /descriptorBoundIdempotencyStore:\s*false/u);
809
+ assert.doesNotMatch(
810
+ consumer,
811
+ /acquireRetainedIntegrationRuntimeRepositoryFence|createAgintiIntegrationRuntimeAuthority|createIntegrationServer|createNativeIntegrationSessionService/u,
812
+ `${consumerName} may compose the repository-state surface only before runtime activation.`
813
+ );
814
+ continue;
815
+ }
803
816
  assert.doesNotMatch(
804
817
  consumer,
805
818
  /integration-retained-native-session-repository-state|(?:create|assert)RetainedIntegrationNativeSessionRepositoryState/u,