@quolu/lattice 0.1.0 → 0.12.2
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/README.md +87 -4
- package/bin/lattice-bridge.mjs +87 -0
- package/bin/lattice-dashboard.mjs +70 -0
- package/bin/lattice-mcp.mjs +9 -9
- package/bin/lattice.mjs +61 -8
- package/docs/bridge-setup.md +87 -0
- package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -0
- package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -0
- package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -0
- package/package.json +19 -7
- package/sensor/dist/bin/command-supervision.d.ts +1 -1
- package/sensor/dist/bin/command-supervision.js +4 -4
- package/sensor/dist/bin/command-supervision.js.map +1 -1
- package/sensor/dist/bin/fatal-handler.js +2 -2
- package/sensor/dist/bin/fatal-handler.js.map +1 -1
- package/sensor/dist/bin/{codegraph.js → lattice-sensor.js} +207 -328
- package/sensor/dist/bin/node-version-check.d.ts +7 -5
- package/sensor/dist/bin/node-version-check.d.ts.map +1 -1
- package/sensor/dist/bin/node-version-check.js +19 -14
- package/sensor/dist/bin/node-version-check.js.map +1 -1
- package/sensor/dist/context/index.d.ts +1 -1
- package/sensor/dist/context/index.js +6 -6
- package/sensor/dist/context/index.js.map +1 -1
- package/sensor/dist/db/index.d.ts +5 -5
- package/sensor/dist/db/index.d.ts.map +1 -1
- package/sensor/dist/db/index.js +7 -7
- package/sensor/dist/db/index.js.map +1 -1
- package/sensor/dist/db/migrations.js +1 -1
- package/sensor/dist/db/migrations.js.map +1 -1
- package/sensor/dist/db/queries.d.ts +1 -1
- package/sensor/dist/db/queries.js +5 -5
- package/sensor/dist/db/queries.js.map +1 -1
- package/sensor/dist/db/schema.sql +2 -2
- package/sensor/dist/db/sqlite-adapter.d.ts +2 -2
- package/sensor/dist/db/sqlite-adapter.js +3 -3
- package/sensor/dist/db/sqlite-adapter.js.map +1 -1
- package/sensor/dist/db/wal-valve.d.ts +1 -1
- package/sensor/dist/db/wal-valve.d.ts.map +1 -1
- package/sensor/dist/db/wal-valve.js +2 -2
- package/sensor/dist/db/wal-valve.js.map +1 -1
- package/sensor/dist/directory.d.ts +27 -63
- package/sensor/dist/directory.d.ts.map +1 -1
- package/sensor/dist/directory.js +78 -134
- package/sensor/dist/directory.js.map +1 -1
- package/sensor/dist/errors.d.ts +15 -15
- package/sensor/dist/errors.d.ts.map +1 -1
- package/sensor/dist/errors.js +21 -21
- package/sensor/dist/errors.js.map +1 -1
- package/sensor/dist/extraction/dynamic-import.d.ts +1 -1
- package/sensor/dist/extraction/dynamic-import.js +1 -1
- package/sensor/dist/extraction/extraction-version.d.ts +1 -1
- package/sensor/dist/extraction/extraction-version.js +1 -1
- package/sensor/dist/extraction/generated-detection.d.ts +1 -1
- package/sensor/dist/extraction/generated-detection.js +1 -1
- package/sensor/dist/extraction/grammars.d.ts +3 -3
- package/sensor/dist/extraction/grammars.js +5 -5
- package/sensor/dist/extraction/grammars.js.map +1 -1
- package/sensor/dist/extraction/index.d.ts +6 -6
- package/sensor/dist/extraction/index.js +50 -50
- package/sensor/dist/extraction/index.js.map +1 -1
- package/sensor/dist/extraction/kernel/decode.d.ts +1 -1
- package/sensor/dist/extraction/kernel/decode.js +1 -1
- package/sensor/dist/extraction/kernel/index.d.ts +3 -3
- package/sensor/dist/extraction/kernel/index.js +6 -6
- package/sensor/dist/extraction/kernel/index.js.map +1 -1
- package/sensor/dist/extraction/kernel/layout.d.ts +1 -1
- package/sensor/dist/extraction/kernel/layout.js +1 -1
- package/sensor/dist/extraction/kernel/loader.d.ts +6 -6
- package/sensor/dist/extraction/kernel/loader.js +13 -13
- package/sensor/dist/extraction/kernel/loader.js.map +1 -1
- package/sensor/dist/extraction/languages/cfquery.d.ts +1 -1
- package/sensor/dist/extraction/languages/cfquery.js +1 -1
- package/sensor/dist/extraction/languages/lua.d.ts +11 -0
- package/sensor/dist/extraction/languages/lua.d.ts.map +1 -1
- package/sensor/dist/extraction/languages/lua.js +1 -0
- package/sensor/dist/extraction/languages/lua.js.map +1 -1
- package/sensor/dist/extraction/parse-pool.d.ts +5 -5
- package/sensor/dist/extraction/parse-pool.d.ts.map +1 -1
- package/sensor/dist/extraction/parse-pool.js +4 -4
- package/sensor/dist/extraction/parse-worker.js +1 -1
- package/sensor/dist/extraction/parse-worker.js.map +1 -1
- package/sensor/dist/extraction/store-writer.d.ts +1 -1
- package/sensor/dist/extraction/store-writer.js +1 -1
- package/sensor/dist/extraction/svelte-extractor.d.ts +1 -1
- package/sensor/dist/extraction/svelte-extractor.js +1 -1
- package/sensor/dist/extraction/tree-sitter-helpers.js +1 -1
- package/sensor/dist/extraction/tree-sitter.d.ts +2 -2
- package/sensor/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/sensor/dist/extraction/tree-sitter.js +71 -4
- package/sensor/dist/extraction/tree-sitter.js.map +1 -1
- package/sensor/dist/extraction/wasm-runtime-flags.d.ts +2 -2
- package/sensor/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
- package/sensor/dist/extraction/wasm-runtime-flags.js +5 -5
- package/sensor/dist/extraction/wasm-runtime-flags.js.map +1 -1
- package/sensor/dist/index.d.ts +36 -36
- package/sensor/dist/index.d.ts.map +1 -1
- package/sensor/dist/index.js +71 -71
- package/sensor/dist/index.js.map +1 -1
- package/sensor/dist/mcp/daemon-manager.js +1 -1
- package/sensor/dist/mcp/daemon-paths.d.ts +3 -3
- package/sensor/dist/mcp/daemon-paths.js +7 -7
- package/sensor/dist/mcp/daemon-paths.js.map +1 -1
- package/sensor/dist/mcp/daemon-registry.d.ts +2 -2
- package/sensor/dist/mcp/daemon-registry.js +5 -5
- package/sensor/dist/mcp/daemon.d.ts +7 -7
- package/sensor/dist/mcp/daemon.d.ts.map +1 -1
- package/sensor/dist/mcp/daemon.js +21 -21
- package/sensor/dist/mcp/daemon.js.map +1 -1
- package/sensor/dist/mcp/dynamic-boundaries.js +1 -1
- package/sensor/dist/mcp/engine.d.ts +9 -9
- package/sensor/dist/mcp/engine.d.ts.map +1 -1
- package/sensor/dist/mcp/engine.js +44 -44
- package/sensor/dist/mcp/engine.js.map +1 -1
- package/sensor/dist/mcp/index.d.ts +14 -14
- package/sensor/dist/mcp/index.d.ts.map +1 -1
- package/sensor/dist/mcp/index.js +41 -41
- package/sensor/dist/mcp/index.js.map +1 -1
- package/sensor/dist/mcp/liveness-watchdog.js +7 -7
- package/sensor/dist/mcp/liveness-watchdog.js.map +1 -1
- package/sensor/dist/mcp/ppid-watchdog.d.ts +3 -3
- package/sensor/dist/mcp/ppid-watchdog.js +2 -2
- package/sensor/dist/mcp/proxy.d.ts.map +1 -1
- package/sensor/dist/mcp/proxy.js +37 -37
- package/sensor/dist/mcp/proxy.js.map +1 -1
- package/sensor/dist/mcp/query-pool.d.ts +3 -3
- package/sensor/dist/mcp/query-pool.js +7 -7
- package/sensor/dist/mcp/query-pool.js.map +1 -1
- package/sensor/dist/mcp/query-worker.d.ts +2 -2
- package/sensor/dist/mcp/query-worker.js +7 -7
- package/sensor/dist/mcp/query-worker.js.map +1 -1
- package/sensor/dist/mcp/server-instructions.d.ts +10 -12
- package/sensor/dist/mcp/server-instructions.d.ts.map +1 -1
- package/sensor/dist/mcp/server-instructions.js +39 -37
- package/sensor/dist/mcp/server-instructions.js.map +1 -1
- package/sensor/dist/mcp/session.d.ts +2 -2
- package/sensor/dist/mcp/session.js +18 -18
- package/sensor/dist/mcp/session.js.map +1 -1
- package/sensor/dist/mcp/startup-handshake.d.ts +3 -3
- package/sensor/dist/mcp/startup-handshake.d.ts.map +1 -1
- package/sensor/dist/mcp/startup-handshake.js +3 -3
- package/sensor/dist/mcp/startup-handshake.js.map +1 -1
- package/sensor/dist/mcp/tools.d.ts +53 -53
- package/sensor/dist/mcp/tools.d.ts.map +1 -1
- package/sensor/dist/mcp/tools.js +180 -216
- package/sensor/dist/mcp/tools.js.map +1 -1
- package/sensor/dist/mcp/transport.d.ts +1 -1
- package/sensor/dist/mcp/transport.js +6 -6
- package/sensor/dist/mcp/transport.js.map +1 -1
- package/sensor/dist/mcp/version.d.ts +2 -2
- package/sensor/dist/mcp/version.d.ts.map +1 -1
- package/sensor/dist/mcp/version.js +3 -3
- package/sensor/dist/mcp/version.js.map +1 -1
- package/sensor/dist/project-config.d.ts +6 -6
- package/sensor/dist/project-config.d.ts.map +1 -1
- package/sensor/dist/project-config.js +10 -10
- package/sensor/dist/project-config.js.map +1 -1
- package/sensor/dist/resolution/callback-synthesizer.js +4 -4
- package/sensor/dist/resolution/callback-synthesizer.js.map +1 -1
- package/sensor/dist/resolution/frameworks/drupal.d.ts +3 -3
- package/sensor/dist/resolution/frameworks/drupal.js +3 -3
- package/sensor/dist/resolution/frameworks/fabric.js +1 -1
- package/sensor/dist/resolution/frameworks/fabric.js.map +1 -1
- package/sensor/dist/resolution/frameworks/java.js +1 -1
- package/sensor/dist/resolution/frameworks/java.js.map +1 -1
- package/sensor/dist/resolution/frameworks/svelte.js +1 -1
- package/sensor/dist/resolution/frameworks/svelte.js.map +1 -1
- package/sensor/dist/resolution/goframe-synthesizer.d.ts +1 -1
- package/sensor/dist/resolution/goframe-synthesizer.js +1 -1
- package/sensor/dist/resolution/index.d.ts +1 -1
- package/sensor/dist/resolution/index.js +9 -9
- package/sensor/dist/resolution/index.js.map +1 -1
- package/sensor/dist/resolution/name-matcher.js +2 -2
- package/sensor/dist/resolution/name-matcher.js.map +1 -1
- package/sensor/dist/resolution/resolver-pool.d.ts +2 -2
- package/sensor/dist/resolution/resolver-pool.js +4 -4
- package/sensor/dist/resolution/resolver-pool.js.map +1 -1
- package/sensor/dist/resolution/resolver-worker.js +2 -2
- package/sensor/dist/resolution/resolver-worker.js.map +1 -1
- package/sensor/dist/resolution/workspace-packages.js +1 -1
- package/sensor/dist/resolution/workspace-packages.js.map +1 -1
- package/sensor/dist/search/identifier-segments.d.ts +1 -1
- package/sensor/dist/search/identifier-segments.js +1 -1
- package/sensor/dist/search/query-utils.d.ts +1 -0
- package/sensor/dist/search/query-utils.d.ts.map +1 -1
- package/sensor/dist/search/query-utils.js +10 -3
- package/sensor/dist/search/query-utils.js.map +1 -1
- package/sensor/dist/sync/git-hooks.d.ts +9 -9
- package/sensor/dist/sync/git-hooks.d.ts.map +1 -1
- package/sensor/dist/sync/git-hooks.js +15 -15
- package/sensor/dist/sync/git-hooks.js.map +1 -1
- package/sensor/dist/sync/watch-policy.d.ts +2 -2
- package/sensor/dist/sync/watch-policy.js +5 -5
- package/sensor/dist/sync/watch-policy.js.map +1 -1
- package/sensor/dist/sync/watcher.d.ts +2 -2
- package/sensor/dist/sync/watcher.d.ts.map +1 -1
- package/sensor/dist/sync/watcher.js +16 -16
- package/sensor/dist/sync/watcher.js.map +1 -1
- package/sensor/dist/sync/worktree.d.ts +5 -5
- package/sensor/dist/sync/worktree.d.ts.map +1 -1
- package/sensor/dist/sync/worktree.js +9 -9
- package/sensor/dist/sync/worktree.js.map +1 -1
- package/sensor/dist/telemetry/index.d.ts +8 -8
- package/sensor/dist/telemetry/index.d.ts.map +1 -1
- package/sensor/dist/telemetry/index.js +16 -16
- package/sensor/dist/telemetry/index.js.map +1 -1
- package/sensor/dist/types.d.ts +2 -2
- package/sensor/dist/types.js +1 -1
- package/sensor/dist/ui/color.d.ts +2 -2
- package/sensor/dist/ui/color.js +2 -2
- package/sensor/dist/ui/glyphs.d.ts +3 -3
- package/sensor/dist/ui/glyphs.js +7 -7
- package/sensor/dist/ui/glyphs.js.map +1 -1
- package/sensor/dist/utils.d.ts +4 -4
- package/sensor/dist/utils.js +8 -8
- package/sensor/dist/utils.js.map +1 -1
- package/sensor/package.json +8 -13
- package/src/artifact-contracts.mjs +2 -2
- package/src/boundary-compiler.mjs +28 -28
- package/src/boundary-observation-compiler-v2.mjs +10 -10
- package/src/bounded-seam.mjs +144 -0
- package/src/bridge-cli.mjs +227 -0
- package/src/bridge-config.mjs +346 -0
- package/src/bridge-daemon.mjs +328 -0
- package/src/bridge-launch-agent.mjs +311 -0
- package/src/bridge-server.mjs +309 -0
- package/src/cli-help.mjs +163 -0
- package/src/control-compiler.mjs +30 -30
- package/src/dag-chain.mjs +261 -0
- package/src/factory-diagnostics.mjs +8 -7
- package/src/hash-chain.mjs +76 -0
- package/src/node-version-guard.mjs +5 -4
- package/src/project-cli.mjs +392 -0
- package/src/project-identity.mjs +71 -0
- package/src/rc1-evidence-bundle.mjs +16 -16
- package/src/rc1-v4-campaign.mjs +15 -14
- package/src/rc1-v5-artifact-set.mjs +2 -2
- package/src/rc1-v5-campaign.mjs +15 -14
- package/src/rc1-v6-artifact-set.mjs +18 -18
- package/src/rc1-v6-campaign.mjs +16 -16
- package/src/rc1-v6-causal-binding.mjs +16 -14
- package/src/rc1-v6-measurement.mjs +20 -38
- package/src/rc2-artifact-set.mjs +45 -40
- package/src/rc2-campaign.mjs +48 -66
- package/src/rc2-delivery-policy-front-end.mjs +30 -30
- package/src/rc2-rc1-transfer-front-end.mjs +5 -5
- package/src/rc3-actual-dogfood.mjs +6 -6
- package/src/rc3-dogfood-scaffold.mjs +12 -7
- package/src/rc3-scripted-campaign.mjs +75 -21
- package/src/rc4-stage1-dogfood.mjs +24 -7
- package/src/runtime-cli.mjs +2424 -45
- package/src/runtime-contracts.mjs +7 -7
- package/src/runtime-control-store.mjs +547 -0
- package/src/runtime-controller-protocol.mjs +517 -0
- package/src/runtime-direct-os-observer.mjs +284 -0
- package/src/runtime-engine.mjs +2 -2
- package/src/runtime-errors.mjs +1 -1
- package/src/runtime-event-store.mjs +15 -43
- package/src/runtime-front-end.mjs +26 -26
- package/src/runtime-gate-store.mjs +477 -0
- package/src/runtime-hold-recompile.mjs +214 -23
- package/src/runtime-lifecycle-lock.mjs +290 -0
- package/src/runtime-managed-supervisor.mjs +1276 -0
- package/src/runtime-multi-epoch-store.mjs +761 -0
- package/src/runtime-projection.mjs +62 -0
- package/src/seam-transform.mjs +38 -38
- package/src/{codegraph-adapter.mjs → sensor-adapter.mjs} +7 -7
- package/src/sensor-cli.mjs +107 -0
- package/src/sensor-runtime.mjs +48 -0
- package/src/timestamp-contract.mjs +8 -0
- package/src/todo-chain.mjs +178 -0
- package/src/todo-cli.mjs +1032 -0
- package/src/todo-contracts.mjs +501 -0
- package/src/todo-dashboard-registry.mjs +318 -0
- package/src/todo-gantt-html.mjs +416 -0
- package/src/todo-gantt-layout.mjs +603 -0
- package/src/todo-gantt-live.mjs +269 -0
- package/src/todo-gantt-presentation.mjs +217 -0
- package/src/todo-gantt-svg.mjs +249 -0
- package/src/todo-markdown-renderer.mjs +260 -0
- package/src/todo-migration.mjs +260 -0
- package/src/todo-narrative-anchor.mjs +130 -0
- package/src/todo-revision.mjs +425 -0
- package/src/todo-status.mjs +340 -0
- package/src/todo-store.mjs +3451 -0
- package/src/treatment-compiler.mjs +28 -28
- package/src/treatment-runner.mjs +42 -44
- package/sensor/dist/bin/codegraph.d.ts +0 -26
- package/sensor/dist/bin/codegraph.d.ts.map +0 -1
- package/sensor/dist/bin/codegraph.js.map +0 -1
- package/sensor/dist/bin/uninstall.d.ts +0 -14
- package/sensor/dist/bin/uninstall.d.ts.map +0 -1
- package/sensor/dist/bin/uninstall.js +0 -36
- package/sensor/dist/bin/uninstall.js.map +0 -1
- package/sensor/dist/installer/beta-signup.d.ts +0 -54
- package/sensor/dist/installer/beta-signup.d.ts.map +0 -1
- package/sensor/dist/installer/beta-signup.js +0 -178
- package/sensor/dist/installer/beta-signup.js.map +0 -1
- package/sensor/dist/installer/config-writer.d.ts +0 -28
- package/sensor/dist/installer/config-writer.d.ts.map +0 -1
- package/sensor/dist/installer/config-writer.js +0 -91
- package/sensor/dist/installer/config-writer.js.map +0 -1
- package/sensor/dist/installer/index.d.ts +0 -142
- package/sensor/dist/installer/index.d.ts.map +0 -1
- package/sensor/dist/installer/index.js +0 -622
- package/sensor/dist/installer/index.js.map +0 -1
- package/sensor/dist/installer/instructions-template.d.ts +0 -41
- package/sensor/dist/installer/instructions-template.d.ts.map +0 -1
- package/sensor/dist/installer/instructions-template.js +0 -53
- package/sensor/dist/installer/instructions-template.js.map +0 -1
- package/sensor/dist/installer/targets/antigravity.d.ts +0 -57
- package/sensor/dist/installer/targets/antigravity.d.ts.map +0 -1
- package/sensor/dist/installer/targets/antigravity.js +0 -308
- package/sensor/dist/installer/targets/antigravity.js.map +0 -1
- package/sensor/dist/installer/targets/claude.d.ts +0 -62
- package/sensor/dist/installer/targets/claude.d.ts.map +0 -1
- package/sensor/dist/installer/targets/claude.js +0 -454
- package/sensor/dist/installer/targets/claude.js.map +0 -1
- package/sensor/dist/installer/targets/codex.d.ts +0 -18
- package/sensor/dist/installer/targets/codex.d.ts.map +0 -1
- package/sensor/dist/installer/targets/codex.js +0 -185
- package/sensor/dist/installer/targets/codex.js.map +0 -1
- package/sensor/dist/installer/targets/cursor.d.ts +0 -35
- package/sensor/dist/installer/targets/cursor.d.ts.map +0 -1
- package/sensor/dist/installer/targets/cursor.js +0 -254
- package/sensor/dist/installer/targets/cursor.js.map +0 -1
- package/sensor/dist/installer/targets/gemini.d.ts +0 -26
- package/sensor/dist/installer/targets/gemini.d.ts.map +0 -1
- package/sensor/dist/installer/targets/gemini.js +0 -165
- package/sensor/dist/installer/targets/gemini.js.map +0 -1
- package/sensor/dist/installer/targets/hermes.d.ts +0 -18
- package/sensor/dist/installer/targets/hermes.d.ts.map +0 -1
- package/sensor/dist/installer/targets/hermes.js +0 -359
- package/sensor/dist/installer/targets/hermes.js.map +0 -1
- package/sensor/dist/installer/targets/kiro.d.ts +0 -27
- package/sensor/dist/installer/targets/kiro.d.ts.map +0 -1
- package/sensor/dist/installer/targets/kiro.js +0 -178
- package/sensor/dist/installer/targets/kiro.js.map +0 -1
- package/sensor/dist/installer/targets/opencode.d.ts +0 -38
- package/sensor/dist/installer/targets/opencode.d.ts.map +0 -1
- package/sensor/dist/installer/targets/opencode.js +0 -288
- package/sensor/dist/installer/targets/opencode.js.map +0 -1
- package/sensor/dist/installer/targets/registry.d.ts +0 -35
- package/sensor/dist/installer/targets/registry.d.ts.map +0 -1
- package/sensor/dist/installer/targets/registry.js +0 -91
- package/sensor/dist/installer/targets/registry.js.map +0 -1
- package/sensor/dist/installer/targets/shared.d.ts +0 -101
- package/sensor/dist/installer/targets/shared.d.ts.map +0 -1
- package/sensor/dist/installer/targets/shared.js +0 -264
- package/sensor/dist/installer/targets/shared.js.map +0 -1
- package/sensor/dist/installer/targets/toml.d.ts +0 -52
- package/sensor/dist/installer/targets/toml.d.ts.map +0 -1
- package/sensor/dist/installer/targets/toml.js +0 -147
- package/sensor/dist/installer/targets/toml.js.map +0 -1
- package/sensor/dist/installer/targets/types.d.ts +0 -108
- package/sensor/dist/installer/targets/types.d.ts.map +0 -1
- package/sensor/dist/installer/targets/types.js +0 -16
- package/sensor/dist/installer/targets/types.js.map +0 -1
- package/sensor/dist/upgrade/index.d.ts +0 -171
- package/sensor/dist/upgrade/index.d.ts.map +0 -1
- package/sensor/dist/upgrade/index.js +0 -659
- package/sensor/dist/upgrade/index.js.map +0 -1
- package/sensor/dist/upgrade/remove-binary.d.ts +0 -87
- package/sensor/dist/upgrade/remove-binary.d.ts.map +0 -1
- package/sensor/dist/upgrade/remove-binary.js +0 -289
- package/sensor/dist/upgrade/remove-binary.js.map +0 -1
- package/sensor/dist/upgrade/update-check.d.ts +0 -92
- package/sensor/dist/upgrade/update-check.d.ts.map +0 -1
- package/sensor/dist/upgrade/update-check.js +0 -258
- package/sensor/dist/upgrade/update-check.js.map +0 -1
- package/src/bootstrap.mjs +0 -88
package/src/cli-help.mjs
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
const ROOT_HELP = `Usage: lattice <command> [options]
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
status --json Discover the current project and next action
|
|
5
|
+
plan <command> Create, compile, or verify plans
|
|
6
|
+
run <command> Start or observe compiled runs
|
|
7
|
+
event verify Verify a runtime event log
|
|
8
|
+
todo <command> Read and update the canonical TODO store
|
|
9
|
+
sensor <command> Initialize or synchronize the bundled sensor
|
|
10
|
+
factory-diagnostics --json Check native factory integration
|
|
11
|
+
runtime-errors <command> Inspect the local runtime error store
|
|
12
|
+
bridge <command> Configure the optional network bridge
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
-h, --help Show help
|
|
16
|
+
--version Show the installed version
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const NAMESPACE_HELP = Object.freeze({
|
|
20
|
+
plan: `Usage: lattice plan <command> [options]
|
|
21
|
+
|
|
22
|
+
Commands:
|
|
23
|
+
create --input <file>
|
|
24
|
+
create --schema --json
|
|
25
|
+
create --schema-version <2|3> --json
|
|
26
|
+
compile --request <request.json>
|
|
27
|
+
verify --request <request.json> --plan <plan.json>
|
|
28
|
+
`,
|
|
29
|
+
run: `Usage: lattice run <command> [options]
|
|
30
|
+
|
|
31
|
+
Commands:
|
|
32
|
+
start --request <request.json> --executor <adapter>
|
|
33
|
+
observe --run .lattice/runs/<id>
|
|
34
|
+
status --run .lattice/runs/<id>
|
|
35
|
+
resume --run .lattice/runs/<id>
|
|
36
|
+
close --run .lattice/runs/<id>
|
|
37
|
+
abandon --run .lattice/runs/<id> --reason <reason>
|
|
38
|
+
list --json
|
|
39
|
+
`,
|
|
40
|
+
event: `Usage: lattice event verify --run .lattice/runs/<id>
|
|
41
|
+
`,
|
|
42
|
+
todo: `Usage: lattice todo <command> [options]
|
|
43
|
+
|
|
44
|
+
Read commands:
|
|
45
|
+
status [--json]
|
|
46
|
+
verify [--plan <key>] [--json]
|
|
47
|
+
snapshot --rebuild --plan <key>
|
|
48
|
+
gantt [--out <file>]
|
|
49
|
+
gantt status [--out <file>]
|
|
50
|
+
gantt serve --port <port> # /projects/<project_id>/ をforeground配信
|
|
51
|
+
phase status --plan <key>
|
|
52
|
+
|
|
53
|
+
Write commands:
|
|
54
|
+
start --plan <key> --task <id> [--parallel-frontier|--override-reason <text>]
|
|
55
|
+
block --plan <key> --task <id> --reason <text>
|
|
56
|
+
unblock --plan <key> --task <id>
|
|
57
|
+
done --plan <key> --task <id> --evidence <file>
|
|
58
|
+
reopen --plan <key> --task <id> --reason <text> [--override-reason <text>]
|
|
59
|
+
evidence promote --plan <key> --task <id> --evidence <file>
|
|
60
|
+
revise --plan <key> --input <file>
|
|
61
|
+
revise-phase --plan <key> --input <file>
|
|
62
|
+
revise-set --input <file>
|
|
63
|
+
phase review --plan <key> --phase <id> --reason <text>
|
|
64
|
+
phase <accept|reject> --plan <key> --phase <id> --input <file>
|
|
65
|
+
phase reopen --plan <key> --phase <id> --reason <text> [--override-reason <text>]
|
|
66
|
+
|
|
67
|
+
Write commands require LATTICE_TODO_ACTOR_HOST, LATTICE_TODO_ACTOR_SESSION,
|
|
68
|
+
and LATTICE_TODO_ACTOR_AGENT.
|
|
69
|
+
`,
|
|
70
|
+
sensor: `Usage: lattice sensor <init|sync> [path] --json
|
|
71
|
+
`,
|
|
72
|
+
'factory-diagnostics': `Usage: lattice factory-diagnostics --json
|
|
73
|
+
`,
|
|
74
|
+
'runtime-errors': `Usage: lattice runtime-errors <command> --json
|
|
75
|
+
|
|
76
|
+
Commands:
|
|
77
|
+
snapshot [--after-cursor <n>] [--limit <n>]
|
|
78
|
+
ack <cursor>
|
|
79
|
+
diagnostics
|
|
80
|
+
resolve <fingerprint>
|
|
81
|
+
reopen <fingerprint>
|
|
82
|
+
compact
|
|
83
|
+
`,
|
|
84
|
+
bridge: `Usage: lattice bridge <command> [options] --json
|
|
85
|
+
|
|
86
|
+
Commands:
|
|
87
|
+
setup --listen <IP> [--port <49152..65535|auto>] [--dashboard|--upstream <URL>] [--allow-host <host>...]
|
|
88
|
+
reconfigure [--listen <IP>] [--port <49152..65535|auto>] [--dashboard|--upstream <URL>] [--allow-host <host>...]
|
|
89
|
+
status
|
|
90
|
+
disable
|
|
91
|
+
`,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const SUBCOMMAND_USAGE = Object.freeze({
|
|
95
|
+
'plan create': 'plan create --input <file> | --schema --json | --schema-version <2|3> --json',
|
|
96
|
+
'plan compile': 'plan compile --request <request.json>',
|
|
97
|
+
'plan verify': 'plan verify --request <request.json> --plan <plan.json>',
|
|
98
|
+
'run start': 'run start --request <request.json> --executor <adapter>',
|
|
99
|
+
'run observe': 'run observe --run .lattice/runs/<id>',
|
|
100
|
+
'run status': 'run status --run .lattice/runs/<id>',
|
|
101
|
+
'run resume': 'run resume --run .lattice/runs/<id>',
|
|
102
|
+
'run close': 'run close --run .lattice/runs/<id>',
|
|
103
|
+
'run abandon': 'run abandon --run .lattice/runs/<id> --reason <reason>',
|
|
104
|
+
'run list': 'run list --json',
|
|
105
|
+
'event verify': 'event verify --run .lattice/runs/<id>',
|
|
106
|
+
'todo status': 'todo status [--json]',
|
|
107
|
+
'todo verify': 'todo verify [--plan <key>] [--json]',
|
|
108
|
+
'todo snapshot': 'todo snapshot --rebuild --plan <key>',
|
|
109
|
+
'todo gantt': 'todo gantt [--out <file>] | status [--out <file>] | serve --port <port>',
|
|
110
|
+
'todo phase': 'todo phase <status|review|accept|reject|reopen> --plan <key> [options]',
|
|
111
|
+
'todo phase status': 'todo phase status --plan <key>',
|
|
112
|
+
'todo phase review': 'todo phase review --plan <key> --phase <id> --reason <text>',
|
|
113
|
+
'todo phase accept': 'todo phase accept --plan <key> --phase <id> --input <file>',
|
|
114
|
+
'todo phase reject': 'todo phase reject --plan <key> --phase <id> --input <file>',
|
|
115
|
+
'todo phase reopen': 'todo phase reopen --plan <key> --phase <id> --reason <text> [--override-reason <text>]',
|
|
116
|
+
'todo start': 'todo start --plan <key> --task <id> [--parallel-frontier|--override-reason <text>]',
|
|
117
|
+
'todo block': 'todo block --plan <key> --task <id> --reason <text>',
|
|
118
|
+
'todo unblock': 'todo unblock --plan <key> --task <id>',
|
|
119
|
+
'todo done': 'todo done --plan <key> --task <id> --evidence <file>',
|
|
120
|
+
'todo reopen': 'todo reopen --plan <key> --task <id> --reason <text> [--override-reason <text>]',
|
|
121
|
+
'todo evidence': 'todo evidence promote --plan <key> --task <id> --evidence <file>',
|
|
122
|
+
'todo evidence promote': 'todo evidence promote --plan <key> --task <id> --evidence <file>',
|
|
123
|
+
'todo revise': 'todo revise --plan <key> --input <file>',
|
|
124
|
+
'todo revise-phase': 'todo revise-phase --plan <key> --input <file>',
|
|
125
|
+
'todo revise-set': 'todo revise-set --input <file>',
|
|
126
|
+
'sensor init': 'sensor init [path] --json',
|
|
127
|
+
'sensor sync': 'sensor sync [path] --json',
|
|
128
|
+
'runtime-errors snapshot': 'runtime-errors snapshot [--after-cursor <n>] [--limit <n>] --json',
|
|
129
|
+
'runtime-errors ack': 'runtime-errors ack <cursor> --json',
|
|
130
|
+
'runtime-errors diagnostics': 'runtime-errors diagnostics --json',
|
|
131
|
+
'runtime-errors resolve': 'runtime-errors resolve <fingerprint> --json',
|
|
132
|
+
'runtime-errors reopen': 'runtime-errors reopen <fingerprint> --json',
|
|
133
|
+
'runtime-errors compact': 'runtime-errors compact --json',
|
|
134
|
+
'bridge setup': 'bridge setup --listen <IP> [--port <49152..65535|auto>] [--dashboard|--upstream <URL>] [--allow-host <host>...] --json',
|
|
135
|
+
'bridge reconfigure': 'bridge reconfigure [--listen <IP>] [--port <49152..65535|auto>] [--dashboard|--upstream <URL>] [--allow-host <host>...] --json',
|
|
136
|
+
'bridge status': 'bridge status --json',
|
|
137
|
+
'bridge disable': 'bridge disable --json',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
function requestedNamespace(argv) {
|
|
141
|
+
if (argv.length === 2 && ['-h', '--help'].includes(argv[1])) return argv[0];
|
|
142
|
+
if (argv.length === 2 && argv[0] === 'help') return argv[1];
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function requestedSubcommand(argv) {
|
|
147
|
+
if (argv.length >= 3 && ['-h', '--help'].includes(argv.at(-1))) {
|
|
148
|
+
return argv.slice(0, -1).join(' ');
|
|
149
|
+
}
|
|
150
|
+
if (argv.length >= 3 && argv[0] === 'help') return argv.slice(1).join(' ');
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function renderCliHelp(argv) {
|
|
155
|
+
if (argv.length === 1 && ['-h', '--help', 'help'].includes(argv[0])) return ROOT_HELP;
|
|
156
|
+
const subcommand = requestedSubcommand(argv);
|
|
157
|
+
if (subcommand !== null) {
|
|
158
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
159
|
+
return usage === undefined ? null : `Usage: lattice ${usage}\n`;
|
|
160
|
+
}
|
|
161
|
+
const namespace = requestedNamespace(argv);
|
|
162
|
+
return namespace === null ? null : NAMESPACE_HELP[namespace] ?? null;
|
|
163
|
+
}
|
package/src/control-compiler.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
validatePlanGraph,
|
|
7
7
|
validatePlanInput,
|
|
8
8
|
} from './artifact-contracts.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import { portableSensorOutcome } from './sensor-adapter.mjs';
|
|
10
10
|
|
|
11
11
|
const SHA256 = /^[0-9a-f]{64}$/;
|
|
12
12
|
const IDENTIFIER = /^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$/;
|
|
@@ -98,7 +98,7 @@ function assertManualEvidence(planInput, manualEvidence) {
|
|
|
98
98
|
|
|
99
99
|
function assertQuerySet(querySet) {
|
|
100
100
|
if (!exactRecord(querySet, ['schema', 'queries'])
|
|
101
|
-
|| querySet.schema !== 'lattice.
|
|
101
|
+
|| querySet.schema !== 'lattice.sensor_query_set.v1'
|
|
102
102
|
|| !Array.isArray(querySet.queries)
|
|
103
103
|
|| querySet.queries.length === 0
|
|
104
104
|
|| querySet.queries.length > 256) {
|
|
@@ -128,21 +128,21 @@ function assertQuerySet(querySet) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
function
|
|
132
|
-
if (!exactRecord(
|
|
133
|
-
|| !nonEmptyText(
|
|
134
|
-
|| !Array.isArray(
|
|
135
|
-
||
|
|
136
|
-
fail('
|
|
131
|
+
function assertLatticeSensorEvidence(querySet, sensorEvidence) {
|
|
132
|
+
if (!exactRecord(sensorEvidence, ['cwd', 'outcomes'])
|
|
133
|
+
|| !nonEmptyText(sensorEvidence.cwd)
|
|
134
|
+
|| !Array.isArray(sensorEvidence.outcomes)
|
|
135
|
+
|| sensorEvidence.outcomes.length !== querySet.queries.length) {
|
|
136
|
+
fail('LatticeSensor evidence rootがquery setと一致しない');
|
|
137
137
|
}
|
|
138
138
|
for (let index = 0; index < querySet.queries.length; index += 1) {
|
|
139
139
|
const query = querySet.queries[index];
|
|
140
|
-
const outcome =
|
|
140
|
+
const outcome = sensorEvidence.outcomes[index];
|
|
141
141
|
if (!outcome || typeof outcome !== 'object' || Array.isArray(outcome)
|
|
142
142
|
|| outcome.id !== query.id
|
|
143
143
|
|| outcome.operation !== query.operation
|
|
144
144
|
|| !nonEmptyText(outcome.outcome)) {
|
|
145
|
-
fail(`
|
|
145
|
+
fail(`LatticeSensor evidence ${query.id}がID/operation/順序と一致しない`);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
}
|
|
@@ -190,27 +190,27 @@ function assertRc1QueryCoverage(planInput, querySet, seams) {
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
function outcomeById(querySet,
|
|
193
|
+
function outcomeById(querySet, sensorEvidence) {
|
|
194
194
|
return new Map(querySet.queries.map((query, index) => [
|
|
195
195
|
query.id,
|
|
196
|
-
|
|
196
|
+
sensorEvidence.outcomes[index],
|
|
197
197
|
]));
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
function assertOutcome(outcomes, query, expected) {
|
|
201
201
|
const outcome = outcomes.get(query.id);
|
|
202
202
|
if (outcome.outcome !== expected) {
|
|
203
|
-
fail(`
|
|
203
|
+
fail(`LatticeSensor evidence ${query.id}は${expected}でなく${outcome.outcome}`);
|
|
204
204
|
}
|
|
205
205
|
return outcome;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
function controlGraphFacts(planInput, querySet,
|
|
209
|
-
const outcomes = outcomeById(querySet,
|
|
208
|
+
function controlGraphFacts(planInput, querySet, sensorEvidence, seams) {
|
|
209
|
+
const outcomes = outcomeById(querySet, sensorEvidence);
|
|
210
210
|
const statusQuery = findSingleQuery(querySet, 'status');
|
|
211
211
|
const status = assertOutcome(outcomes, statusQuery, 'ready');
|
|
212
212
|
if (!status.data || !nonEmptyText(status.data.version)) {
|
|
213
|
-
fail('
|
|
213
|
+
fail('LatticeSensor statusにversionがない');
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
const anchorSymbol = planInput.todos[0].anchor.symbol;
|
|
@@ -227,7 +227,7 @@ function controlGraphFacts(planInput, querySet, codegraphEvidence, seams) {
|
|
|
227
227
|
if (!Array.isArray(affected.targets)
|
|
228
228
|
|| affected.targets.length !== affectedQuery.targets.length
|
|
229
229
|
|| affected.targets.some((entry, index) => entry.target !== affectedQuery.targets[index])) {
|
|
230
|
-
fail('affected
|
|
230
|
+
fail('affected LatticeSensor evidenceがquery targetsと一致しない');
|
|
231
231
|
}
|
|
232
232
|
const anchorEvidence = affected.targets[0];
|
|
233
233
|
if (anchorEvidence.outcome !== 'ready'
|
|
@@ -246,7 +246,7 @@ function controlGraphFacts(planInput, querySet, codegraphEvidence, seams) {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
return {
|
|
249
|
-
|
|
249
|
+
sensorVersion: status.data.version,
|
|
250
250
|
affectedTests: [...new Set(anchorEvidence.data.affectedTests)].sort(),
|
|
251
251
|
outcomes,
|
|
252
252
|
};
|
|
@@ -311,12 +311,12 @@ function sharedManualConflicts(planInput, manualRecords) {
|
|
|
311
311
|
return conflicts;
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
function graphRecords(querySet,
|
|
314
|
+
function graphRecords(querySet, sensorEvidence) {
|
|
315
315
|
return querySet.queries.map((query, index) => ({
|
|
316
316
|
id: query.id,
|
|
317
317
|
operation: query.operation,
|
|
318
|
-
status:
|
|
319
|
-
result_digest: digestArtifact(
|
|
318
|
+
status: sensorEvidence.outcomes[index].outcome,
|
|
319
|
+
result_digest: digestArtifact(portableSensorOutcome(sensorEvidence.outcomes[index])),
|
|
320
320
|
}));
|
|
321
321
|
}
|
|
322
322
|
|
|
@@ -324,7 +324,7 @@ function compileManifest({
|
|
|
324
324
|
planInput,
|
|
325
325
|
manualEvidence,
|
|
326
326
|
querySet,
|
|
327
|
-
|
|
327
|
+
sensorEvidence,
|
|
328
328
|
codeSnapshotDigest,
|
|
329
329
|
seams,
|
|
330
330
|
facts,
|
|
@@ -382,9 +382,9 @@ function compileManifest({
|
|
|
382
382
|
code_snapshot_digest: codeSnapshotDigest,
|
|
383
383
|
query_set_digest: digestArtifact(querySet),
|
|
384
384
|
manual_evidence_digest: digestArtifact(manualEvidence),
|
|
385
|
-
|
|
385
|
+
sensor_version: facts.sensorVersion,
|
|
386
386
|
},
|
|
387
|
-
graph_evidence: graphRecords(querySet,
|
|
387
|
+
graph_evidence: graphRecords(querySet, sensorEvidence),
|
|
388
388
|
manual_evidence: manualEvidenceRecords,
|
|
389
389
|
todos,
|
|
390
390
|
conflicts,
|
|
@@ -422,7 +422,7 @@ function compileVerdict(manifest, seams, manualEvidence) {
|
|
|
422
422
|
})),
|
|
423
423
|
preconditions: [
|
|
424
424
|
'characterization verifier is green',
|
|
425
|
-
'post-transform
|
|
425
|
+
'post-transform LatticeSensor query set resolves proposed surfaces',
|
|
426
426
|
],
|
|
427
427
|
};
|
|
428
428
|
}
|
|
@@ -494,10 +494,10 @@ export function compileControlArtifacts({
|
|
|
494
494
|
planInput,
|
|
495
495
|
manualEvidence,
|
|
496
496
|
querySet,
|
|
497
|
-
|
|
497
|
+
sensorEvidence,
|
|
498
498
|
codeSnapshotDigest,
|
|
499
499
|
} = {}) {
|
|
500
|
-
for (const value of [planInput, manualEvidence, querySet,
|
|
500
|
+
for (const value of [planInput, manualEvidence, querySet, sensorEvidence]) {
|
|
501
501
|
canonicalizeArtifact(value);
|
|
502
502
|
}
|
|
503
503
|
if (!validatePlanInput(planInput)) fail('plan inputがpublic contractを満たさない');
|
|
@@ -506,15 +506,15 @@ export function compileControlArtifacts({
|
|
|
506
506
|
}
|
|
507
507
|
assertManualEvidence(planInput, manualEvidence);
|
|
508
508
|
assertQuerySet(querySet);
|
|
509
|
-
|
|
509
|
+
assertLatticeSensorEvidence(querySet, sensorEvidence);
|
|
510
510
|
const seams = rc1Seams(planInput);
|
|
511
511
|
assertRc1QueryCoverage(planInput, querySet, seams);
|
|
512
|
-
const facts = controlGraphFacts(planInput, querySet,
|
|
512
|
+
const facts = controlGraphFacts(planInput, querySet, sensorEvidence, seams);
|
|
513
513
|
const boundaryManifest = compileManifest({
|
|
514
514
|
planInput,
|
|
515
515
|
manualEvidence,
|
|
516
516
|
querySet,
|
|
517
|
-
|
|
517
|
+
sensorEvidence,
|
|
518
518
|
codeSnapshotDigest,
|
|
519
519
|
seams,
|
|
520
520
|
facts,
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
export class DagChainError extends Error {
|
|
2
|
+
constructor(code, message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'DagChainError';
|
|
5
|
+
this.code = code;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class DagCycleError extends DagChainError {
|
|
10
|
+
constructor(message = 'directed graph contains a cycle') {
|
|
11
|
+
super('DAG_CYCLE', message);
|
|
12
|
+
this.name = 'DagCycleError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function defaultCompare(left, right) {
|
|
17
|
+
const leftText = String(left);
|
|
18
|
+
const rightText = String(right);
|
|
19
|
+
if (leftText < rightText) return -1;
|
|
20
|
+
if (leftText > rightText) return 1;
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function assertOptions(countCap, representativeLimit) {
|
|
25
|
+
if (!Number.isSafeInteger(countCap) || countCap < 1 || countCap >= Number.MAX_SAFE_INTEGER) {
|
|
26
|
+
throw new DagChainError(
|
|
27
|
+
'DAG_INVALID_COUNT_CAP',
|
|
28
|
+
'countCap must be a positive safe integer below Number.MAX_SAFE_INTEGER',
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (
|
|
32
|
+
!Number.isSafeInteger(representativeLimit)
|
|
33
|
+
|| representativeLimit < 0
|
|
34
|
+
|| representativeLimit > 8
|
|
35
|
+
) {
|
|
36
|
+
throw new DagChainError(
|
|
37
|
+
'DAG_INVALID_REPRESENTATIVE_LIMIT',
|
|
38
|
+
'representativeLimit must be a safe integer from 0 through 8',
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function normalizeGraph(nodes, edges) {
|
|
44
|
+
if (!Array.isArray(nodes) || !Array.isArray(edges)) {
|
|
45
|
+
throw new DagChainError('DAG_INVALID_GRAPH', 'nodes and edges must be arrays');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const nodeSet = new Set();
|
|
49
|
+
for (const node of nodes) {
|
|
50
|
+
if (nodeSet.has(node)) {
|
|
51
|
+
throw new DagChainError('DAG_DUPLICATE_NODE', 'nodes must be unique');
|
|
52
|
+
}
|
|
53
|
+
nodeSet.add(node);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const successors = new Map(nodes.map((node) => [node, []]));
|
|
57
|
+
const predecessors = new Map(nodes.map((node) => [node, []]));
|
|
58
|
+
const normalizedEdges = [];
|
|
59
|
+
const seenBySource = new Map();
|
|
60
|
+
|
|
61
|
+
for (const edge of edges) {
|
|
62
|
+
if (!Array.isArray(edge) || edge.length !== 2) {
|
|
63
|
+
throw new DagChainError('DAG_INVALID_EDGE', 'each edge must be a [from, to] pair');
|
|
64
|
+
}
|
|
65
|
+
const [from, to] = edge;
|
|
66
|
+
if (!nodeSet.has(from) || !nodeSet.has(to)) {
|
|
67
|
+
throw new DagChainError('DAG_DANGLING_EDGE', 'edge endpoint is absent from nodes');
|
|
68
|
+
}
|
|
69
|
+
let targets = seenBySource.get(from);
|
|
70
|
+
if (targets === undefined) {
|
|
71
|
+
targets = new Set();
|
|
72
|
+
seenBySource.set(from, targets);
|
|
73
|
+
}
|
|
74
|
+
if (targets.has(to)) continue;
|
|
75
|
+
targets.add(to);
|
|
76
|
+
successors.get(from).push(to);
|
|
77
|
+
predecessors.get(to).push(from);
|
|
78
|
+
normalizedEdges.push([from, to]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { successors, predecessors, edges: normalizedEdges };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function topologicalOrder(nodes, successors, predecessors) {
|
|
85
|
+
const indegree = new Map(nodes.map((node) => [node, predecessors.get(node).length]));
|
|
86
|
+
const ready = [];
|
|
87
|
+
for (const node of nodes) {
|
|
88
|
+
if (indegree.get(node) === 0) ready.push(node);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const order = [];
|
|
92
|
+
let cursor = 0;
|
|
93
|
+
while (cursor < ready.length) {
|
|
94
|
+
const node = ready[cursor];
|
|
95
|
+
cursor += 1;
|
|
96
|
+
order.push(node);
|
|
97
|
+
for (const successor of successors.get(node)) {
|
|
98
|
+
const remaining = indegree.get(successor) - 1;
|
|
99
|
+
indegree.set(successor, remaining);
|
|
100
|
+
if (remaining === 0) ready.push(successor);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (order.length !== nodes.length) throw new DagCycleError();
|
|
105
|
+
return order;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function saturatedAdd(left, right, saturationPoint) {
|
|
109
|
+
if (left >= saturationPoint || right >= saturationPoint) return saturationPoint;
|
|
110
|
+
if (left > saturationPoint - right) return saturationPoint;
|
|
111
|
+
return left + right;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function enumerateRepresentatives({
|
|
115
|
+
orderedNodes,
|
|
116
|
+
successors,
|
|
117
|
+
down,
|
|
118
|
+
up,
|
|
119
|
+
maximumDepth,
|
|
120
|
+
representativeLimit,
|
|
121
|
+
}) {
|
|
122
|
+
if (maximumDepth === 0 || representativeLimit === 0) return [];
|
|
123
|
+
|
|
124
|
+
const eligibleSuccessors = new Map();
|
|
125
|
+
for (const node of orderedNodes) {
|
|
126
|
+
eligibleSuccessors.set(
|
|
127
|
+
node,
|
|
128
|
+
successors.get(node).filter((successor) => (
|
|
129
|
+
up.get(successor) + 1 === up.get(node)
|
|
130
|
+
)),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const starts = orderedNodes.filter((node) => down.get(node) === 1 && up.get(node) === maximumDepth);
|
|
135
|
+
const representatives = [];
|
|
136
|
+
|
|
137
|
+
for (const start of starts) {
|
|
138
|
+
const path = [start];
|
|
139
|
+
const frames = [{ node: start, successorIndex: 0 }];
|
|
140
|
+
|
|
141
|
+
while (frames.length > 0 && representatives.length < representativeLimit) {
|
|
142
|
+
const frame = frames[frames.length - 1];
|
|
143
|
+
if (up.get(frame.node) === 1) {
|
|
144
|
+
representatives.push([...path]);
|
|
145
|
+
frames.pop();
|
|
146
|
+
path.pop();
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const choices = eligibleSuccessors.get(frame.node);
|
|
151
|
+
if (frame.successorIndex >= choices.length) {
|
|
152
|
+
frames.pop();
|
|
153
|
+
path.pop();
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const successor = choices[frame.successorIndex];
|
|
158
|
+
frame.successorIndex += 1;
|
|
159
|
+
path.push(successor);
|
|
160
|
+
frames.push({ node: successor, successorIndex: 0 });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (representatives.length >= representativeLimit) break;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return representatives;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function analyzeDagChains(
|
|
170
|
+
nodes,
|
|
171
|
+
edges,
|
|
172
|
+
{
|
|
173
|
+
countCap = 1_000_000,
|
|
174
|
+
representativeLimit = 8,
|
|
175
|
+
compare = defaultCompare,
|
|
176
|
+
} = {},
|
|
177
|
+
) {
|
|
178
|
+
assertOptions(countCap, representativeLimit);
|
|
179
|
+
if (typeof compare !== 'function') {
|
|
180
|
+
throw new DagChainError('DAG_INVALID_COMPARATOR', 'compare must be a function');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const graph = normalizeGraph(nodes, edges);
|
|
184
|
+
const order = topologicalOrder(nodes, graph.successors, graph.predecessors);
|
|
185
|
+
const saturationPoint = countCap + 1;
|
|
186
|
+
const down = new Map();
|
|
187
|
+
const waysDown = new Map();
|
|
188
|
+
|
|
189
|
+
for (const node of order) {
|
|
190
|
+
let depth = 1;
|
|
191
|
+
let ways = 1;
|
|
192
|
+
for (const predecessor of graph.predecessors.get(node)) {
|
|
193
|
+
const candidateDepth = down.get(predecessor) + 1;
|
|
194
|
+
if (candidateDepth > depth) {
|
|
195
|
+
depth = candidateDepth;
|
|
196
|
+
ways = waysDown.get(predecessor);
|
|
197
|
+
} else if (candidateDepth === depth) {
|
|
198
|
+
ways = saturatedAdd(ways, waysDown.get(predecessor), saturationPoint);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
down.set(node, depth);
|
|
202
|
+
waysDown.set(node, ways);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const up = new Map();
|
|
206
|
+
const waysUp = new Map();
|
|
207
|
+
for (let index = order.length - 1; index >= 0; index -= 1) {
|
|
208
|
+
const node = order[index];
|
|
209
|
+
let depth = 1;
|
|
210
|
+
let ways = 1;
|
|
211
|
+
for (const successor of graph.successors.get(node)) {
|
|
212
|
+
const candidateDepth = up.get(successor) + 1;
|
|
213
|
+
if (candidateDepth > depth) {
|
|
214
|
+
depth = candidateDepth;
|
|
215
|
+
ways = waysUp.get(successor);
|
|
216
|
+
} else if (candidateDepth === depth) {
|
|
217
|
+
ways = saturatedAdd(ways, waysUp.get(successor), saturationPoint);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
up.set(node, depth);
|
|
221
|
+
waysUp.set(node, ways);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let maximumDepth = 0;
|
|
225
|
+
for (const node of nodes) maximumDepth = Math.max(maximumDepth, down.get(node) ?? 0);
|
|
226
|
+
|
|
227
|
+
let saturatedCount = 0;
|
|
228
|
+
for (const node of nodes) {
|
|
229
|
+
if (down.get(node) === maximumDepth) {
|
|
230
|
+
saturatedCount = saturatedAdd(saturatedCount, waysDown.get(node), saturationPoint);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const orderedNodes = [...nodes].sort(compare);
|
|
235
|
+
for (const values of graph.successors.values()) values.sort(compare);
|
|
236
|
+
const longestChainNodes = orderedNodes.filter((node) => (
|
|
237
|
+
down.get(node) + up.get(node) - 1 === maximumDepth
|
|
238
|
+
));
|
|
239
|
+
const longestChainEdges = graph.edges
|
|
240
|
+
.filter(([from, to]) => down.get(from) + up.get(to) === maximumDepth)
|
|
241
|
+
.sort((left, right) => compare(left[0], right[0]) || compare(left[1], right[1]));
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
maximumDepth,
|
|
245
|
+
longestChainNodes,
|
|
246
|
+
longestChainEdges,
|
|
247
|
+
longestChainCount: {
|
|
248
|
+
count: Math.min(saturatedCount, countCap),
|
|
249
|
+
overflow: saturatedCount === saturationPoint,
|
|
250
|
+
},
|
|
251
|
+
representativeChains: enumerateRepresentatives({
|
|
252
|
+
orderedNodes,
|
|
253
|
+
successors: graph.successors,
|
|
254
|
+
down,
|
|
255
|
+
up,
|
|
256
|
+
maximumDepth,
|
|
257
|
+
representativeLimit,
|
|
258
|
+
}),
|
|
259
|
+
topologicalOrder: order,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile, lstat } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* dotagents工場の native factory diagnostics 面(親plan L6要件)。
|
|
@@ -8,7 +8,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
* - schema `lattice.native_factory_diagnostics.v1`: exact key・bounded・秘密なしJSON。
|
|
9
9
|
* - read-only: provider・network・run store書込・index生成を一切行わない。
|
|
10
10
|
* - 非0意味論: overall `failed` → exit 1。CLI usage違反は既存contractどおり exit 2。
|
|
11
|
-
* -
|
|
11
|
+
* - 本面が健全性の唯一の診断正本(旧`doctor --json`はADR 0052で退役済み)。
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const SCHEMA = 'lattice.native_factory_diagnostics.v1';
|
|
@@ -17,7 +17,7 @@ const MAX_DETAIL_LENGTH = 256;
|
|
|
17
17
|
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
18
18
|
const UNKNOWN_VERSION_SENTINEL = '0.0.0-unknown';
|
|
19
19
|
const NODE_VERSION_PATTERN = /^v(\d+)\.(\d+)\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
|
|
20
|
-
const
|
|
20
|
+
const ENGINES_FLOOR_RANGE_PATTERN = /^(>=(\d+)(?:\.(\d+))?(?:\.\d+)?)(?: +<25(?:\.0\.0)? +\|\| +>=26(?:\.0\.0)?)$/;
|
|
21
21
|
const CHECK_IDS = Object.freeze([
|
|
22
22
|
'package_version',
|
|
23
23
|
'node_runtime',
|
|
@@ -70,23 +70,24 @@ function checkNodeRuntime(nodeVersion, enginesNode) {
|
|
|
70
70
|
if (!runtime) {
|
|
71
71
|
return check('node_runtime', false, 'node version is unreadable');
|
|
72
72
|
}
|
|
73
|
-
const floor =
|
|
73
|
+
const floor = ENGINES_FLOOR_RANGE_PATTERN.exec(enginesNode ?? '');
|
|
74
74
|
if (!floor) {
|
|
75
75
|
return check('node_runtime', false, 'package.json engines.node floor is unreadable');
|
|
76
76
|
}
|
|
77
77
|
const [major, minor] = [Number(runtime[1]), Number(runtime[2])];
|
|
78
|
-
const [floorMajor, floorMinor] = [Number(floor[
|
|
78
|
+
const [floorMajor, floorMinor] = [Number(floor[2]), Number(floor[3] ?? '0')];
|
|
79
79
|
const satisfied = major > floorMajor || (major === floorMajor && minor >= floorMinor);
|
|
80
80
|
return check(
|
|
81
81
|
'node_runtime',
|
|
82
82
|
satisfied,
|
|
83
|
-
satisfied ? `${nodeVersion} satisfies engines.node ${
|
|
83
|
+
satisfied ? `${nodeVersion} satisfies engines.node floor ${floor[1]}`
|
|
84
|
+
: `${nodeVersion} is below engines.node floor ${floor[1]}`,
|
|
84
85
|
);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
async function checkCliSurface(rootDir) {
|
|
88
89
|
try {
|
|
89
|
-
const runtimeCli = await import(path.join(rootDir, 'src', 'runtime-cli.mjs'));
|
|
90
|
+
const runtimeCli = await import(pathToFileURL(path.join(rootDir, 'src', 'runtime-cli.mjs')).href);
|
|
90
91
|
if (typeof runtimeCli.runRuntimeCli !== 'function') {
|
|
91
92
|
return check('cli_surface', false, 'src/runtime-cli.mjs does not export runRuntimeCli');
|
|
92
93
|
}
|