@flyingrobots/graft 0.6.1 → 0.7.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 +135 -0
- package/README.md +1 -1
- package/dist/adapters/json-text-decoder.d.ts +3 -0
- package/dist/adapters/json-text-decoder.d.ts.map +1 -0
- package/dist/adapters/json-text-decoder.js +12 -0
- package/dist/adapters/json-text-decoder.js.map +1 -0
- package/dist/adapters/node-paths.d.ts +3 -0
- package/dist/adapters/node-paths.d.ts.map +1 -0
- package/dist/adapters/node-paths.js +29 -0
- package/dist/adapters/node-paths.js.map +1 -0
- package/dist/adapters/repo-paths.d.ts.map +1 -1
- package/dist/adapters/repo-paths.js +40 -5
- package/dist/adapters/repo-paths.js.map +1 -1
- package/dist/api/tool-bridge.d.ts +1 -1
- package/dist/api/tool-bridge.d.ts.map +1 -1
- package/dist/api/tool-bridge.js +1 -1
- package/dist/api/tool-bridge.js.map +1 -1
- package/dist/cli/cli-error.d.ts.map +1 -1
- package/dist/cli/cli-error.js +47 -10
- package/dist/cli/cli-error.js.map +1 -1
- package/dist/cli/command-parser.d.ts +12 -3
- package/dist/cli/command-parser.d.ts.map +1 -1
- package/dist/cli/command-parser.js +161 -2
- package/dist/cli/command-parser.js.map +1 -1
- package/dist/cli/daemon-status-model.d.ts +87 -0
- package/dist/cli/daemon-status-model.d.ts.map +1 -0
- package/dist/cli/daemon-status-model.js +142 -0
- package/dist/cli/daemon-status-model.js.map +1 -0
- package/dist/cli/daemon-status-render.d.ts +3 -0
- package/dist/cli/daemon-status-render.d.ts.map +1 -0
- package/dist/cli/daemon-status-render.js +100 -0
- package/dist/cli/daemon-status-render.js.map +1 -0
- package/dist/cli/daemon-status.d.ts +7 -0
- package/dist/cli/daemon-status.d.ts.map +1 -0
- package/dist/cli/daemon-status.js +79 -0
- package/dist/cli/daemon-status.js.map +1 -0
- package/dist/cli/git-graft-enhance-model.d.ts +67 -0
- package/dist/cli/git-graft-enhance-model.d.ts.map +1 -0
- package/dist/cli/git-graft-enhance-model.js +55 -0
- package/dist/cli/git-graft-enhance-model.js.map +1 -0
- package/dist/cli/git-graft-enhance-render.d.ts +3 -0
- package/dist/cli/git-graft-enhance-render.d.ts.map +1 -0
- package/dist/cli/git-graft-enhance-render.js +29 -0
- package/dist/cli/git-graft-enhance-render.js.map +1 -0
- package/dist/cli/git-graft-enhance.d.ts +14 -0
- package/dist/cli/git-graft-enhance.d.ts.map +1 -0
- package/dist/cli/git-graft-enhance.js +29 -0
- package/dist/cli/git-graft-enhance.js.map +1 -0
- package/dist/cli/index-cmd.d.ts.map +1 -1
- package/dist/cli/index-cmd.js +18 -21
- package/dist/cli/index-cmd.js.map +1 -1
- package/dist/cli/index-model.d.ts +5 -9
- package/dist/cli/index-model.d.ts.map +1 -1
- package/dist/cli/index-model.js +20 -18
- package/dist/cli/index-model.js.map +1 -1
- package/dist/cli/init-client-config.d.ts +12 -7
- package/dist/cli/init-client-config.d.ts.map +1 -1
- package/dist/cli/init-client-config.js +105 -43
- package/dist/cli/init-client-config.js.map +1 -1
- package/dist/cli/init-model.d.ts +9 -2
- package/dist/cli/init-model.d.ts.map +1 -1
- package/dist/cli/init-model.js +52 -4
- package/dist/cli/init-model.js.map +1 -1
- package/dist/cli/init-render.d.ts.map +1 -1
- package/dist/cli/init-render.js +2 -2
- package/dist/cli/init-render.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +11 -9
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/json-document.d.ts +5 -0
- package/dist/cli/json-document.d.ts.map +1 -1
- package/dist/cli/json-document.js +9 -0
- package/dist/cli/json-document.js.map +1 -1
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +49 -7
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migrate-local-history.d.ts.map +1 -1
- package/dist/cli/migrate-local-history.js +3 -2
- package/dist/cli/migrate-local-history.js.map +1 -1
- package/dist/cli/peer-command.d.ts +1 -1
- package/dist/cli/peer-command.d.ts.map +1 -1
- package/dist/cli/peer-command.js +1 -1
- package/dist/cli/peer-command.js.map +1 -1
- package/dist/contracts/capabilities.d.ts +5 -5
- package/dist/contracts/capabilities.d.ts.map +1 -1
- package/dist/contracts/capabilities.js +89 -0
- package/dist/contracts/capabilities.js.map +1 -1
- package/dist/contracts/causal-ontology.d.ts +17 -17
- package/dist/contracts/json-object.d.ts +0 -1
- package/dist/contracts/json-object.d.ts.map +1 -1
- package/dist/contracts/json-object.js +0 -10
- package/dist/contracts/json-object.js.map +1 -1
- package/dist/contracts/output-schema-cli.d.ts +277 -25
- package/dist/contracts/output-schema-cli.d.ts.map +1 -1
- package/dist/contracts/output-schema-cli.js +35 -3
- package/dist/contracts/output-schema-cli.js.map +1 -1
- package/dist/contracts/output-schema-fragments.d.ts +212 -87
- package/dist/contracts/output-schema-fragments.d.ts.map +1 -1
- package/dist/contracts/output-schema-fragments.js +49 -2
- package/dist/contracts/output-schema-fragments.js.map +1 -1
- package/dist/contracts/output-schema-mcp.d.ts +372 -47
- package/dist/contracts/output-schema-mcp.d.ts.map +1 -1
- package/dist/contracts/output-schema-mcp.js +217 -1
- package/dist/contracts/output-schema-mcp.js.map +1 -1
- package/dist/contracts/output-schema-meta.d.ts +2 -2
- package/dist/contracts/output-schema-meta.d.ts.map +1 -1
- package/dist/contracts/output-schemas.d.ts +7 -7
- package/dist/contracts/output-schemas.d.ts.map +1 -1
- package/dist/contracts/output-schemas.js +294 -6
- package/dist/contracts/output-schemas.js.map +1 -1
- package/dist/git/diff.d.ts +11 -0
- package/dist/git/diff.d.ts.map +1 -1
- package/dist/git/diff.js +50 -6
- package/dist/git/diff.js.map +1 -1
- package/dist/mcp/burden.d.ts.map +1 -1
- package/dist/mcp/burden.js +9 -0
- package/dist/mcp/burden.js.map +1 -1
- package/dist/mcp/context.d.ts +3 -2
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/context.js +2 -37
- package/dist/mcp/context.js.map +1 -1
- package/dist/mcp/daemon-server.d.ts +2 -0
- package/dist/mcp/daemon-server.d.ts.map +1 -1
- package/dist/mcp/daemon-server.js +6 -1
- package/dist/mcp/daemon-server.js.map +1 -1
- package/dist/mcp/daemon-session-host.d.ts +1 -0
- package/dist/mcp/daemon-session-host.d.ts.map +1 -1
- package/dist/mcp/daemon-session-host.js +3 -0
- package/dist/mcp/daemon-session-host.js.map +1 -1
- package/dist/mcp/daemon-stdio-bridge.d.ts +1 -0
- package/dist/mcp/daemon-stdio-bridge.d.ts.map +1 -1
- package/dist/mcp/daemon-stdio-bridge.js +1 -0
- package/dist/mcp/daemon-stdio-bridge.js.map +1 -1
- package/dist/mcp/monitor-tick-job.d.ts +1 -0
- package/dist/mcp/monitor-tick-job.d.ts.map +1 -1
- package/dist/mcp/monitor-tick-job.js +84 -29
- package/dist/mcp/monitor-tick-job.js.map +1 -1
- package/dist/mcp/monitor-types.d.ts +1 -1
- package/dist/mcp/monitor-types.d.ts.map +1 -1
- package/dist/mcp/persisted-local-history-graph.d.ts +2 -2
- package/dist/mcp/persisted-local-history-graph.d.ts.map +1 -1
- package/dist/mcp/persisted-local-history-graph.js +3 -2
- package/dist/mcp/persisted-local-history-graph.js.map +1 -1
- package/dist/mcp/persisted-local-history.d.ts +5 -5
- package/dist/mcp/persisted-local-history.js +2 -2
- package/dist/mcp/persisted-local-history.js.map +1 -1
- package/dist/mcp/persistent-monitor-runtime.d.ts +1 -0
- package/dist/mcp/persistent-monitor-runtime.d.ts.map +1 -1
- package/dist/mcp/persistent-monitor-runtime.js +35 -0
- package/dist/mcp/persistent-monitor-runtime.js.map +1 -1
- package/dist/mcp/repo-tool-worker-context.d.ts.map +1 -1
- package/dist/mcp/repo-tool-worker-context.js +5 -2
- package/dist/mcp/repo-tool-worker-context.js.map +1 -1
- package/dist/mcp/server-context.d.ts.map +1 -1
- package/dist/mcp/server-context.js +13 -0
- package/dist/mcp/server-context.js.map +1 -1
- package/dist/mcp/server-tool-access.d.ts +1 -1
- package/dist/mcp/server-tool-access.d.ts.map +1 -1
- package/dist/mcp/server-tool-access.js +3 -1
- package/dist/mcp/server-tool-access.js.map +1 -1
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +5 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +18 -0
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/mcp/tools/code-find.d.ts.map +1 -1
- package/dist/mcp/tools/code-find.js +20 -0
- package/dist/mcp/tools/code-find.js.map +1 -1
- package/dist/mcp/tools/code-show.d.ts.map +1 -1
- package/dist/mcp/tools/code-show.js +24 -0
- package/dist/mcp/tools/code-show.js.map +1 -1
- package/dist/mcp/tools/diagnostic-models.d.ts +2 -0
- package/dist/mcp/tools/diagnostic-models.d.ts.map +1 -1
- package/dist/mcp/tools/doctor.d.ts.map +1 -1
- package/dist/mcp/tools/doctor.js +18 -1
- package/dist/mcp/tools/doctor.js.map +1 -1
- package/dist/mcp/tools/export-surface-diff.d.ts +3 -0
- package/dist/mcp/tools/export-surface-diff.d.ts.map +1 -0
- package/dist/mcp/tools/export-surface-diff.js +24 -0
- package/dist/mcp/tools/export-surface-diff.js.map +1 -0
- package/dist/mcp/tools/file-outline.js +1 -1
- package/dist/mcp/tools/file-outline.js.map +1 -1
- package/dist/mcp/tools/graft-edit.d.ts +3 -0
- package/dist/mcp/tools/graft-edit.d.ts.map +1 -0
- package/dist/mcp/tools/graft-edit.js +192 -0
- package/dist/mcp/tools/graft-edit.js.map +1 -0
- package/dist/mcp/tools/knowledge-map.d.ts +3 -0
- package/dist/mcp/tools/knowledge-map.d.ts.map +1 -0
- package/dist/mcp/tools/knowledge-map.js +31 -0
- package/dist/mcp/tools/knowledge-map.js.map +1 -0
- package/dist/mcp/tools/monitor-nudge.d.ts +3 -0
- package/dist/mcp/tools/monitor-nudge.d.ts.map +1 -0
- package/dist/mcp/tools/monitor-nudge.js +17 -0
- package/dist/mcp/tools/monitor-nudge.js.map +1 -0
- package/dist/mcp/tools/precision-warp.d.ts +3 -3
- package/dist/mcp/tools/precision-warp.d.ts.map +1 -1
- package/dist/mcp/tools/precision-warp.js +24 -15
- package/dist/mcp/tools/precision-warp.js.map +1 -1
- package/dist/mcp/tools/refactor-difficulty.d.ts +3 -0
- package/dist/mcp/tools/refactor-difficulty.d.ts.map +1 -0
- package/dist/mcp/tools/refactor-difficulty.js +36 -0
- package/dist/mcp/tools/refactor-difficulty.js.map +1 -0
- package/dist/mcp/tools/safe-read.js +2 -2
- package/dist/mcp/tools/safe-read.js.map +1 -1
- package/dist/mcp/tools/structural-blame.d.ts +3 -0
- package/dist/mcp/tools/structural-blame.d.ts.map +1 -0
- package/dist/mcp/tools/structural-blame.js +44 -0
- package/dist/mcp/tools/structural-blame.js.map +1 -0
- package/dist/mcp/tools/structural-churn.d.ts +3 -0
- package/dist/mcp/tools/structural-churn.d.ts.map +1 -0
- package/dist/mcp/tools/structural-churn.js +28 -0
- package/dist/mcp/tools/structural-churn.js.map +1 -0
- package/dist/mcp/tools/structural-log.d.ts +3 -0
- package/dist/mcp/tools/structural-log.d.ts.map +1 -0
- package/dist/mcp/tools/structural-log.js +38 -0
- package/dist/mcp/tools/structural-log.js.map +1 -0
- package/dist/mcp/tools/structural-review.d.ts +3 -0
- package/dist/mcp/tools/structural-review.d.ts.map +1 -0
- package/dist/mcp/tools/structural-review.js +55 -0
- package/dist/mcp/tools/structural-review.js.map +1 -0
- package/dist/mcp/warp-pool.d.ts +4 -4
- package/dist/mcp/warp-pool.d.ts.map +1 -1
- package/dist/mcp/warp-pool.js.map +1 -1
- package/dist/mcp/workspace-router-model.d.ts +2 -2
- package/dist/mcp/workspace-router-model.d.ts.map +1 -1
- package/dist/mcp/workspace-router-runtime.d.ts +3 -3
- package/dist/mcp/workspace-router-runtime.d.ts.map +1 -1
- package/dist/mcp/workspace-router-runtime.js +4 -1
- package/dist/mcp/workspace-router-runtime.js.map +1 -1
- package/dist/mcp/workspace-router.d.ts +3 -2
- package/dist/mcp/workspace-router.d.ts.map +1 -1
- package/dist/mcp/workspace-router.js +6 -0
- package/dist/mcp/workspace-router.js.map +1 -1
- package/dist/operations/adaptive-projection.d.ts +22 -0
- package/dist/operations/adaptive-projection.d.ts.map +1 -0
- package/dist/operations/adaptive-projection.js +36 -0
- package/dist/operations/adaptive-projection.js.map +1 -0
- package/dist/operations/agent-handoff.d.ts +25 -0
- package/dist/operations/agent-handoff.d.ts.map +1 -0
- package/dist/operations/agent-handoff.js +36 -0
- package/dist/operations/agent-handoff.js.map +1 -0
- package/dist/operations/capture-range.d.ts +33 -0
- package/dist/operations/capture-range.d.ts.map +1 -0
- package/dist/operations/capture-range.js +45 -0
- package/dist/operations/capture-range.js.map +1 -0
- package/dist/operations/conversation-primer.d.ts +27 -0
- package/dist/operations/conversation-primer.d.ts.map +1 -0
- package/dist/operations/conversation-primer.js +52 -0
- package/dist/operations/conversation-primer.js.map +1 -0
- package/dist/operations/cross-session-resume.d.ts +28 -0
- package/dist/operations/cross-session-resume.d.ts.map +1 -0
- package/dist/operations/cross-session-resume.js +79 -0
- package/dist/operations/cross-session-resume.js.map +1 -0
- package/dist/operations/deterministic-replay.d.ts +39 -0
- package/dist/operations/deterministic-replay.d.ts.map +1 -0
- package/dist/operations/deterministic-replay.js +90 -0
- package/dist/operations/deterministic-replay.js.map +1 -0
- package/dist/operations/export-surface-diff.d.ts +36 -0
- package/dist/operations/export-surface-diff.d.ts.map +1 -0
- package/dist/operations/export-surface-diff.js +298 -0
- package/dist/operations/export-surface-diff.js.map +1 -0
- package/dist/operations/footprint-parallelism.d.ts +25 -0
- package/dist/operations/footprint-parallelism.d.ts.map +1 -0
- package/dist/operations/footprint-parallelism.js +79 -0
- package/dist/operations/footprint-parallelism.js.map +1 -0
- package/dist/operations/graft-diff.d.ts.map +1 -1
- package/dist/operations/graft-diff.js +14 -7
- package/dist/operations/graft-diff.js.map +1 -1
- package/dist/operations/horizon-of-readability.d.ts +23 -0
- package/dist/operations/horizon-of-readability.d.ts.map +1 -0
- package/dist/operations/horizon-of-readability.js +39 -0
- package/dist/operations/horizon-of-readability.js.map +1 -0
- package/dist/operations/import-reference-impact.d.ts +13 -0
- package/dist/operations/import-reference-impact.d.ts.map +1 -0
- package/dist/operations/import-reference-impact.js +101 -0
- package/dist/operations/import-reference-impact.js.map +1 -0
- package/dist/operations/knowledge-map.d.ts +30 -0
- package/dist/operations/knowledge-map.d.ts.map +1 -0
- package/dist/operations/knowledge-map.js +64 -0
- package/dist/operations/knowledge-map.js.map +1 -0
- package/dist/operations/observation-cache.d.ts +8 -2
- package/dist/operations/observation-cache.d.ts.map +1 -1
- package/dist/operations/observation-cache.js +17 -5
- package/dist/operations/observation-cache.js.map +1 -1
- package/dist/operations/projection-safety.d.ts +31 -0
- package/dist/operations/projection-safety.d.ts.map +1 -0
- package/dist/operations/projection-safety.js +77 -0
- package/dist/operations/projection-safety.js.map +1 -0
- package/dist/operations/repo-workspace.js +3 -3
- package/dist/operations/repo-workspace.js.map +1 -1
- package/dist/operations/semantic-drift.d.ts +27 -0
- package/dist/operations/semantic-drift.d.ts.map +1 -0
- package/dist/operations/semantic-drift.js +46 -0
- package/dist/operations/semantic-drift.js.map +1 -0
- package/dist/operations/session-filtration.d.ts +36 -0
- package/dist/operations/session-filtration.d.ts.map +1 -0
- package/dist/operations/session-filtration.js +48 -0
- package/dist/operations/session-filtration.js.map +1 -0
- package/dist/operations/session-replay.d.ts +17 -0
- package/dist/operations/session-replay.d.ts.map +1 -0
- package/dist/operations/session-replay.js +59 -0
- package/dist/operations/session-replay.js.map +1 -0
- package/dist/operations/sludge-detector.d.ts +45 -0
- package/dist/operations/sludge-detector.d.ts.map +1 -0
- package/dist/operations/sludge-detector.js +278 -0
- package/dist/operations/sludge-detector.js.map +1 -0
- package/dist/operations/structural-blame.d.ts +67 -0
- package/dist/operations/structural-blame.d.ts.map +1 -0
- package/dist/operations/structural-blame.js +111 -0
- package/dist/operations/structural-blame.js.map +1 -0
- package/dist/operations/structural-review.d.ts +47 -0
- package/dist/operations/structural-review.d.ts.map +1 -0
- package/dist/operations/structural-review.js +225 -0
- package/dist/operations/structural-review.js.map +1 -0
- package/dist/operations/teaching-hints.d.ts +18 -0
- package/dist/operations/teaching-hints.d.ts.map +1 -0
- package/dist/operations/teaching-hints.js +35 -0
- package/dist/operations/teaching-hints.js.map +1 -0
- package/dist/parser/diff.d.ts +2 -0
- package/dist/parser/diff.d.ts.map +1 -1
- package/dist/parser/diff.js +7 -0
- package/dist/parser/diff.js.map +1 -1
- package/dist/ports/paths.d.ts +17 -0
- package/dist/ports/paths.d.ts.map +1 -0
- package/dist/ports/{warp.js → paths.js} +2 -2
- package/dist/ports/paths.js.map +1 -0
- package/dist/warp/ast-emitter.d.ts +28 -0
- package/dist/warp/ast-emitter.d.ts.map +1 -0
- package/dist/warp/ast-emitter.js +90 -0
- package/dist/warp/ast-emitter.js.map +1 -0
- package/dist/warp/ast-import-resolver.d.ts +13 -0
- package/dist/warp/ast-import-resolver.d.ts.map +1 -0
- package/dist/warp/ast-import-resolver.js +259 -0
- package/dist/warp/ast-import-resolver.js.map +1 -0
- package/dist/warp/commit-meta.d.ts +8 -0
- package/dist/warp/commit-meta.d.ts.map +1 -0
- package/dist/warp/commit-meta.js +13 -0
- package/dist/warp/commit-meta.js.map +1 -0
- package/dist/warp/context.d.ts +10 -0
- package/dist/warp/context.d.ts.map +1 -0
- package/dist/warp/context.js +26 -0
- package/dist/warp/context.js.map +1 -0
- package/dist/warp/dead-symbols.d.ts +40 -0
- package/dist/warp/dead-symbols.d.ts.map +1 -0
- package/dist/warp/dead-symbols.js +127 -0
- package/dist/warp/dead-symbols.js.map +1 -0
- package/dist/warp/drift-sentinel.d.ts +30 -0
- package/dist/warp/drift-sentinel.d.ts.map +1 -0
- package/dist/warp/drift-sentinel.js +65 -0
- package/dist/warp/drift-sentinel.js.map +1 -0
- package/dist/warp/index-head.d.ts +32 -0
- package/dist/warp/index-head.d.ts.map +1 -0
- package/dist/warp/index-head.js +245 -0
- package/dist/warp/index-head.js.map +1 -0
- package/dist/warp/observers.d.ts +6 -6
- package/dist/warp/observers.d.ts.map +1 -1
- package/dist/warp/observers.js +5 -4
- package/dist/warp/observers.js.map +1 -1
- package/dist/warp/open.d.ts +5 -4
- package/dist/warp/open.d.ts.map +1 -1
- package/dist/warp/open.js +24 -49
- package/dist/warp/open.js.map +1 -1
- package/dist/warp/outline-diff-trailer.d.ts +26 -0
- package/dist/warp/outline-diff-trailer.d.ts.map +1 -0
- package/dist/warp/outline-diff-trailer.js +68 -0
- package/dist/warp/outline-diff-trailer.js.map +1 -0
- package/dist/warp/refactor-difficulty.d.ts +38 -0
- package/dist/warp/refactor-difficulty.d.ts.map +1 -0
- package/dist/warp/refactor-difficulty.js +169 -0
- package/dist/warp/refactor-difficulty.js.map +1 -0
- package/dist/warp/references.d.ts +22 -0
- package/dist/warp/references.d.ts.map +1 -0
- package/dist/warp/references.js +57 -0
- package/dist/warp/references.js.map +1 -0
- package/dist/warp/stale-docs.d.ts +56 -0
- package/dist/warp/stale-docs.d.ts.map +1 -0
- package/dist/warp/stale-docs.js +149 -0
- package/dist/warp/stale-docs.js.map +1 -0
- package/dist/warp/structural-drift-detection.d.ts +49 -0
- package/dist/warp/structural-drift-detection.d.ts.map +1 -0
- package/dist/warp/structural-drift-detection.js +51 -0
- package/dist/warp/structural-drift-detection.js.map +1 -0
- package/dist/warp/structural-queries.d.ts +49 -0
- package/dist/warp/structural-queries.d.ts.map +1 -0
- package/dist/warp/structural-queries.js +175 -0
- package/dist/warp/structural-queries.js.map +1 -0
- package/dist/warp/symbol-timeline.d.ts +34 -0
- package/dist/warp/symbol-timeline.d.ts.map +1 -0
- package/dist/warp/symbol-timeline.js +127 -0
- package/dist/warp/symbol-timeline.js.map +1 -0
- package/dist/warp/traverse-hydrate.d.ts +23 -0
- package/dist/warp/traverse-hydrate.d.ts.map +1 -0
- package/dist/warp/traverse-hydrate.js +39 -0
- package/dist/warp/traverse-hydrate.js.map +1 -0
- package/dist/warp/warp-reference-count.d.ts +19 -0
- package/dist/warp/warp-reference-count.d.ts.map +1 -0
- package/dist/warp/warp-reference-count.js +32 -0
- package/dist/warp/warp-reference-count.js.map +1 -0
- package/dist/warp/warp-structural-blame.d.ts +20 -0
- package/dist/warp/warp-structural-blame.d.ts.map +1 -0
- package/dist/warp/warp-structural-blame.js +43 -0
- package/dist/warp/warp-structural-blame.js.map +1 -0
- package/dist/warp/warp-structural-churn.d.ts +30 -0
- package/dist/warp/warp-structural-churn.d.ts.map +1 -0
- package/dist/warp/warp-structural-churn.js +213 -0
- package/dist/warp/warp-structural-churn.js.map +1 -0
- package/dist/warp/warp-structural-log.d.ts +35 -0
- package/dist/warp/warp-structural-log.d.ts.map +1 -0
- package/dist/warp/warp-structural-log.js +104 -0
- package/dist/warp/warp-structural-log.js.map +1 -0
- package/docs/CLI.md +68 -4
- package/docs/MCP.md +23 -0
- package/docs/SETUP.md +101 -20
- package/package.json +5 -3
- package/src/adapters/json-text-decoder.ts +11 -0
- package/src/adapters/node-paths.ts +35 -0
- package/src/adapters/repo-paths.ts +45 -4
- package/src/api/tool-bridge.ts +2 -1
- package/src/cli/cli-error.ts +49 -10
- package/src/cli/command-parser.ts +185 -3
- package/src/cli/daemon-status-model.ts +238 -0
- package/src/cli/daemon-status-render.ts +102 -0
- package/src/cli/daemon-status.ts +100 -0
- package/src/cli/git-graft-enhance-model.ts +131 -0
- package/src/cli/git-graft-enhance-render.ts +33 -0
- package/src/cli/git-graft-enhance.ts +54 -0
- package/src/cli/index-cmd.ts +18 -22
- package/src/cli/index-model.ts +21 -22
- package/src/cli/init-client-config.ts +167 -38
- package/src/cli/init-model.ts +57 -2
- package/src/cli/init-render.ts +2 -2
- package/src/cli/init.ts +11 -9
- package/src/cli/json-document.ts +11 -0
- package/src/cli/main.ts +53 -6
- package/src/cli/migrate-local-history.ts +3 -2
- package/src/cli/peer-command.ts +2 -1
- package/src/contracts/capabilities.ts +90 -0
- package/src/contracts/json-object.ts +1 -11
- package/src/contracts/output-schema-cli.ts +36 -3
- package/src/contracts/output-schema-fragments.ts +52 -2
- package/src/contracts/output-schema-mcp.ts +219 -0
- package/src/contracts/output-schemas.ts +300 -6
- package/src/git/diff.ts +61 -0
- package/src/mcp/burden.ts +9 -0
- package/src/mcp/context.ts +5 -42
- package/src/mcp/daemon-server.ts +8 -1
- package/src/mcp/daemon-session-host.ts +4 -0
- package/src/mcp/daemon-stdio-bridge.ts +2 -0
- package/src/mcp/monitor-tick-job.ts +90 -39
- package/src/mcp/monitor-types.ts +1 -1
- package/src/mcp/persisted-local-history-graph.ts +5 -4
- package/src/mcp/persisted-local-history.ts +2 -2
- package/src/mcp/persistent-monitor-runtime.ts +37 -0
- package/src/mcp/repo-tool-worker-context.ts +5 -2
- package/src/mcp/server-context.ts +15 -2
- package/src/mcp/server-tool-access.ts +4 -1
- package/src/mcp/server.ts +8 -3
- package/src/mcp/tool-registry.ts +18 -0
- package/src/mcp/tools/code-find.ts +23 -0
- package/src/mcp/tools/code-show.ts +27 -0
- package/src/mcp/tools/diagnostic-models.ts +2 -0
- package/src/mcp/tools/doctor.ts +18 -1
- package/src/mcp/tools/export-surface-diff.ts +26 -0
- package/src/mcp/tools/file-outline.ts +1 -1
- package/src/mcp/tools/graft-edit.ts +276 -0
- package/src/mcp/tools/knowledge-map.ts +34 -0
- package/src/mcp/tools/monitor-nudge.ts +19 -0
- package/src/mcp/tools/precision-warp.ts +27 -16
- package/src/mcp/tools/refactor-difficulty.ts +42 -0
- package/src/mcp/tools/safe-read.ts +2 -2
- package/src/mcp/tools/structural-blame.ts +55 -0
- package/src/mcp/tools/structural-churn.ts +28 -0
- package/src/mcp/tools/structural-log.ts +41 -0
- package/src/mcp/tools/structural-review.ts +63 -0
- package/src/mcp/warp-pool.ts +6 -6
- package/src/mcp/workspace-router-model.ts +2 -2
- package/src/mcp/workspace-router-runtime.ts +11 -8
- package/src/mcp/workspace-router.ts +9 -2
- package/src/operations/adaptive-projection.ts +54 -0
- package/src/operations/agent-handoff.ts +59 -0
- package/src/operations/capture-range.ts +64 -0
- package/src/operations/conversation-primer.ts +82 -0
- package/src/operations/cross-session-resume.ts +104 -0
- package/src/operations/deterministic-replay.ts +143 -0
- package/src/operations/export-surface-diff.ts +355 -0
- package/src/operations/footprint-parallelism.ts +98 -0
- package/src/operations/graft-diff.ts +14 -7
- package/src/operations/horizon-of-readability.ts +60 -0
- package/src/operations/import-reference-impact.ts +143 -0
- package/src/operations/knowledge-map.ts +96 -0
- package/src/operations/observation-cache.ts +20 -4
- package/src/operations/projection-safety.ts +111 -0
- package/src/operations/repo-workspace.ts +3 -3
- package/src/operations/semantic-drift.ts +70 -0
- package/src/operations/session-filtration.ts +76 -0
- package/src/operations/session-replay.ts +73 -0
- package/src/operations/sludge-detector.ts +356 -0
- package/src/operations/structural-blame.ts +197 -0
- package/src/operations/structural-review.ts +317 -0
- package/src/operations/teaching-hints.ts +52 -0
- package/src/parser/diff.ts +7 -0
- package/src/ports/paths.ts +22 -0
- package/src/warp/ast-emitter.ts +133 -0
- package/src/warp/ast-import-resolver.ts +333 -0
- package/src/warp/commit-meta.ts +19 -0
- package/src/warp/context.ts +48 -0
- package/src/warp/dead-symbols.ts +174 -0
- package/src/warp/drift-sentinel.ts +101 -0
- package/src/warp/index-head.ts +348 -0
- package/src/warp/observers.ts +8 -7
- package/src/warp/open.ts +40 -66
- package/src/warp/outline-diff-trailer.ts +100 -0
- package/src/warp/plumbing.d.ts +11 -2
- package/src/warp/refactor-difficulty.ts +257 -0
- package/src/warp/references.ts +77 -0
- package/src/warp/stale-docs.ts +210 -0
- package/src/warp/structural-drift-detection.ts +97 -0
- package/src/warp/structural-queries.ts +258 -0
- package/src/warp/symbol-timeline.ts +209 -0
- package/src/warp/traverse-hydrate.ts +61 -0
- package/src/warp/warp-reference-count.ts +47 -0
- package/src/warp/warp-structural-blame.ts +65 -0
- package/src/warp/warp-structural-churn.ts +309 -0
- package/src/warp/warp-structural-log.ts +149 -0
- package/dist/ports/warp.d.ts +0 -45
- package/dist/ports/warp.d.ts.map +0 -1
- package/dist/ports/warp.js.map +0 -1
- package/dist/warp/identity-resolver.d.ts +0 -14
- package/dist/warp/identity-resolver.d.ts.map +0 -1
- package/dist/warp/identity-resolver.js +0 -31
- package/dist/warp/identity-resolver.js.map +0 -1
- package/dist/warp/indexer-git.d.ts +0 -22
- package/dist/warp/indexer-git.d.ts.map +0 -1
- package/dist/warp/indexer-git.js +0 -148
- package/dist/warp/indexer-git.js.map +0 -1
- package/dist/warp/indexer-graph.d.ts +0 -17
- package/dist/warp/indexer-graph.d.ts.map +0 -1
- package/dist/warp/indexer-graph.js +0 -179
- package/dist/warp/indexer-graph.js.map +0 -1
- package/dist/warp/indexer-model.d.ts +0 -51
- package/dist/warp/indexer-model.d.ts.map +0 -1
- package/dist/warp/indexer-model.js +0 -21
- package/dist/warp/indexer-model.js.map +0 -1
- package/dist/warp/indexer.d.ts +0 -9
- package/dist/warp/indexer.d.ts.map +0 -1
- package/dist/warp/indexer.js +0 -112
- package/dist/warp/indexer.js.map +0 -1
- package/dist/warp/symbol-identity.d.ts +0 -11
- package/dist/warp/symbol-identity.d.ts.map +0 -1
- package/dist/warp/symbol-identity.js +0 -67
- package/dist/warp/symbol-identity.js.map +0 -1
- package/src/ports/warp.ts +0 -55
- package/src/warp/identity-resolver.ts +0 -35
- package/src/warp/indexer-git.ts +0 -182
- package/src/warp/indexer-graph.ts +0 -276
- package/src/warp/indexer-model.ts +0 -69
- package/src/warp/indexer.ts +0 -186
- package/src/warp/symbol-identity.ts +0 -100
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { getFileAtRef } from "../git/diff.js";
|
|
2
|
+
import { detectLang } from "../parser/lang.js";
|
|
3
|
+
import type { GitClient } from "../ports/git.js";
|
|
4
|
+
import type { PathOps } from "../ports/paths.js";
|
|
5
|
+
import type { ReferenceCountResult } from "./structural-review.js";
|
|
6
|
+
|
|
7
|
+
const NAMED_IMPORT_OR_REEXPORT =
|
|
8
|
+
/\b(?:import|export)\s+(?:type\s+)?\{([\s\S]*?)\}\s+from\s+["']([^"']+)["']/g;
|
|
9
|
+
|
|
10
|
+
export interface ImportReferenceImpactOptions {
|
|
11
|
+
readonly cwd: string;
|
|
12
|
+
readonly git: GitClient;
|
|
13
|
+
readonly pathOps: PathOps;
|
|
14
|
+
readonly symbolName: string;
|
|
15
|
+
readonly filePath: string;
|
|
16
|
+
readonly ref: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function listFilesAtRef(opts: Pick<ImportReferenceImpactOptions, "cwd" | "git" | "ref">): Promise<readonly string[]> {
|
|
20
|
+
const result = await opts.git.run({
|
|
21
|
+
args: ["ls-tree", "-r", "--name-only", opts.ref],
|
|
22
|
+
cwd: opts.cwd,
|
|
23
|
+
});
|
|
24
|
+
if (result.error !== undefined || result.status !== 0) {
|
|
25
|
+
throw result.error ?? new Error(result.stderr.trim() || `git ls-tree failed with status ${String(result.status)}`);
|
|
26
|
+
}
|
|
27
|
+
const output = result.stdout.trim();
|
|
28
|
+
return output.length === 0 ? [] : output.split("\n");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function compiledSpecifierSourceCandidates(resolvedImportSource: string): readonly string[] {
|
|
32
|
+
const compiledToSourceExtensions: readonly [string, readonly string[]][] = [
|
|
33
|
+
[".js", [".ts", ".tsx"]],
|
|
34
|
+
[".jsx", [".tsx", ".ts"]],
|
|
35
|
+
[".mjs", [".mts", ".ts"]],
|
|
36
|
+
[".cjs", [".cts", ".ts"]],
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
for (const [compiledExtension, sourceExtensions] of compiledToSourceExtensions) {
|
|
40
|
+
if (!resolvedImportSource.endsWith(compiledExtension)) continue;
|
|
41
|
+
|
|
42
|
+
const base = resolvedImportSource.slice(0, -compiledExtension.length);
|
|
43
|
+
return sourceExtensions.map((sourceExtension) => `${base}${sourceExtension}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function resolveModulePath(
|
|
50
|
+
importSource: string,
|
|
51
|
+
importingFilePath: string,
|
|
52
|
+
knownFiles: ReadonlySet<string>,
|
|
53
|
+
pathOps: PathOps,
|
|
54
|
+
): string | null {
|
|
55
|
+
if (!importSource.startsWith(".") && !importSource.startsWith("/")) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const dir = importingFilePath.includes("/")
|
|
60
|
+
? importingFilePath.slice(0, importingFilePath.lastIndexOf("/"))
|
|
61
|
+
: "";
|
|
62
|
+
const raw = dir.length > 0
|
|
63
|
+
? pathOps.join(dir, importSource)
|
|
64
|
+
: pathOps.normalize(importSource);
|
|
65
|
+
const sourceExtensionCandidates = compiledSpecifierSourceCandidates(raw);
|
|
66
|
+
const candidates = [
|
|
67
|
+
raw,
|
|
68
|
+
...sourceExtensionCandidates,
|
|
69
|
+
`${raw}.ts`,
|
|
70
|
+
`${raw}.tsx`,
|
|
71
|
+
`${raw}.js`,
|
|
72
|
+
`${raw}.jsx`,
|
|
73
|
+
`${raw}/index.ts`,
|
|
74
|
+
`${raw}/index.tsx`,
|
|
75
|
+
`${raw}/index.js`,
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
return candidates.find((candidate) => knownFiles.has(candidate)) ?? null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function importsSymbol(namedImports: string, symbolName: string): boolean {
|
|
82
|
+
return namedImports
|
|
83
|
+
.split(",")
|
|
84
|
+
.map((part) => part.trim().replace(/^type\s+/, ""))
|
|
85
|
+
.some((part) => {
|
|
86
|
+
const importedName = part.split(/\s+as\s+/u)[0]?.trim();
|
|
87
|
+
return importedName === symbolName;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function fileImportsSymbolFromTarget(
|
|
92
|
+
content: string,
|
|
93
|
+
importingFilePath: string,
|
|
94
|
+
symbolName: string,
|
|
95
|
+
targetFilePath: string,
|
|
96
|
+
knownFiles: ReadonlySet<string>,
|
|
97
|
+
pathOps: PathOps,
|
|
98
|
+
): boolean {
|
|
99
|
+
NAMED_IMPORT_OR_REEXPORT.lastIndex = 0;
|
|
100
|
+
let match: RegExpExecArray | null;
|
|
101
|
+
while ((match = NAMED_IMPORT_OR_REEXPORT.exec(content)) !== null) {
|
|
102
|
+
const namedImports = match[1];
|
|
103
|
+
const importSource = match[2];
|
|
104
|
+
if (namedImports === undefined || importSource === undefined) continue;
|
|
105
|
+
if (!importsSymbol(namedImports, symbolName)) continue;
|
|
106
|
+
if (resolveModulePath(importSource, importingFilePath, knownFiles, pathOps) === targetFilePath) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function countNamedImportReferencesAtRef(
|
|
114
|
+
opts: ImportReferenceImpactOptions,
|
|
115
|
+
): Promise<ReferenceCountResult> {
|
|
116
|
+
const files = await listFilesAtRef(opts);
|
|
117
|
+
const knownFiles = new Set(files);
|
|
118
|
+
const referencingFiles: string[] = [];
|
|
119
|
+
|
|
120
|
+
for (const candidate of files) {
|
|
121
|
+
if (candidate === opts.filePath || detectLang(candidate) === null) continue;
|
|
122
|
+
const content = await getFileAtRef(opts.ref, candidate, {
|
|
123
|
+
cwd: opts.cwd,
|
|
124
|
+
git: opts.git,
|
|
125
|
+
});
|
|
126
|
+
if (content === null) continue;
|
|
127
|
+
if (fileImportsSymbolFromTarget(
|
|
128
|
+
content,
|
|
129
|
+
candidate,
|
|
130
|
+
opts.symbolName,
|
|
131
|
+
opts.filePath,
|
|
132
|
+
knownFiles,
|
|
133
|
+
opts.pathOps,
|
|
134
|
+
)) {
|
|
135
|
+
referencingFiles.push(candidate);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
referenceCount: referencingFiles.length,
|
|
141
|
+
referencingFiles,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Knowledge map — "what do I already know?" query over the observation cache
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { ObservationCache } from "./observation-cache.js";
|
|
6
|
+
import { hashContent } from "./observation-cache.js";
|
|
7
|
+
import type { FileSystem } from "../ports/filesystem.js";
|
|
8
|
+
|
|
9
|
+
export interface KnowledgeFileEntry {
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly symbols: readonly string[];
|
|
12
|
+
readonly readCount: number;
|
|
13
|
+
readonly lastReadAt: string;
|
|
14
|
+
readonly stale: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface KnowledgeMapResult {
|
|
18
|
+
readonly totalFiles: number;
|
|
19
|
+
readonly totalSymbols: number;
|
|
20
|
+
readonly files: readonly KnowledgeFileEntry[];
|
|
21
|
+
readonly staleFiles: readonly string[];
|
|
22
|
+
readonly directoryCoverage: Readonly<Record<string, number>>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface KnowledgeMapOptions {
|
|
26
|
+
readonly cache: ObservationCache;
|
|
27
|
+
readonly fs: FileSystem;
|
|
28
|
+
readonly projectRoot: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build a knowledge map from the current observation cache.
|
|
33
|
+
*
|
|
34
|
+
* For each observed file, checks whether the file has changed on disk
|
|
35
|
+
* since it was last read (staleness). Aggregates symbols and directory
|
|
36
|
+
* coverage.
|
|
37
|
+
*/
|
|
38
|
+
export async function buildKnowledgeMap(options: KnowledgeMapOptions): Promise<KnowledgeMapResult> {
|
|
39
|
+
const { cache, fs: fileSystem, projectRoot } = options;
|
|
40
|
+
const files: KnowledgeFileEntry[] = [];
|
|
41
|
+
const staleFiles: string[] = [];
|
|
42
|
+
const dirCounts = new Map<string, number>();
|
|
43
|
+
let totalSymbols = 0;
|
|
44
|
+
|
|
45
|
+
for (const [filePath, observation] of cache.allEntries()) {
|
|
46
|
+
const symbols = observation.outline.map((entry) => entry.name);
|
|
47
|
+
totalSymbols += symbols.length;
|
|
48
|
+
|
|
49
|
+
// Check staleness by reading current content and comparing hash
|
|
50
|
+
let stale: boolean;
|
|
51
|
+
try {
|
|
52
|
+
const currentContent = await fileSystem.readFile(filePath, "utf-8");
|
|
53
|
+
stale = observation.isStale(hashContent(currentContent));
|
|
54
|
+
} catch {
|
|
55
|
+
// File no longer exists — mark as stale
|
|
56
|
+
stale = true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (stale) {
|
|
60
|
+
staleFiles.push(filePath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
files.push({
|
|
64
|
+
path: filePath,
|
|
65
|
+
symbols,
|
|
66
|
+
readCount: observation.readCount,
|
|
67
|
+
lastReadAt: observation.lastReadAt,
|
|
68
|
+
stale,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Directory coverage — use relative path from project root
|
|
72
|
+
const relative = filePath.startsWith(projectRoot + "/")
|
|
73
|
+
? filePath.slice(projectRoot.length + 1)
|
|
74
|
+
: filePath;
|
|
75
|
+
const lastSlash = relative.lastIndexOf("/");
|
|
76
|
+
const dir = lastSlash === -1 ? "." : relative.slice(0, lastSlash);
|
|
77
|
+
dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Sort files by path for deterministic output
|
|
81
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
82
|
+
staleFiles.sort();
|
|
83
|
+
|
|
84
|
+
const directoryCoverage: Record<string, number> = {};
|
|
85
|
+
for (const [dir, count] of [...dirCounts.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
86
|
+
directoryCoverage[dir] = count;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
totalFiles: files.length,
|
|
91
|
+
totalSymbols,
|
|
92
|
+
files,
|
|
93
|
+
staleFiles,
|
|
94
|
+
directoryCoverage,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -62,9 +62,9 @@ export class Observation {
|
|
|
62
62
|
return this.contentHash !== currentContentHash;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
touch(): void {
|
|
65
|
+
touch(now: string): void {
|
|
66
66
|
this._readCount++;
|
|
67
|
-
this._lastReadAt =
|
|
67
|
+
this._lastReadAt = now;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
snapshot(): ObservationSnapshot {
|
|
@@ -90,11 +90,17 @@ export type CacheResult =
|
|
|
90
90
|
|
|
91
91
|
export class ObservationCache {
|
|
92
92
|
private readonly entries = new Map<string, Observation>();
|
|
93
|
+
readonly now: () => string;
|
|
94
|
+
|
|
95
|
+
constructor(now?: () => string) {
|
|
96
|
+
this.now = now ?? (() => new Date().toISOString());
|
|
97
|
+
}
|
|
93
98
|
|
|
94
99
|
static fromSnapshots(
|
|
95
100
|
snapshots: Readonly<Record<string, ObservationSnapshot>> | undefined,
|
|
101
|
+
now?: () => string,
|
|
96
102
|
): ObservationCache {
|
|
97
|
-
const cache = new ObservationCache();
|
|
103
|
+
const cache = new ObservationCache(now);
|
|
98
104
|
if (snapshots === undefined) {
|
|
99
105
|
return cache;
|
|
100
106
|
}
|
|
@@ -112,7 +118,7 @@ export class ObservationCache {
|
|
|
112
118
|
actual: Readonly<{ lines: number; bytes: number }>,
|
|
113
119
|
): void {
|
|
114
120
|
const existing = this.entries.get(filePath);
|
|
115
|
-
const now =
|
|
121
|
+
const now = this.now();
|
|
116
122
|
this.entries.set(filePath, new Observation({
|
|
117
123
|
contentHash,
|
|
118
124
|
outline,
|
|
@@ -146,4 +152,14 @@ export class ObservationCache {
|
|
|
146
152
|
}
|
|
147
153
|
this.entries.set(filePath, Observation.fromSnapshot(snapshot));
|
|
148
154
|
}
|
|
155
|
+
|
|
156
|
+
/** Iterate all observed file paths and their observations. */
|
|
157
|
+
allEntries(): IterableIterator<[string, Observation]> {
|
|
158
|
+
return this.entries.entries();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Number of observed files. */
|
|
162
|
+
get size(): number {
|
|
163
|
+
return this.entries.size;
|
|
164
|
+
}
|
|
149
165
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Projection Safety Classes — what can each projection level answer?
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** Question classes ordered by information requirement. */
|
|
6
|
+
export type QuestionClass = "existence" | "structure" | "signature" | "behavior";
|
|
7
|
+
|
|
8
|
+
/** Projection levels ordered by detail. */
|
|
9
|
+
export type ProjectionLevel = "outline" | "signature" | "content";
|
|
10
|
+
|
|
11
|
+
/** Warning when a projection is insufficient for the inferred question. */
|
|
12
|
+
export interface SafetyWarning {
|
|
13
|
+
readonly questionClass: QuestionClass;
|
|
14
|
+
readonly currentProjection: ProjectionLevel;
|
|
15
|
+
readonly requiredProjection: ProjectionLevel;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Metadata about what a projection level can answer. */
|
|
20
|
+
export interface SafetyClassMetadata {
|
|
21
|
+
readonly projection: ProjectionLevel;
|
|
22
|
+
readonly answerable: readonly QuestionClass[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Question class taxonomy
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
/** What each projection level can safely answer. */
|
|
30
|
+
const ANSWERABLE: Readonly<Record<ProjectionLevel, readonly QuestionClass[]>> = {
|
|
31
|
+
outline: ["existence", "structure"],
|
|
32
|
+
signature: ["existence", "structure", "signature"],
|
|
33
|
+
content: ["existence", "structure", "signature", "behavior"],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Minimum projection needed for each question class. */
|
|
37
|
+
const MINIMUM_PROJECTION: Readonly<Record<QuestionClass, ProjectionLevel>> = {
|
|
38
|
+
existence: "outline",
|
|
39
|
+
structure: "outline",
|
|
40
|
+
signature: "signature",
|
|
41
|
+
behavior: "content",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Tool → question class mapping
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
const TOOL_QUESTION_CLASS: Readonly<Record<string, QuestionClass>> = {
|
|
49
|
+
code_find: "existence",
|
|
50
|
+
graft_map: "structure",
|
|
51
|
+
file_outline: "structure",
|
|
52
|
+
code_refs: "existence",
|
|
53
|
+
code_show: "behavior",
|
|
54
|
+
safe_read: "behavior",
|
|
55
|
+
read_range: "behavior",
|
|
56
|
+
graft_diff: "structure",
|
|
57
|
+
graft_review: "structure",
|
|
58
|
+
changed_since: "structure",
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Infer the question class from a tool name.
|
|
63
|
+
* Defaults to "behavior" for unknown tools (conservative).
|
|
64
|
+
*/
|
|
65
|
+
export function getQuestionClass(toolName: string): QuestionClass {
|
|
66
|
+
return TOOL_QUESTION_CLASS[toolName] ?? "behavior";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Safety check
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
/** Projection detail ordering for comparison. */
|
|
74
|
+
const LEVEL_ORDER: Readonly<Record<ProjectionLevel, number>> = {
|
|
75
|
+
outline: 0,
|
|
76
|
+
signature: 1,
|
|
77
|
+
content: 2,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check whether a projection is sufficient for the question implied
|
|
82
|
+
* by a tool call. Returns null if safe, or a warning if insufficient.
|
|
83
|
+
*/
|
|
84
|
+
export function checkProjectionSafety(
|
|
85
|
+
toolName: string,
|
|
86
|
+
currentProjection: ProjectionLevel,
|
|
87
|
+
): SafetyWarning | null {
|
|
88
|
+
const questionClass = getQuestionClass(toolName);
|
|
89
|
+
const required = MINIMUM_PROJECTION[questionClass];
|
|
90
|
+
|
|
91
|
+
if (LEVEL_ORDER[currentProjection] >= LEVEL_ORDER[required]) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
questionClass,
|
|
97
|
+
currentProjection,
|
|
98
|
+
requiredProjection: required,
|
|
99
|
+
message: `${toolName} asks a "${questionClass}" question which requires "${required}" projection, but current projection is "${currentProjection}".`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get metadata about what question classes a projection level can answer.
|
|
105
|
+
*/
|
|
106
|
+
export function getSafetyClassMetadata(projection: ProjectionLevel): SafetyClassMetadata {
|
|
107
|
+
return {
|
|
108
|
+
projection,
|
|
109
|
+
answerable: ANSWERABLE[projection],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -163,7 +163,7 @@ export class RepoWorkspace {
|
|
|
163
163
|
if (snapshot?.supportsOutline === true) {
|
|
164
164
|
const cacheResult = this.cache.check(filePath, snapshot.rawContent);
|
|
165
165
|
if (cacheResult.hit) {
|
|
166
|
-
cacheResult.obs.touch();
|
|
166
|
+
cacheResult.obs.touch(this.cache.now());
|
|
167
167
|
return {
|
|
168
168
|
path: filePath,
|
|
169
169
|
projection: "cache_hit",
|
|
@@ -193,7 +193,7 @@ export class RepoWorkspace {
|
|
|
193
193
|
jumpTable: snapshot.jumpTable,
|
|
194
194
|
actual: snapshot.actual,
|
|
195
195
|
readCount: cacheResult.stale.readCount + 1,
|
|
196
|
-
lastReadAt: updated?.lastReadAt ??
|
|
196
|
+
lastReadAt: updated?.lastReadAt ?? this.cache.now(),
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
199
|
}
|
|
@@ -243,7 +243,7 @@ export class RepoWorkspace {
|
|
|
243
243
|
}
|
|
244
244
|
const cacheResult = this.cache.check(filePath, rawContent);
|
|
245
245
|
if (cacheResult.hit) {
|
|
246
|
-
cacheResult.obs.touch();
|
|
246
|
+
cacheResult.obs.touch(this.cache.now());
|
|
247
247
|
return {
|
|
248
248
|
path: filePath,
|
|
249
249
|
outline: [...cacheResult.obs.outline],
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Semantic Drift Detection — flag interpretation shift during reading
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** A single entry in the reading path. */
|
|
6
|
+
export interface ReadingPathEntry {
|
|
7
|
+
readonly filePath: string;
|
|
8
|
+
readonly timestamp: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Warning about potential interpretation shift. */
|
|
12
|
+
export interface DriftWarning {
|
|
13
|
+
readonly filePath: string;
|
|
14
|
+
readonly firstReadIndex: number;
|
|
15
|
+
readonly reReadIndex: number;
|
|
16
|
+
readonly intervening: readonly string[];
|
|
17
|
+
readonly message: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Detect semantic drift in a reading path.
|
|
22
|
+
*
|
|
23
|
+
* When an agent re-reads a file after reading structurally related
|
|
24
|
+
* files (files with cross-file reference edges), the re-read may
|
|
25
|
+
* yield different understanding because the agent's context has
|
|
26
|
+
* shifted. This is holonomy: translating through a chain of
|
|
27
|
+
* observers and returning does not return to the same understanding.
|
|
28
|
+
*
|
|
29
|
+
* @param readingPath - Ordered sequence of file reads in the session
|
|
30
|
+
* @param relatedFiles - Map of file → related files (from reference edges)
|
|
31
|
+
*/
|
|
32
|
+
export function detectSemanticDrift(
|
|
33
|
+
readingPath: readonly ReadingPathEntry[],
|
|
34
|
+
relatedFiles: ReadonlyMap<string, readonly string[]>,
|
|
35
|
+
): DriftWarning[] {
|
|
36
|
+
const warnings: DriftWarning[] = [];
|
|
37
|
+
const lastReadIndex = new Map<string, number>();
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < readingPath.length; i++) {
|
|
40
|
+
const entry = readingPath[i] ?? { filePath: "", timestamp: "" };
|
|
41
|
+
const prevIndex = lastReadIndex.get(entry.filePath);
|
|
42
|
+
|
|
43
|
+
if (prevIndex !== undefined) {
|
|
44
|
+
// This is a re-read — check if related files were read in between
|
|
45
|
+
const related = relatedFiles.get(entry.filePath) ?? [];
|
|
46
|
+
const intervening: string[] = [];
|
|
47
|
+
|
|
48
|
+
for (let j = prevIndex + 1; j < i; j++) {
|
|
49
|
+
const interveningFile = (readingPath[j] ?? { filePath: "" }).filePath;
|
|
50
|
+
if (related.includes(interveningFile)) {
|
|
51
|
+
intervening.push(interveningFile);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (intervening.length > 0) {
|
|
56
|
+
warnings.push({
|
|
57
|
+
filePath: entry.filePath,
|
|
58
|
+
firstReadIndex: prevIndex,
|
|
59
|
+
reReadIndex: i,
|
|
60
|
+
intervening,
|
|
61
|
+
message: `Re-reading ${entry.filePath} after reading related files (${intervening.join(", ")}) may shift interpretation.`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
lastReadIndex.set(entry.filePath, i);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return warnings;
|
|
70
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Session Filtration — accumulation-aware projection escalation
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** Input for filtration level computation. */
|
|
6
|
+
export interface FiltrationInput {
|
|
7
|
+
readonly observedFiles: number;
|
|
8
|
+
readonly totalFiles: number;
|
|
9
|
+
readonly reReadCount: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Input for escalation decision. */
|
|
13
|
+
export interface EscalationInput {
|
|
14
|
+
readonly filtrationLevel: number;
|
|
15
|
+
readonly previousProjection: "outline" | "content";
|
|
16
|
+
readonly readCount: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Result of escalation check. */
|
|
20
|
+
export interface EscalationResult {
|
|
21
|
+
readonly escalate: boolean;
|
|
22
|
+
readonly suggestedProjection: "outline" | "content";
|
|
23
|
+
readonly reason?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const ESCALATION_THRESHOLD = 0.5;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compute the filtration level for the current session.
|
|
30
|
+
*
|
|
31
|
+
* Ranges from 0 (fresh session) to 1 (fully saturated). Based on
|
|
32
|
+
* the fraction of files observed and the number of re-reads.
|
|
33
|
+
* As filtration grows, graft escalates detail — an agent that has
|
|
34
|
+
* already explored the codebase should get richer projections.
|
|
35
|
+
*/
|
|
36
|
+
export function computeFiltrationLevel(input: FiltrationInput): number {
|
|
37
|
+
const { observedFiles, totalFiles, reReadCount } = input;
|
|
38
|
+
if (totalFiles === 0) return 0;
|
|
39
|
+
|
|
40
|
+
const coverageFraction = observedFiles / totalFiles;
|
|
41
|
+
const reReadBoost = Math.min(reReadCount / 20, 0.3);
|
|
42
|
+
|
|
43
|
+
return Math.min(coverageFraction + reReadBoost, 1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Determine whether to escalate projection detail for a re-read.
|
|
48
|
+
*
|
|
49
|
+
* Monotone accumulation: as filtration grows, graft escalates.
|
|
50
|
+
* An agent that outlined a directory and is now re-reading a file
|
|
51
|
+
* in that directory should get content instead of another outline.
|
|
52
|
+
*/
|
|
53
|
+
export function shouldEscalateDetail(input: EscalationInput): EscalationResult {
|
|
54
|
+
const { filtrationLevel, previousProjection, readCount } = input;
|
|
55
|
+
|
|
56
|
+
// Never escalate on first read
|
|
57
|
+
if (readCount <= 1) {
|
|
58
|
+
return { escalate: false, suggestedProjection: previousProjection };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Already at content — nothing to escalate to
|
|
62
|
+
if (previousProjection === "content") {
|
|
63
|
+
return { escalate: false, suggestedProjection: "content" };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Escalate when filtration is high enough and this is a re-read
|
|
67
|
+
if (filtrationLevel >= ESCALATION_THRESHOLD) {
|
|
68
|
+
return {
|
|
69
|
+
escalate: true,
|
|
70
|
+
suggestedProjection: "content",
|
|
71
|
+
reason: `Filtration level ${String(Math.round(filtrationLevel * 100))}% — escalating from outline to content for re-read.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { escalate: false, suggestedProjection: previousProjection };
|
|
76
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Structural Session Replay — render a session as a structural walkthrough
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** A single tool call extracted from NDJSON receipts. */
|
|
6
|
+
export interface ReplayEntry {
|
|
7
|
+
readonly tool: string;
|
|
8
|
+
readonly path?: string;
|
|
9
|
+
readonly symbol?: string;
|
|
10
|
+
readonly ts: string;
|
|
11
|
+
readonly sessionId: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Parse NDJSON receipt lines into replay entries for a given session.
|
|
16
|
+
*/
|
|
17
|
+
export function parseReceiptsForReplay(ndjson: string, sessionId: string): ReplayEntry[] {
|
|
18
|
+
const entries: ReplayEntry[] = [];
|
|
19
|
+
|
|
20
|
+
for (const line of ndjson.split("\n")) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (trimmed.length === 0) continue;
|
|
23
|
+
|
|
24
|
+
let parsed: Record<string, unknown>;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(trimmed) as Record<string, unknown>;
|
|
27
|
+
} catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (parsed["sessionId"] !== sessionId) continue;
|
|
32
|
+
if (typeof parsed["tool"] !== "string") continue;
|
|
33
|
+
|
|
34
|
+
entries.push({
|
|
35
|
+
tool: parsed["tool"],
|
|
36
|
+
...(typeof parsed["path"] === "string" ? { path: parsed["path"] } : {}),
|
|
37
|
+
...(typeof parsed["symbol"] === "string" ? { symbol: parsed["symbol"] } : {}),
|
|
38
|
+
ts: typeof parsed["ts"] === "string" ? parsed["ts"] : "",
|
|
39
|
+
sessionId,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return entries;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Render replay entries as a Markdown summary.
|
|
48
|
+
*/
|
|
49
|
+
export function renderReplayMarkdown(entries: readonly ReplayEntry[]): string {
|
|
50
|
+
if (entries.length === 0) {
|
|
51
|
+
return "# Session Replay\n\nNo activity recorded for this session.\n";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const lines: string[] = [
|
|
55
|
+
"# Session Replay",
|
|
56
|
+
"",
|
|
57
|
+
`**${String(entries.length)} tool calls**`,
|
|
58
|
+
"",
|
|
59
|
+
"| # | Tool | Target | Time |",
|
|
60
|
+
"|---|------|--------|------|",
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < entries.length; i++) {
|
|
64
|
+
const e = entries[i] ?? { tool: "", ts: "", sessionId: "" };
|
|
65
|
+
const target = e.symbol !== undefined
|
|
66
|
+
? `${e.path ?? ""}:${e.symbol}`
|
|
67
|
+
: (e.path ?? "—");
|
|
68
|
+
lines.push(`| ${String(i + 1)} | ${e.tool} | ${target} | ${e.ts} |`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
lines.push("");
|
|
72
|
+
return lines.join("\n");
|
|
73
|
+
}
|