@llblab/pi-kit 0.38.4 → 0.39.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.
- package/CHANGELOG.md +5 -0
- package/README.md +1 -1
- package/node_modules/@llblab/pi-actors/AGENTS.md +108 -20
- package/node_modules/@llblab/pi-actors/BACKLOG.md +207 -4
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +13 -0
- package/node_modules/@llblab/pi-actors/README.md +31 -1
- package/node_modules/@llblab/pi-actors/dist/index.js +1 -1
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +131 -62
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.js +3 -2
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.js +263 -129
- package/node_modules/@llblab/pi-actors/dist/lib/execution-files.d.ts +32 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-files.js +128 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-output.js +5 -4
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.d.ts +19 -1
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.js +62 -26
- package/node_modules/@llblab/pi-actors/dist/lib/execution.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/execution.js +6 -1
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +9 -2
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +92 -14
- package/node_modules/@llblab/pi-actors/dist/lib/file-state.js +21 -2
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.js +2 -2
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.d.ts +25 -7
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +562 -262
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.d.ts +20 -10
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.js +80 -91
- package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.js +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +15 -1
- package/node_modules/@llblab/pi-actors/dist/lib/observability.js +216 -99
- package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +5 -4
- package/node_modules/@llblab/pi-actors/dist/lib/pi.js +64 -10
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.js +220 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.js +30 -6
- package/node_modules/@llblab/pi-actors/dist/lib/registry.js +270 -36
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +213 -5
- package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +1909 -40
- package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.d.ts +107 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.js +412 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +9 -2
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +283 -60
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.d.ts +26 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.js +68 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.d.ts +451 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.js +2315 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.d.ts +97 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.js +368 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.js +46 -7
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.d.ts +78 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.js +334 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.js +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.d.ts +80 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.js +287 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.d.ts +110 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.js +282 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.d.ts +66 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.js +349 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.d.ts +73 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.js +227 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.d.ts +141 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.js +292 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.d.ts +10 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.js +36 -4
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.d.ts +46 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.js +114 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.d.ts +34 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.js +158 -26
- package/node_modules/@llblab/pi-actors/dist/lib/runs-results.d.ts +116 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-results.js +518 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.d.ts +15 -2
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.js +148 -9
- package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.d.ts +95 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.js +470 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.d.ts +58 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.js +92 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.d.ts +2 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.js +44 -3
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.d.ts +15 -1
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.js +337 -13
- package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.d.ts +105 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.js +501 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +14 -3
- package/node_modules/@llblab/pi-actors/dist/lib/runtime.js +22 -3
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +59 -3
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.js +14 -8
- package/node_modules/@llblab/pi-actors/dist/lib/temp.d.ts +2 -4
- package/node_modules/@llblab/pi-actors/dist/lib/temp.js +4 -56
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.js +13 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.d.ts +1 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +110 -43
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.js +18 -6
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.d.ts +4 -1
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.js +126 -31
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.d.ts +31 -3
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.js +311 -47
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.d.ts +3 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.js +29 -7
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +192 -43
- package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +272 -194
- package/node_modules/@llblab/pi-actors/dist/scripts/conformance.mjs +14 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +46 -2
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/diagnostics.md +40 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +55 -1
- package/node_modules/@llblab/pi-actors/docs/README.md +9 -1
- package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +84 -15
- package/node_modules/@llblab/pi-actors/docs/agent-experience.md +216 -0
- package/node_modules/@llblab/pi-actors/docs/async-runs.md +18 -2
- package/node_modules/@llblab/pi-actors/docs/composition-transport.md +103 -0
- package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +204 -4
- package/node_modules/@llblab/pi-actors/docs/inspection.md +38 -2
- package/node_modules/@llblab/pi-actors/docs/output-projection-map.md +130 -0
- package/node_modules/@llblab/pi-actors/docs/releasing.md +19 -2
- package/node_modules/@llblab/pi-actors/docs/run-supervision.md +1622 -0
- package/node_modules/@llblab/pi-actors/docs/template-recipes.md +4 -0
- package/node_modules/@llblab/pi-actors/docs/windows-process-observation.md +248 -0
- package/node_modules/@llblab/pi-actors/index.ts +1 -1
- package/node_modules/@llblab/pi-actors/lib/async-runs.ts +164 -73
- package/node_modules/@llblab/pi-actors/lib/automatic-review-runtime.ts +4 -2
- package/node_modules/@llblab/pi-actors/lib/command-templates.ts +287 -138
- package/node_modules/@llblab/pi-actors/lib/execution-files.ts +118 -0
- package/node_modules/@llblab/pi-actors/lib/execution-output.ts +4 -4
- package/node_modules/@llblab/pi-actors/lib/execution-sessions.ts +57 -27
- package/node_modules/@llblab/pi-actors/lib/execution.ts +8 -0
- package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +102 -12
- package/node_modules/@llblab/pi-actors/lib/file-state.ts +16 -2
- package/node_modules/@llblab/pi-actors/lib/inspector-command.ts +2 -2
- package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +524 -261
- package/node_modules/@llblab/pi-actors/lib/inspector.ts +101 -130
- package/node_modules/@llblab/pi-actors/lib/limits.ts +1 -0
- package/node_modules/@llblab/pi-actors/lib/observability.ts +235 -116
- package/node_modules/@llblab/pi-actors/lib/pi.ts +59 -11
- package/node_modules/@llblab/pi-actors/lib/recipe-projection.ts +232 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-context.ts +27 -6
- package/node_modules/@llblab/pi-actors/lib/registry.ts +266 -36
- package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +1737 -49
- package/node_modules/@llblab/pi-actors/lib/run-supervision.ts +411 -0
- package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +237 -73
- package/node_modules/@llblab/pi-actors/lib/runs-artifacts.ts +73 -1
- package/node_modules/@llblab/pi-actors/lib/runs-context-exports.ts +1871 -0
- package/node_modules/@llblab/pi-actors/lib/runs-context-index.ts +372 -0
- package/node_modules/@llblab/pi-actors/lib/runs-control-delivery.ts +36 -18
- package/node_modules/@llblab/pi-actors/lib/runs-control.ts +297 -1
- package/node_modules/@llblab/pi-actors/lib/runs-controls.ts +3 -1
- package/node_modules/@llblab/pi-actors/lib/runs-descendant-launches.ts +338 -0
- package/node_modules/@llblab/pi-actors/lib/runs-execution-evidence.ts +302 -0
- package/node_modules/@llblab/pi-actors/lib/runs-index.ts +345 -17
- package/node_modules/@llblab/pi-actors/lib/runs-native-launches.ts +270 -0
- package/node_modules/@llblab/pi-actors/lib/runs-outcomes.ts +377 -0
- package/node_modules/@llblab/pi-actors/lib/runs-ownership.ts +37 -4
- package/node_modules/@llblab/pi-actors/lib/runs-process-windows-mi.ts +113 -0
- package/node_modules/@llblab/pi-actors/lib/runs-process.ts +210 -34
- package/node_modules/@llblab/pi-actors/lib/runs-results.ts +601 -0
- package/node_modules/@llblab/pi-actors/lib/runs-retention.ts +134 -10
- package/node_modules/@llblab/pi-actors/lib/runs-session-exports.ts +406 -0
- package/node_modules/@llblab/pi-actors/lib/runs-snapshot.ts +143 -0
- package/node_modules/@llblab/pi-actors/lib/runs-start.ts +44 -2
- package/node_modules/@llblab/pi-actors/lib/runs-status.ts +252 -10
- package/node_modules/@llblab/pi-actors/lib/runs-supervision.ts +394 -0
- package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +14 -3
- package/node_modules/@llblab/pi-actors/lib/runtime.ts +22 -3
- package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +76 -4
- package/node_modules/@llblab/pi-actors/lib/state-readers.ts +16 -7
- package/node_modules/@llblab/pi-actors/lib/temp.ts +3 -56
- package/node_modules/@llblab/pi-actors/lib/tools-access.ts +13 -0
- package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +110 -51
- package/node_modules/@llblab/pi-actors/lib/tools-local.ts +37 -24
- package/node_modules/@llblab/pi-actors/lib/tools-message.ts +120 -37
- package/node_modules/@llblab/pi-actors/lib/tools-response.ts +273 -50
- package/node_modules/@llblab/pi-actors/lib/tools-spawn.ts +31 -10
- package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +165 -42
- package/node_modules/@llblab/pi-actors/package.json +10 -6
- package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +272 -194
- package/node_modules/@llblab/pi-actors/scripts/conformance.mjs +14 -2
- package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +46 -2
- package/node_modules/@llblab/pi-actors/skills/actors/references/diagnostics.md +40 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +55 -1
- package/node_modules/yaml/LICENSE +13 -0
- package/node_modules/yaml/README.md +172 -0
- package/node_modules/yaml/bin.mjs +11 -0
- package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
- package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
- package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
- package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
- package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
- package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
- package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
- package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
- package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
- package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
- package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
- package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
- package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
- package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
- package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
- package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
- package/node_modules/yaml/browser/dist/errors.js +57 -0
- package/node_modules/yaml/browser/dist/index.js +17 -0
- package/node_modules/yaml/browser/dist/log.js +11 -0
- package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
- package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
- package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
- package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
- package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
- package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
- package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
- package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
- package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
- package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
- package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
- package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
- package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
- package/node_modules/yaml/browser/dist/public-api.js +102 -0
- package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
- package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
- package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
- package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
- package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
- package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
- package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
- package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
- package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
- package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
- package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
- package/node_modules/yaml/browser/dist/util.js +11 -0
- package/node_modules/yaml/browser/dist/visit.js +233 -0
- package/node_modules/yaml/browser/index.js +5 -0
- package/node_modules/yaml/browser/package.json +3 -0
- package/node_modules/yaml/dist/cli.d.ts +8 -0
- package/node_modules/yaml/dist/cli.mjs +201 -0
- package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
- package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
- package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
- package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
- package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
- package/node_modules/yaml/dist/compose/compose-node.js +112 -0
- package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
- package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
- package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
- package/node_modules/yaml/dist/compose/composer.js +224 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
- package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
- package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
- package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
- package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
- package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
- package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
- package/node_modules/yaml/dist/doc/Document.js +337 -0
- package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
- package/node_modules/yaml/dist/doc/anchors.js +76 -0
- package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
- package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
- package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
- package/node_modules/yaml/dist/doc/createNode.js +90 -0
- package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
- package/node_modules/yaml/dist/doc/directives.js +178 -0
- package/node_modules/yaml/dist/errors.d.ts +21 -0
- package/node_modules/yaml/dist/errors.js +62 -0
- package/node_modules/yaml/dist/index.d.ts +25 -0
- package/node_modules/yaml/dist/index.js +50 -0
- package/node_modules/yaml/dist/log.d.ts +3 -0
- package/node_modules/yaml/dist/log.js +19 -0
- package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/Alias.js +118 -0
- package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
- package/node_modules/yaml/dist/nodes/Collection.js +151 -0
- package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/Node.js +40 -0
- package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
- package/node_modules/yaml/dist/nodes/Pair.js +39 -0
- package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
- package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
- package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
- package/node_modules/yaml/dist/nodes/identity.js +53 -0
- package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/toJS.js +39 -0
- package/node_modules/yaml/dist/options.d.ts +350 -0
- package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
- package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
- package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
- package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
- package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
- package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
- package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
- package/node_modules/yaml/dist/parse/cst.js +112 -0
- package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
- package/node_modules/yaml/dist/parse/lexer.js +723 -0
- package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
- package/node_modules/yaml/dist/parse/line-counter.js +41 -0
- package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
- package/node_modules/yaml/dist/parse/parser.js +980 -0
- package/node_modules/yaml/dist/public-api.d.ts +44 -0
- package/node_modules/yaml/dist/public-api.js +107 -0
- package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
- package/node_modules/yaml/dist/schema/Schema.js +39 -0
- package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/map.js +19 -0
- package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
- package/node_modules/yaml/dist/schema/common/null.js +17 -0
- package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/seq.js +19 -0
- package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/string.js +16 -0
- package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/bool.js +21 -0
- package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/float.js +47 -0
- package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/int.js +42 -0
- package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/core/schema.js +25 -0
- package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
- package/node_modules/yaml/dist/schema/json/schema.js +64 -0
- package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
- package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
- package/node_modules/yaml/dist/schema/tags.js +99 -0
- package/node_modules/yaml/dist/schema/types.d.ts +92 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
- package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
- package/node_modules/yaml/dist/stringify/stringify.js +132 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
- package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
- package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
- package/node_modules/yaml/dist/test-events.d.ts +4 -0
- package/node_modules/yaml/dist/test-events.js +134 -0
- package/node_modules/yaml/dist/util.d.ts +16 -0
- package/node_modules/yaml/dist/util.js +28 -0
- package/node_modules/yaml/dist/visit.d.ts +102 -0
- package/node_modules/yaml/dist/visit.js +236 -0
- package/node_modules/yaml/package.json +97 -0
- package/node_modules/yaml/util.js +2 -0
- package/package.json +2 -2
- package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +0 -16
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +0 -57
- package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +0 -79
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded Run observation projection.
|
|
3
|
+
* Owns: one data-only snapshot shape from already-admitted identity/lifecycle/timing facts.
|
|
4
|
+
* Excludes: evidence reads/admission, reference authorization/redaction, clocks, exports,
|
|
5
|
+
* lifecycle mutation, delivery acceptance, and native work/control/scope authority.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { RUN_DELIVERY_MODEL_MAX_BYTES } from "./limits.ts";
|
|
9
|
+
|
|
10
|
+
export interface RunSnapshotIdentity {
|
|
11
|
+
readonly run: string;
|
|
12
|
+
readonly run_instance_id: string;
|
|
13
|
+
readonly ownerId?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Kernel read-model inputs, not raw Run metadata or serialized proof capabilities. */
|
|
17
|
+
export interface RunSnapshotFacts {
|
|
18
|
+
readonly identity: RunSnapshotIdentity;
|
|
19
|
+
readonly captured_at: string;
|
|
20
|
+
readonly timing:
|
|
21
|
+
| { readonly basis: "live" | "terminal"; readonly elapsed_ms: number }
|
|
22
|
+
| { readonly basis: "unproven" };
|
|
23
|
+
readonly lifecycle:
|
|
24
|
+
| { readonly status: "running"; readonly phase?: "stopping" }
|
|
25
|
+
| { readonly status: "done" | "failed" }
|
|
26
|
+
| { readonly status: "unproven" };
|
|
27
|
+
readonly cwd: string;
|
|
28
|
+
readonly context_index?: {
|
|
29
|
+
readonly identity: RunSnapshotIdentity;
|
|
30
|
+
readonly path: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RunSnapshot {
|
|
35
|
+
readonly kind: "run_snapshot";
|
|
36
|
+
readonly run: string;
|
|
37
|
+
readonly run_instance_id: string;
|
|
38
|
+
readonly captured_at: string;
|
|
39
|
+
readonly elapsed_ms: number;
|
|
40
|
+
readonly status: "running" | "done" | "failed";
|
|
41
|
+
readonly phase?: "stopping";
|
|
42
|
+
readonly cwd: string;
|
|
43
|
+
readonly evidence: string | null;
|
|
44
|
+
readonly evidence_error?: "index_unavailable";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type SnapshotUnavailableReason =
|
|
48
|
+
| "identity_unavailable"
|
|
49
|
+
| "identity_mismatch"
|
|
50
|
+
| "observation_unavailable"
|
|
51
|
+
| "lifecycle_unproven"
|
|
52
|
+
| "timing_unproven"
|
|
53
|
+
| "references_unavailable"
|
|
54
|
+
| "snapshot_too_large";
|
|
55
|
+
|
|
56
|
+
export type RunSnapshotProjection =
|
|
57
|
+
| { readonly state: "available"; readonly snapshot: Readonly<RunSnapshot> }
|
|
58
|
+
| { readonly state: "unavailable"; readonly reason: SnapshotUnavailableReason };
|
|
59
|
+
|
|
60
|
+
function record(value: unknown): Record<string, unknown> | undefined {
|
|
61
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
62
|
+
? value as Record<string, unknown>
|
|
63
|
+
: undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function own(value: Record<string, unknown> | undefined, key: string): unknown {
|
|
67
|
+
return value && Object.hasOwn(value, key) ? value[key] : undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function boundedText(value: unknown): value is string {
|
|
71
|
+
return typeof value === "string" && value.length > 0 && value.length <= RUN_DELIVERY_MODEL_MAX_BYTES;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readIdentity(value: unknown): RunSnapshotIdentity | undefined {
|
|
75
|
+
const source = record(value);
|
|
76
|
+
const run = own(source, "run");
|
|
77
|
+
const generation = own(source, "run_instance_id");
|
|
78
|
+
if (!boundedText(run) || /[^A-Za-z0-9_.-]/u.test(run) || !boundedText(generation)) return undefined;
|
|
79
|
+
if (source && Object.hasOwn(source, "ownerId")) {
|
|
80
|
+
if (!boundedText(source.ownerId)) return undefined;
|
|
81
|
+
return { run, run_instance_id: generation, ownerId: source.ownerId };
|
|
82
|
+
}
|
|
83
|
+
if (source?.ownerId !== undefined) return undefined;
|
|
84
|
+
return { run, run_instance_id: generation };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function sameIdentity(left: RunSnapshotIdentity, right: RunSnapshotIdentity): boolean {
|
|
88
|
+
return left.run === right.run && left.run_instance_id === right.run_instance_id && left.ownerId === right.ownerId;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function readableReference(value: unknown): value is string {
|
|
92
|
+
return boundedText(value) && !/[\u0000-\u001f\u007f]/u.test(value);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function unavailable(reason: SnapshotUnavailableReason): RunSnapshotProjection {
|
|
96
|
+
return Object.freeze({ state: "unavailable", reason });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Facts and curated references must be admitted by their owners before projection; no I/O or authority is acquired here. */
|
|
100
|
+
export function projectRunSnapshot(expected: unknown, facts: unknown): Readonly<RunSnapshotProjection> {
|
|
101
|
+
const expectedIdentity = readIdentity(expected);
|
|
102
|
+
const source = record(facts);
|
|
103
|
+
const identity = readIdentity(own(source, "identity"));
|
|
104
|
+
if (!expectedIdentity || !identity) return unavailable("identity_unavailable");
|
|
105
|
+
if (!sameIdentity(expectedIdentity, identity)) return unavailable("identity_mismatch");
|
|
106
|
+
const capturedAt = own(source, "captured_at");
|
|
107
|
+
if (!boundedText(capturedAt)) return unavailable("observation_unavailable");
|
|
108
|
+
const capturedMs = Date.parse(capturedAt);
|
|
109
|
+
if (!Number.isSafeInteger(capturedMs) || new Date(capturedMs).toISOString() !== capturedAt) {
|
|
110
|
+
return unavailable("observation_unavailable");
|
|
111
|
+
}
|
|
112
|
+
const lifecycle = record(own(source, "lifecycle"));
|
|
113
|
+
const status = own(lifecycle, "status");
|
|
114
|
+
const phase = own(lifecycle, "phase");
|
|
115
|
+
if ((status !== "running" && status !== "done" && status !== "failed") ||
|
|
116
|
+
(phase !== undefined && (status !== "running" || phase !== "stopping"))) {
|
|
117
|
+
return unavailable("lifecycle_unproven");
|
|
118
|
+
}
|
|
119
|
+
const timing = record(own(source, "timing"));
|
|
120
|
+
const elapsedMs = own(timing, "elapsed_ms");
|
|
121
|
+
if (own(timing, "basis") !== (status === "running" ? "live" : "terminal") ||
|
|
122
|
+
typeof elapsedMs !== "number" || !Number.isSafeInteger(elapsedMs) || elapsedMs < 0) {
|
|
123
|
+
return unavailable("timing_unproven");
|
|
124
|
+
}
|
|
125
|
+
const cwd = own(source, "cwd");
|
|
126
|
+
if (typeof cwd === "string" && cwd.length > RUN_DELIVERY_MODEL_MAX_BYTES) return unavailable("snapshot_too_large");
|
|
127
|
+
if (!readableReference(cwd)) return unavailable("references_unavailable");
|
|
128
|
+
const index = record(own(source, "context_index"));
|
|
129
|
+
const indexIdentity = readIdentity(own(index, "identity"));
|
|
130
|
+
const indexPath = own(index, "path");
|
|
131
|
+
const evidence = indexIdentity && sameIdentity(identity, indexIdentity) && readableReference(indexPath) ? indexPath : null;
|
|
132
|
+
const snapshot: Readonly<RunSnapshot> = Object.freeze({
|
|
133
|
+
kind: "run_snapshot", run: identity.run, run_instance_id: identity.run_instance_id,
|
|
134
|
+
captured_at: capturedAt, elapsed_ms: elapsedMs, status,
|
|
135
|
+
...(phase === "stopping" ? { phase } : {}), cwd, evidence,
|
|
136
|
+
...(evidence === null ? { evidence_error: "index_unavailable" } as const : {}),
|
|
137
|
+
});
|
|
138
|
+
// This is a row ceiling, not a second allowance: delivery still bounds the combined packet.
|
|
139
|
+
if (Buffer.byteLength(JSON.stringify(snapshot), "utf8") > RUN_DELIVERY_MODEL_MAX_BYTES) {
|
|
140
|
+
return unavailable("snapshot_too_large");
|
|
141
|
+
}
|
|
142
|
+
return Object.freeze({ state: "available", snapshot });
|
|
143
|
+
}
|
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
* preparation before a new runner process is spawned.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { rmSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
7
|
+
import { readdirSync, rmSync } from "node:fs";
|
|
8
|
+
import { basename, join } from "node:path";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
acquireFileMutationLock,
|
|
12
|
+
mutationLockPath,
|
|
12
13
|
type FileMutationLockOptions,
|
|
13
14
|
} from "./file-state.ts";
|
|
15
|
+
import { assertNoRetainedDescendantLaunchScope } from "./runs-descendant-launches.ts";
|
|
16
|
+
import { assertNoRetainedNativeLaunchScope } from "./runs-native-launches.ts";
|
|
17
|
+
import { isRunStopResultCapture, readRunStopClaim, RUN_STOP_CLAIM_FILE } from "./runs-outcomes.ts";
|
|
18
|
+
import { RUN_STATE_OWNERSHIP_FILE } from "./runs-ownership.ts";
|
|
14
19
|
import {
|
|
15
20
|
isAlive,
|
|
16
21
|
verifyRunProcessIdentity,
|
|
@@ -19,6 +24,19 @@ import {
|
|
|
19
24
|
|
|
20
25
|
type RunJsonReader = (path: string) => Record<string, unknown> | undefined;
|
|
21
26
|
|
|
27
|
+
function assertNoPendingStop(stateDir: string, meta: Record<string, unknown>): void {
|
|
28
|
+
const stop = readRunStopClaim(stateDir, meta);
|
|
29
|
+
if (stop.state === "pending" || stop.state === "invalid") {
|
|
30
|
+
throw new Error("Run stop is pending or unproven; confirm the complete owned scope before restarting.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function assertNoUnresolvedCapture(result: Record<string, unknown> | undefined): void {
|
|
35
|
+
if (isRunStopResultCapture(result)) {
|
|
36
|
+
throw new Error("Run stop result capture is not confirmed terminal evidence.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
22
40
|
export function readActiveOwnedRunState(
|
|
23
41
|
stateDir: string,
|
|
24
42
|
readJson: RunJsonReader,
|
|
@@ -26,7 +44,9 @@ export function readActiveOwnedRunState(
|
|
|
26
44
|
): Record<string, unknown> | undefined {
|
|
27
45
|
const meta = readJson(join(stateDir, "run.json"));
|
|
28
46
|
if (!meta) return undefined;
|
|
47
|
+
assertNoPendingStop(stateDir, meta);
|
|
29
48
|
const result = readJson(join(stateDir, "result.json"));
|
|
49
|
+
assertNoUnresolvedCapture(result);
|
|
30
50
|
if (typeof result?.completedAt === "string") return undefined;
|
|
31
51
|
const pid = Number(meta.pid || 0);
|
|
32
52
|
if (!pid || !isAlive(pid)) return undefined;
|
|
@@ -52,6 +72,8 @@ export function assertNoActiveRunState(
|
|
|
52
72
|
readJson: RunJsonReader,
|
|
53
73
|
runnerPath: string,
|
|
54
74
|
): void {
|
|
75
|
+
assertNoRetainedDescendantLaunchScope(stateDir);
|
|
76
|
+
assertNoRetainedNativeLaunchScope(stateDir);
|
|
55
77
|
const meta = readActiveOwnedRunState(stateDir, readJson, runnerPath);
|
|
56
78
|
if (meta) {
|
|
57
79
|
throw new Error(
|
|
@@ -60,6 +82,21 @@ export function assertNoActiveRunState(
|
|
|
60
82
|
}
|
|
61
83
|
}
|
|
62
84
|
|
|
85
|
+
/** Prepare-only metadata must neither replace an earlier Run nor erase unrelated retained evidence. */
|
|
86
|
+
export function assertFreshRunPreparationState(stateDir: string): void {
|
|
87
|
+
assertNoRetainedDescendantLaunchScope(stateDir);
|
|
88
|
+
let entries: string[];
|
|
89
|
+
try { entries = readdirSync(stateDir); }
|
|
90
|
+
catch (error) {
|
|
91
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
const lock = basename(mutationLockPath(join(stateDir, ".lifecycle")));
|
|
95
|
+
if (entries.some((name) => name !== RUN_STATE_OWNERSHIP_FILE && name !== lock && !name.startsWith(`${lock}.`))) {
|
|
96
|
+
throw new Error("Run descendant preparation requires fresh state without published Run metadata or retained evidence.");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
63
100
|
export function acquireStateStartLock(
|
|
64
101
|
stateDir: string,
|
|
65
102
|
options: FileMutationLockOptions = {},
|
|
@@ -72,7 +109,11 @@ export function prepareStateDirForStart(
|
|
|
72
109
|
readJson: RunJsonReader,
|
|
73
110
|
_runnerPath: string,
|
|
74
111
|
): void {
|
|
112
|
+
assertNoRetainedDescendantLaunchScope(stateDir);
|
|
113
|
+
assertNoRetainedNativeLaunchScope(stateDir);
|
|
75
114
|
const existing = readJson(join(stateDir, "run.json"));
|
|
115
|
+
assertNoPendingStop(stateDir, existing ?? {});
|
|
116
|
+
assertNoUnresolvedCapture(readJson(join(stateDir, "result.json")));
|
|
76
117
|
const existingPid = Number(existing?.pid || 0);
|
|
77
118
|
if (existingPid && isAlive(existingPid)) {
|
|
78
119
|
const identity = verifyRunProcessIdentity(
|
|
@@ -102,6 +143,7 @@ export function prepareStateDirForStart(
|
|
|
102
143
|
"execution.json",
|
|
103
144
|
"progress.json",
|
|
104
145
|
"result.json",
|
|
146
|
+
RUN_STOP_CLAIM_FILE,
|
|
105
147
|
"stderr.log",
|
|
106
148
|
"stdout.log",
|
|
107
149
|
"terminal-delivery-failure.json",
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Async run status and log readers.
|
|
3
|
-
* Owns: status derivation
|
|
3
|
+
* Owns: status derivation, readonly canonical snapshot-fact admission and bounded log/event tails.
|
|
4
|
+
* Excludes: snapshot timing/visibility authority, export publication, scheduling and native scope closure.
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
-
import {
|
|
7
|
+
import { closeSync, constants, existsSync, fstatSync, lstatSync, openSync, readFileSync, readSync, type BigIntStats } from "node:fs";
|
|
8
|
+
import { platform } from "node:os";
|
|
9
|
+
import { isAbsolute, join } from "node:path";
|
|
10
|
+
import { types as UtilTypes } from "node:util";
|
|
8
11
|
|
|
12
|
+
import { RUN_DELIVERY_MODEL_MAX_BYTES } from "./limits.ts";
|
|
13
|
+
import { readRunContextIdentity, readRunContextIndex, RUN_CONTEXT_INDEX_FILE, RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES } from "./runs-context-index.ts";
|
|
14
|
+
import { RUN_OUTCOME_PROTOCOL, RUN_STOP_CLAIM_FILE, isRunStopResultCapture, readRunNaturalOutcomeSnapshot, readRunStopClaim } from "./runs-outcomes.ts";
|
|
15
|
+
import type { RunSnapshotFacts } from "./runs-snapshot.ts";
|
|
16
|
+
import { RUN_STATE_OWNERSHIP_FILE } from "./runs-ownership.ts";
|
|
9
17
|
import {
|
|
18
|
+
isAlive,
|
|
19
|
+
observeRunProcessExit,
|
|
20
|
+
readWindowsProcessIdentities,
|
|
21
|
+
WINDOWS_IDENTITY_QUERY_PID_LIMIT,
|
|
10
22
|
verifyRunProcessIdentity,
|
|
11
23
|
type RunProcessIdentity,
|
|
24
|
+
type RunProcessIdentityResult,
|
|
12
25
|
} from "./runs-process.ts";
|
|
13
|
-
import { readJsonlFileResilient } from "./state-readers.ts";
|
|
26
|
+
import { readJsonFileResilient, readJsonlFileResilient } from "./state-readers.ts";
|
|
14
27
|
|
|
15
28
|
export type AsyncRunStatus =
|
|
16
29
|
| "running"
|
|
@@ -50,17 +63,30 @@ export function buildRunStatus(
|
|
|
50
63
|
_runnerPath: string,
|
|
51
64
|
_runnerIdentityGraceMs: number,
|
|
52
65
|
): Record<string, unknown> {
|
|
53
|
-
|
|
66
|
+
return deriveRunStatus(stateDir, meta, readJson, (pid, expected) => verifyRunProcessIdentity(pid, expected));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function deriveRunStatus(stateDir: string, meta: Record<string, unknown>, readJson: RunJsonReader,
|
|
70
|
+
observeIdentity: (pid: number, expected: RunProcessIdentity | undefined) => RunProcessIdentityResult): Record<string, unknown> {
|
|
71
|
+
const snapshot = readRunNaturalOutcomeSnapshot(stateDir, meta, readJson);
|
|
72
|
+
const rawResult = snapshot.result;
|
|
73
|
+
const staleResult = rawResult?.run_instance_id !== undefined && rawResult.run_instance_id !== meta.run_instance_id;
|
|
74
|
+
const result = staleResult ? undefined : rawResult;
|
|
75
|
+
const stop = readRunStopClaim(stateDir, meta);
|
|
76
|
+
const unresolvedCapture = isRunStopResultCapture(result);
|
|
77
|
+
const natural = snapshot.outcome;
|
|
78
|
+
const stopping = natural.state !== "accepted" && (stop.state === "pending" || stop.state === "invalid" || unresolvedCapture);
|
|
54
79
|
const pid = Number(meta.pid || 0);
|
|
55
|
-
const processIdentity =
|
|
56
|
-
pid,
|
|
57
|
-
meta.process_identity as RunProcessIdentity | undefined,
|
|
58
|
-
);
|
|
80
|
+
const processIdentity = observeIdentity(pid, meta.process_identity as RunProcessIdentity | undefined);
|
|
59
81
|
const aliveOwnedRunner = Boolean(
|
|
60
82
|
pid &&
|
|
61
83
|
(processIdentity.valid || processIdentity.status === "unsupported_proof"),
|
|
62
84
|
);
|
|
63
|
-
const status: AsyncRunStatus =
|
|
85
|
+
const status: AsyncRunStatus = natural.state === "accepted"
|
|
86
|
+
? natural.status
|
|
87
|
+
: stopping
|
|
88
|
+
? "running"
|
|
89
|
+
: result
|
|
64
90
|
? Number(result.code ?? 0) === 0
|
|
65
91
|
? "done"
|
|
66
92
|
: "failed"
|
|
@@ -76,6 +102,11 @@ export function buildRunStatus(
|
|
|
76
102
|
traceFile: join(stateDir, "trace.jsonl"),
|
|
77
103
|
executionFile: join(stateDir, "execution.json"),
|
|
78
104
|
process_identity_status: processIdentity.status,
|
|
105
|
+
...(stopping ? { phase: "stopping", stopped: false } : {}),
|
|
106
|
+
...(stopping && stop.state === "pending" ? { stop_reason: stop.claim.reason, stop_claim_id: stop.claim.claim_id } : {}),
|
|
107
|
+
...(stop.state === "invalid" || (unresolvedCapture && stop.state !== "pending")
|
|
108
|
+
? { stop_error: "claim_unavailable" } : {}),
|
|
109
|
+
...(staleResult ? { result_error: "generation_mismatch" } : {}),
|
|
79
110
|
progress: readJson(join(stateDir, "progress.json")) || null,
|
|
80
111
|
result: result || null,
|
|
81
112
|
...(terminalDeliveryFailure
|
|
@@ -88,6 +119,217 @@ export function buildRunStatus(
|
|
|
88
119
|
};
|
|
89
120
|
}
|
|
90
121
|
|
|
122
|
+
interface InventorySource {
|
|
123
|
+
stamp: BigIntStats;
|
|
124
|
+
bytes: Buffer;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function readInventorySource(path: string): InventorySource | undefined {
|
|
128
|
+
let fd: number | undefined;
|
|
129
|
+
try {
|
|
130
|
+
const stamp = snapshotStamp(path);
|
|
131
|
+
if (!stamp?.isFile() || stamp.size > BigInt(RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES)) return undefined;
|
|
132
|
+
fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
|
|
133
|
+
const opened = fstatSync(fd, { bigint: true });
|
|
134
|
+
if (opened.dev !== stamp.dev || opened.ino !== stamp.ino || !opened.isFile() || opened.size !== stamp.size ||
|
|
135
|
+
opened.mtimeNs !== stamp.mtimeNs || opened.ctimeNs !== stamp.ctimeNs) return undefined;
|
|
136
|
+
const bytes = Buffer.alloc(Number(stamp.size)); let offset = 0;
|
|
137
|
+
while (offset < bytes.length) {
|
|
138
|
+
const count = readSync(fd, bytes, offset, bytes.length - offset, offset);
|
|
139
|
+
if (!count) return undefined;
|
|
140
|
+
offset += count;
|
|
141
|
+
}
|
|
142
|
+
if (readSync(fd, Buffer.alloc(1), 0, 1, offset) !== 0 ||
|
|
143
|
+
!sameSnapshotStamp(stamp, path)) return undefined;
|
|
144
|
+
const after = fstatSync(fd, { bigint: true });
|
|
145
|
+
return after.size === stamp.size && after.mtimeNs === stamp.mtimeNs && after.ctimeNs === stamp.ctimeNs ? { stamp, bytes } : undefined;
|
|
146
|
+
} finally { if (fd !== undefined) closeSync(fd); }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function admitInventoryRow(stateDir: string) {
|
|
150
|
+
const path = join(stateDir, "run.json"); const markerPath = join(stateDir, RUN_STATE_OWNERSHIP_FILE);
|
|
151
|
+
const source = readInventorySource(path);
|
|
152
|
+
if (!source) return undefined;
|
|
153
|
+
let meta: Record<string, unknown>;
|
|
154
|
+
try { meta = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(source.bytes)); }
|
|
155
|
+
catch { return undefined; }
|
|
156
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta) || meta.state_dir !== stateDir ||
|
|
157
|
+
typeof meta.pid !== "number" || !Number.isSafeInteger(meta.pid) || meta.pid <= 0) return undefined;
|
|
158
|
+
const expected = meta.process_identity as RunProcessIdentity | undefined;
|
|
159
|
+
if (!expected || expected.platform !== "win32" || typeof expected.command !== "string" ||
|
|
160
|
+
typeof expected.start_time !== "string" || (expected.cwd !== undefined && typeof expected.cwd !== "string")) return undefined;
|
|
161
|
+
const owner = readRunContextIdentity(stateDir, meta);
|
|
162
|
+
if (owner.state !== "available" || owner.local_path !== stateDir) return undefined;
|
|
163
|
+
const marker = readInventorySource(markerPath);
|
|
164
|
+
if (!marker) return undefined;
|
|
165
|
+
const unchanged = (): boolean => {
|
|
166
|
+
if (!owner.unchanged() || !sameSnapshotStamp(source.stamp, path) || !sameSnapshotStamp(marker.stamp, markerPath)) return false;
|
|
167
|
+
const current = readInventorySource(path); const currentMarker = readInventorySource(markerPath);
|
|
168
|
+
return !!current && !!currentMarker && source.bytes.equals(current.bytes) && marker.bytes.equals(currentMarker.bytes) && owner.unchanged();
|
|
169
|
+
};
|
|
170
|
+
// Once admitted, a changed row can only be discarded, never reread through the scalar facade.
|
|
171
|
+
return { meta, pid: meta.pid as number, expected, unchanged };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Fixed kernel inventory path. Native frames are synchronous locals, never capabilities returned to consumers. */
|
|
175
|
+
export function readRunInventoryStatuses(stateDirs: readonly string[], readJson: RunJsonReader,
|
|
176
|
+
scalarStatus: (stateDir: string) => Record<string, unknown>): (Record<string, unknown> | undefined)[] {
|
|
177
|
+
const scalar = (stateDir: string) => { try { return scalarStatus(stateDir); } catch { return undefined; } };
|
|
178
|
+
if (platform() !== "win32") return stateDirs.map(scalar);
|
|
179
|
+
const rows = stateDirs.map(stateDir => { try { return admitInventoryRow(stateDir); } catch { return undefined; } });
|
|
180
|
+
// This selects optional acquisition only; assembly still verifies freshly and excluded rows retain scalar fallback.
|
|
181
|
+
const pids = [...new Set(rows.flatMap(row => row ? [row.pid] : []))].filter(isAlive);
|
|
182
|
+
const observations = new Map<number, Map<number, RunProcessIdentity> | undefined>();
|
|
183
|
+
for (let offset = 0; offset < pids.length; offset += WINDOWS_IDENTITY_QUERY_PID_LIMIT) {
|
|
184
|
+
const chunk = pids.slice(offset, offset + WINDOWS_IDENTITY_QUERY_PID_LIMIT);
|
|
185
|
+
const identities = readWindowsProcessIdentities(chunk);
|
|
186
|
+
for (const pid of chunk) observations.set(pid, identities);
|
|
187
|
+
}
|
|
188
|
+
const statuses = stateDirs.map((stateDir, index) => {
|
|
189
|
+
const row = rows[index];
|
|
190
|
+
if (!row) return scalar(stateDir);
|
|
191
|
+
try {
|
|
192
|
+
if (!row.unchanged()) return undefined;
|
|
193
|
+
const identities = observations.get(row.pid);
|
|
194
|
+
const status = deriveRunStatus(stateDir, row.meta, readJson, () => {
|
|
195
|
+
if (!row.unchanged()) throw new Error("Inventory frame changed");
|
|
196
|
+
const identity = identities === undefined ? verifyRunProcessIdentity(row.pid, row.expected)
|
|
197
|
+
: verifyRunProcessIdentity(row.pid, row.expected, "win32", pid => identities.get(pid));
|
|
198
|
+
if (!row.unchanged()) throw new Error("Inventory frame changed");
|
|
199
|
+
return identity;
|
|
200
|
+
});
|
|
201
|
+
return row.unchanged() ? status : undefined;
|
|
202
|
+
} catch { return undefined; }
|
|
203
|
+
});
|
|
204
|
+
// Later row assembly can reenter file readers and invalidate an earlier assembled row.
|
|
205
|
+
return statuses.map((status, index) => {
|
|
206
|
+
const row = rows[index];
|
|
207
|
+
if (!status || !row) return status;
|
|
208
|
+
try { return row.unchanged() ? status : undefined; } catch { return undefined; }
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type RunSnapshotFactsReading =
|
|
213
|
+
| { readonly state: "available"; readonly facts: Readonly<RunSnapshotFacts>; readonly unchanged: () => boolean }
|
|
214
|
+
| { readonly state: "unavailable"; readonly reason: "identity_unavailable" | "identity_mismatch" | "observation_changed" |
|
|
215
|
+
"observation_unavailable" | "references_unavailable" | "snapshot_too_large" };
|
|
216
|
+
|
|
217
|
+
function snapshotStamp(path: string): BigIntStats | undefined {
|
|
218
|
+
try { return lstatSync(path, { bigint: true }); }
|
|
219
|
+
catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined; throw error; }
|
|
220
|
+
}
|
|
221
|
+
function sameSnapshotStamp(before: BigIntStats | undefined, path: string): boolean {
|
|
222
|
+
const after = snapshotStamp(path);
|
|
223
|
+
return before === undefined ? after === undefined : after !== undefined && before.dev === after.dev && before.ino === after.ino &&
|
|
224
|
+
before.mode === after.mode && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function snapshotDeferred(value: unknown): boolean {
|
|
228
|
+
if (!UtilTypes.isPromise(value)) return false;
|
|
229
|
+
void Promise.prototype.then.call(value, undefined, () => {}); return true;
|
|
230
|
+
}
|
|
231
|
+
function snapshotData(value: unknown): Record<string, unknown> | undefined {
|
|
232
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
233
|
+
for (let target: object | null = value; target; target = Object.getPrototypeOf(target)) {
|
|
234
|
+
const then = Object.getOwnPropertyDescriptor(target, "then");
|
|
235
|
+
if (then && (!Object.hasOwn(then, "value") || typeof then.value === "function")) return undefined;
|
|
236
|
+
}
|
|
237
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
238
|
+
return Object.values(descriptors).every(field => Object.hasOwn(field, "value"))
|
|
239
|
+
? Object.fromEntries(Object.entries(descriptors).map(([key, field]) => [key, field.value])) : undefined;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Kernel-local facts only. Opt-in timing must be the original retained owner's method, never actor data or a cached DTO. */
|
|
243
|
+
export function readRunSnapshotFacts(stateDir: string, expected: unknown, capturedAt: unknown,
|
|
244
|
+
observeTime?: (expected: unknown, stateDir?: string) => unknown,
|
|
245
|
+
observeFrozenNaturalTime?: (expected: unknown, stateDir?: string) => unknown): Readonly<RunSnapshotFactsReading> {
|
|
246
|
+
const unavailable = (reason: Extract<RunSnapshotFactsReading, { state: "unavailable" }>["reason"]): Readonly<RunSnapshotFactsReading> => Object.freeze({ state: "unavailable", reason });
|
|
247
|
+
if ((observeTime !== undefined && typeof observeTime !== "function") ||
|
|
248
|
+
(observeFrozenNaturalTime !== undefined && typeof observeFrozenNaturalTime !== "function") || typeof capturedAt !== "string" || capturedAt.length > 32) return unavailable("observation_unavailable");
|
|
249
|
+
const capturedMs = Date.parse(capturedAt);
|
|
250
|
+
if (!Number.isSafeInteger(capturedMs) || new Date(capturedMs).toISOString() !== capturedAt) return unavailable("observation_unavailable");
|
|
251
|
+
const owner = readRunContextIdentity(stateDir, expected);
|
|
252
|
+
if (owner.state !== "available") return unavailable(owner.reason);
|
|
253
|
+
try {
|
|
254
|
+
const root = owner.local_path; const metadataPath = join(root, "run.json"); const resultPath = join(root, "result.json");
|
|
255
|
+
const indexPath = join(root, RUN_CONTEXT_INDEX_FILE); const metadata = snapshotStamp(metadataPath);
|
|
256
|
+
if (!metadata?.isFile() || metadata.size > BigInt(RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES)) return unavailable("observation_unavailable");
|
|
257
|
+
const read = readJsonFileResilient<unknown>(metadataPath, undefined, { maxBytes: RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES, strictUtf8: true });
|
|
258
|
+
if (!owner.unchanged() || !sameSnapshotStamp(metadata, metadataPath)) return unavailable("observation_changed");
|
|
259
|
+
if (read.diagnostics.length || !read.value || typeof read.value !== "object" || Array.isArray(read.value)) return unavailable("observation_unavailable");
|
|
260
|
+
const meta = read.value as Record<string, unknown>;
|
|
261
|
+
if (meta.run !== owner.identity.run || meta.run_instance_id !== owner.identity.run_instance_id || meta.ownerId !== owner.identity.ownerId || meta.state_dir !== root) return unavailable("identity_mismatch");
|
|
262
|
+
if (typeof meta.cwd !== "string" || !isAbsolute(meta.cwd) || /[\u0000-\u001f\u007f]/u.test(meta.cwd)) return unavailable("references_unavailable");
|
|
263
|
+
if (meta.cwd.length > RUN_DELIVERY_MODEL_MAX_BYTES) return unavailable("snapshot_too_large");
|
|
264
|
+
const result = snapshotStamp(resultPath); const index = snapshotStamp(indexPath);
|
|
265
|
+
if (result && !result.isFile()) return unavailable("observation_unavailable");
|
|
266
|
+
const outcome = readRunNaturalOutcomeSnapshot(root, meta, path => {
|
|
267
|
+
const canonical = readJsonFileResilient<unknown>(path, undefined, { maxBytes: RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES, strictUtf8: true });
|
|
268
|
+
return canonical.diagnostics.length ? undefined : canonical.value;
|
|
269
|
+
});
|
|
270
|
+
const natural = outcome.outcome; const context = readRunContextIndex(root, owner.identity);
|
|
271
|
+
const stopPath = join(root, RUN_STOP_CLAIM_FILE); let stopObserved = false; let stopStamp: BigIntStats | undefined; let timingUnchanged: (() => unknown) | undefined;
|
|
272
|
+
const frameUnchanged = (): boolean => owner.unchanged() && sameSnapshotStamp(metadata, metadataPath) &&
|
|
273
|
+
sameSnapshotStamp(result, resultPath) && sameSnapshotStamp(index, indexPath) && (!stopObserved || sameSnapshotStamp(stopStamp, stopPath));
|
|
274
|
+
const unchanged = (): boolean => {
|
|
275
|
+
try {
|
|
276
|
+
if (!frameUnchanged()) return false;
|
|
277
|
+
if (!timingUnchanged) return true;
|
|
278
|
+
const stable = timingUnchanged();
|
|
279
|
+
return !snapshotDeferred(stable) && stable === true && frameUnchanged();
|
|
280
|
+
} catch { return false; }
|
|
281
|
+
};
|
|
282
|
+
if (!unchanged()) return unavailable("observation_changed");
|
|
283
|
+
let lifecycle: RunSnapshotFacts["lifecycle"] = meta.outcome_protocol === RUN_OUTCOME_PROTOCOL && natural.state === "accepted"
|
|
284
|
+
? Object.freeze({ status: natural.status }) : Object.freeze({ status: "unproven" });
|
|
285
|
+
let timing: RunSnapshotFacts["timing"] = Object.freeze({ basis: "unproven" });
|
|
286
|
+
if (observeFrozenNaturalTime && meta.outcome_protocol === RUN_OUTCOME_PROTOCOL && natural.state === "accepted") {
|
|
287
|
+
const retained = observeFrozenNaturalTime(owner.identity, root);
|
|
288
|
+
if (snapshotDeferred(retained)) return unavailable("observation_unavailable");
|
|
289
|
+
const frozen = snapshotData(retained); if (!frozen) return unavailable("observation_unavailable");
|
|
290
|
+
if (frozen.state === "available") {
|
|
291
|
+
const identity = snapshotData(frozen.identity); const accepted = snapshotData(frozen.natural_acceptance);
|
|
292
|
+
if (!identity || identity.run !== owner.identity.run || identity.run_instance_id !== owner.identity.run_instance_id || identity.ownerId !== owner.identity.ownerId) return unavailable("identity_mismatch");
|
|
293
|
+
if (frozen.basis !== "first_natural_acceptance" || !accepted || accepted.recorded_status !== natural.status || accepted.code !== outcome.result?.code ||
|
|
294
|
+
accepted.completed_at !== outcome.result?.completedAt || typeof frozen.elapsed_ms !== "number" || !Number.isSafeInteger(frozen.elapsed_ms) || frozen.elapsed_ms < 0 ||
|
|
295
|
+
typeof frozen.unchanged !== "function") return unavailable("observation_unavailable");
|
|
296
|
+
timingUnchanged = frozen.unchanged as () => unknown;
|
|
297
|
+
timing = Object.freeze({ basis: "terminal", elapsed_ms: frozen.elapsed_ms });
|
|
298
|
+
} else if (frozen.state !== "unavailable") return unavailable("observation_unavailable");
|
|
299
|
+
if (!unchanged()) return unavailable("observation_changed");
|
|
300
|
+
}
|
|
301
|
+
if (observeTime && meta.outcome_protocol === RUN_OUTCOME_PROTOCOL && (natural.state === "absent" || natural.state === "captured") &&
|
|
302
|
+
typeof meta.pid === "number" && Number.isSafeInteger(meta.pid) && meta.pid > 0) {
|
|
303
|
+
stopObserved = true; stopStamp = snapshotStamp(stopPath);
|
|
304
|
+
const stop = readRunStopClaim(root, meta);
|
|
305
|
+
const eligible = (natural.state === "absent" && (stop.state === "absent" || stop.state === "stale" || stop.state === "pending")) ||
|
|
306
|
+
(natural.state === "captured" && stop.state === "pending" && outcome.result?.stop_claim_id === stop.claim.claim_id);
|
|
307
|
+
if (eligible && observeRunProcessExit(meta.pid, meta.process_identity as RunProcessIdentity | undefined).status === "running") {
|
|
308
|
+
if (!unchanged()) return unavailable("observation_changed");
|
|
309
|
+
const sampled = observeTime(owner.identity, root);
|
|
310
|
+
if (snapshotDeferred(sampled)) return unavailable("observation_unavailable");
|
|
311
|
+
const observed = snapshotData(sampled); if (!observed) return unavailable("observation_unavailable");
|
|
312
|
+
if (observed.state === "available") {
|
|
313
|
+
const identity = snapshotData(observed.identity); const measured = snapshotData(observed.timing);
|
|
314
|
+
if (!identity || identity.run !== owner.identity.run || identity.run_instance_id !== owner.identity.run_instance_id || identity.ownerId !== owner.identity.ownerId) return unavailable("identity_mismatch");
|
|
315
|
+
if (observed.basis !== "since_admission" || !measured || typeof observed.unchanged !== "function") return unavailable("observation_unavailable");
|
|
316
|
+
timingUnchanged = observed.unchanged as () => unknown;
|
|
317
|
+
lifecycle = Object.freeze({ status: "running", ...(stop.state === "pending" ? { phase: "stopping" as const } : {}) });
|
|
318
|
+
if (measured.state === "available" && typeof measured.elapsed_ms === "number" && Number.isSafeInteger(measured.elapsed_ms) && measured.elapsed_ms >= 0) {
|
|
319
|
+
timing = Object.freeze({ basis: "live", elapsed_ms: measured.elapsed_ms });
|
|
320
|
+
} else if (measured.state !== "unproven" || measured.elapsed_ms !== null) return unavailable("observation_unavailable");
|
|
321
|
+
} else if (observed.state !== "unavailable") return unavailable("observation_unavailable");
|
|
322
|
+
if (!unchanged() || observeRunProcessExit(meta.pid, meta.process_identity as RunProcessIdentity | undefined).status !== "running" || !unchanged()) return unavailable("observation_changed");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const facts: Readonly<RunSnapshotFacts> = Object.freeze({ identity: owner.identity, captured_at: capturedAt,
|
|
326
|
+
lifecycle, timing, cwd: meta.cwd,
|
|
327
|
+
...(context.state === "available" ? { context_index: Object.freeze({ identity: context.identity, path: context.local_path }) } : {}) });
|
|
328
|
+
if (Buffer.byteLength(JSON.stringify(facts)) > RUN_DELIVERY_MODEL_MAX_BYTES) return unavailable("snapshot_too_large");
|
|
329
|
+
return unchanged() ? Object.freeze({ state: "available", facts, unchanged }) : unavailable("observation_changed");
|
|
330
|
+
} catch { return unavailable("observation_unavailable"); }
|
|
331
|
+
}
|
|
332
|
+
|
|
91
333
|
export function tailFile(path: string, lines: number): string {
|
|
92
334
|
if (!existsSync(path)) return "";
|
|
93
335
|
const content = readFileSync(path, "utf8").trimEnd();
|