@unerr-ai/unerr 0.2.1 → 0.2.3
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 +36 -45
- package/dist/cli.js +37443 -36022
- package/package.json +2 -1
- package/dist/behaviors/agent-llm-bridge.js +0 -166
- package/dist/behaviors/architecture-guard.js +0 -256
- package/dist/behaviors/auto-doc.js +0 -247
- package/dist/behaviors/cascade-guard.js +0 -289
- package/dist/behaviors/change-narrative.js +0 -270
- package/dist/behaviors/convention-drift.js +0 -290
- package/dist/behaviors/framework.js +0 -235
- package/dist/behaviors/guard-formatter.js +0 -44
- package/dist/behaviors/incomplete-work.js +0 -270
- package/dist/behaviors/loop-breaker.js +0 -300
- package/dist/behaviors/session-continuity.js +0 -208
- package/dist/commands/branches.js +0 -97
- package/dist/commands/check-commit.js +0 -225
- package/dist/commands/compress-output.js +0 -64
- package/dist/commands/config-verify.js +0 -243
- package/dist/commands/daemon.js +0 -905
- package/dist/commands/dashboard.js +0 -52
- package/dist/commands/debug.js +0 -200
- package/dist/commands/enrich.js +0 -184
- package/dist/commands/exec.js +0 -233
- package/dist/commands/gain.js +0 -156
- package/dist/commands/hook.js +0 -88
- package/dist/commands/index.js +0 -88
- package/dist/commands/init.js +0 -74
- package/dist/commands/install.js +0 -505
- package/dist/commands/learn.js +0 -116
- package/dist/commands/manifest.js +0 -193
- package/dist/commands/rewind.js +0 -103
- package/dist/commands/serve.js +0 -19
- package/dist/commands/setup-wizard.js +0 -414
- package/dist/commands/skills.js +0 -64
- package/dist/commands/stats.js +0 -20
- package/dist/commands/status.js +0 -654
- package/dist/commands/timeline.js +0 -139
- package/dist/commands/uninstall.js +0 -230
- package/dist/components/App.js +0 -109
- package/dist/components/Banner.js +0 -12
- package/dist/components/ConfirmPrompt.js +0 -25
- package/dist/components/DriftSummary.js +0 -23
- package/dist/components/GradeBadge.js +0 -15
- package/dist/components/HealthCard.js +0 -18
- package/dist/components/InkSpinner.js +0 -22
- package/dist/components/InputBox.js +0 -17
- package/dist/components/KeyValue.js +0 -13
- package/dist/components/MessageList.js +0 -14
- package/dist/components/ProgressBar.js +0 -26
- package/dist/components/Section.js +0 -16
- package/dist/components/SessionSummaryCard.js +0 -73
- package/dist/components/StartupDisplay.js +0 -24
- package/dist/components/StatusDashboard.js +0 -57
- package/dist/components/StatusLine.js +0 -8
- package/dist/components/StepLine.js +0 -22
- package/dist/components/Theme.js +0 -20
- package/dist/components/ToolProgress.js +0 -8
- package/dist/components/ViolationList.js +0 -21
- package/dist/components/render.js +0 -13
- package/dist/config/agent-registry.js +0 -237
- package/dist/config/claude-settings-hooks.js +0 -304
- package/dist/config/hook-installer.js +0 -65
- package/dist/config/instruction-writer.js +0 -388
- package/dist/config/mcp-config-writer.js +0 -266
- package/dist/config/settings.js +0 -174
- package/dist/config/tool-detector.js +0 -42
- package/dist/config/value-surfacing.js +0 -119
- package/dist/core/context-assembly.js +0 -108
- package/dist/core/conversation.js +0 -33
- package/dist/core/local-chat-provider.js +0 -475
- package/dist/core/provider-factory.js +0 -55
- package/dist/core/providers.js +0 -90
- package/dist/core/query-engine.js +0 -174
- package/dist/daemon/api.js +0 -312
- package/dist/daemon/autostart.js +0 -119
- package/dist/daemon/bootstrap.js +0 -39
- package/dist/daemon/client.js +0 -164
- package/dist/daemon/detect-ci.js +0 -81
- package/dist/daemon/platform-linux.js +0 -146
- package/dist/daemon/platform-macos.js +0 -134
- package/dist/daemon/platform-windows.js +0 -116
- package/dist/daemon/process-manager.js +0 -299
- package/dist/daemon/protocol.js +0 -23
- package/dist/daemon/registry.js +0 -270
- package/dist/daemon/settings-schema.js +0 -72
- package/dist/daemon/system-health.js +0 -134
- package/dist/daemon/version-checker.js +0 -262
- package/dist/daemon/warm-start.js +0 -223
- package/dist/entrypoints/cli.js +0 -1043
- package/dist/entrypoints/daemon.js +0 -380
- package/dist/entrypoints/repl.js +0 -147
- package/dist/hooks/adapters/claude-code.js +0 -90
- package/dist/hooks/adapters/cline.js +0 -100
- package/dist/hooks/adapters/cursor.js +0 -98
- package/dist/hooks/hook-dedup.js +0 -79
- package/dist/hooks/hook-runner.js +0 -113
- package/dist/hooks/navigation-hooks.js +0 -175
- package/dist/hooks/prompt-hooks.js +0 -63
- package/dist/hooks/shell-hooks.js +0 -47
- package/dist/ignore.js +0 -111
- package/dist/intelligence/approach-suggester.js +0 -61
- package/dist/intelligence/ast-extractor.js +0 -2615
- package/dist/intelligence/ast-worker.js +0 -34
- package/dist/intelligence/background-indexer.js +0 -121
- package/dist/intelligence/blast-radius.js +0 -200
- package/dist/intelligence/community-detection.js +0 -691
- package/dist/intelligence/community-detector.js +0 -184
- package/dist/intelligence/computation-scheduler.js +0 -75
- package/dist/intelligence/confidence-propagation.js +0 -47
- package/dist/intelligence/convention-detector.js +0 -242
- package/dist/intelligence/convention-learner.js +0 -205
- package/dist/intelligence/convention-matcher.js +0 -205
- package/dist/intelligence/cozo-schema.js +0 -376
- package/dist/intelligence/decision-point-detector.js +0 -90
- package/dist/intelligence/deep-dive-tools.js +0 -586
- package/dist/intelligence/durability-scorer.js +0 -84
- package/dist/intelligence/exploration-cost.js +0 -204
- package/dist/intelligence/exploration-pattern-tracker.js +0 -61
- package/dist/intelligence/fact-generator.js +0 -322
- package/dist/intelligence/facts-schema.js +0 -90
- package/dist/intelligence/file-intelligence.js +0 -59
- package/dist/intelligence/graph-holder.js +0 -220
- package/dist/intelligence/graph-temporal-joiner.js +0 -238
- package/dist/intelligence/health-grade.js +0 -423
- package/dist/intelligence/health-grader.js +0 -200
- package/dist/intelligence/health-map-data.js +0 -259
- package/dist/intelligence/import-symbols.js +0 -136
- package/dist/intelligence/incremental-indexer.js +0 -658
- package/dist/intelligence/indexer/centrality.js +0 -62
- package/dist/intelligence/indexer/cfg-context.js +0 -95
- package/dist/intelligence/indexer/confidence.js +0 -34
- package/dist/intelligence/indexer/cross-file-resolver.js +0 -104
- package/dist/intelligence/indexer/edge-repair.js +0 -89
- package/dist/intelligence/indexer/entity-key.js +0 -17
- package/dist/intelligence/indexer/export-map.js +0 -132
- package/dist/intelligence/indexer/git-cochange.js +0 -128
- package/dist/intelligence/indexer/graph-patch.js +0 -147
- package/dist/intelligence/indexer/incremental.js +0 -78
- package/dist/intelligence/indexer/ingest.js +0 -160
- package/dist/intelligence/indexer/language-detect.js +0 -226
- package/dist/intelligence/indexer/metadata.js +0 -63
- package/dist/intelligence/indexer/mutation-tracker.js +0 -79
- package/dist/intelligence/indexer/orchestrator.js +0 -155
- package/dist/intelligence/indexer/plugin-interface.js +0 -31
- package/dist/intelligence/indexer/plugins/csharp.js +0 -440
- package/dist/intelligence/indexer/plugins/go.js +0 -335
- package/dist/intelligence/indexer/plugins/java.js +0 -370
- package/dist/intelligence/indexer/plugins/python.js +0 -358
- package/dist/intelligence/indexer/plugins/regex-fallback.js +0 -82
- package/dist/intelligence/indexer/plugins/ruby.js +0 -290
- package/dist/intelligence/indexer/plugins/rust.js +0 -484
- package/dist/intelligence/indexer/plugins/tier2-generic.js +0 -310
- package/dist/intelligence/indexer/plugins/typescript.js +0 -456
- package/dist/intelligence/indexer/resource-monitor.js +0 -93
- package/dist/intelligence/indexer/scip/decoder.js +0 -253
- package/dist/intelligence/indexer/scip/detector.js +0 -232
- package/dist/intelligence/indexer/scip/downloader.js +0 -427
- package/dist/intelligence/indexer/scip/fallback.js +0 -34
- package/dist/intelligence/indexer/scip/merger.js +0 -109
- package/dist/intelligence/indexer/scip/orchestrator.js +0 -433
- package/dist/intelligence/indexer/scip/runner.js +0 -98
- package/dist/intelligence/indexer/snapshot.js +0 -66
- package/dist/intelligence/indexer/test-detector.js +0 -196
- package/dist/intelligence/indexer/watch-integration.js +0 -61
- package/dist/intelligence/indexer/worker.js +0 -85
- package/dist/intelligence/local-convention-detector.js +0 -437
- package/dist/intelligence/local-embeddings.js +0 -190
- package/dist/intelligence/local-graph.js +0 -1946
- package/dist/intelligence/local-indexer.js +0 -1575
- package/dist/intelligence/local-llm.js +0 -163
- package/dist/intelligence/local-rule-generator.js +0 -154
- package/dist/intelligence/local-snapshot.js +0 -213
- package/dist/intelligence/negative-knowledge.js +0 -103
- package/dist/intelligence/persistent-db.js +0 -85
- package/dist/intelligence/query-router.js +0 -2556
- package/dist/intelligence/risk-classifier.js +0 -116
- package/dist/intelligence/rule-evaluator.js +0 -380
- package/dist/intelligence/rule-generator.js +0 -49
- package/dist/intelligence/search-index.js +0 -173
- package/dist/intelligence/semantic/docstring-extractor.js +0 -67
- package/dist/intelligence/semantic/embedding-store.js +0 -52
- package/dist/intelligence/semantic/enrichment-orchestrator.js +0 -48
- package/dist/intelligence/semantic/git-message-miner.js +0 -114
- package/dist/intelligence/semantic/identifier-tokenizer.js +0 -51
- package/dist/intelligence/semantic/node2vec-embeddings.js +0 -71
- package/dist/intelligence/semantic/node2vec-walks.js +0 -103
- package/dist/intelligence/semantic/path-domain-inference.js +0 -112
- package/dist/intelligence/semantic/similarity-engine.js +0 -60
- package/dist/intelligence/semantic/tfidf-vectors.js +0 -88
- package/dist/intelligence/session-brief-builder.js +0 -159
- package/dist/intelligence/session-context.js +0 -221
- package/dist/intelligence/session-health-monitor.js +0 -211
- package/dist/intelligence/session-narrative.js +0 -197
- package/dist/intelligence/session-pattern-analyzer.js +0 -218
- package/dist/intelligence/signal-scorer.js +0 -390
- package/dist/intelligence/signal-show-store.js +0 -182
- package/dist/intelligence/smart-truncate.js +0 -158
- package/dist/intelligence/subgraph-cache.js +0 -88
- package/dist/intelligence/temporal-facts.js +0 -494
- package/dist/intelligence/token-estimator.js +0 -100
- package/dist/intelligence/tool-injector.js +0 -87
- package/dist/intelligence/tree-sitter-loader.js +0 -71
- package/dist/intelligence/worker-pool.js +0 -116
- package/dist/proxy/arg-validator.js +0 -79
- package/dist/proxy/auto-bootstrap.js +0 -167
- package/dist/proxy/bridge.js +0 -147
- package/dist/proxy/budget-enforcer.js +0 -70
- package/dist/proxy/compression-quality-monitor.js +0 -160
- package/dist/proxy/compression-stats.js +0 -51
- package/dist/proxy/context-rot-detector.js +0 -137
- package/dist/proxy/drift-detector.js +0 -139
- package/dist/proxy/efficiency-tracker.js +0 -79
- package/dist/proxy/fact-ranking.js +0 -154
- package/dist/proxy/format-encoder.js +0 -266
- package/dist/proxy/http-transport.js +0 -90
- package/dist/proxy/lifecycle-actor.js +0 -55
- package/dist/proxy/lifecycle-machine.js +0 -187
- package/dist/proxy/log-tailer.js +0 -265
- package/dist/proxy/model-pricing.js +0 -98
- package/dist/proxy/network-firewall.js +0 -141
- package/dist/proxy/nudge-state.js +0 -93
- package/dist/proxy/output-compressor.js +0 -185
- package/dist/proxy/pid-lock.js +0 -291
- package/dist/proxy/proxy-context.js +0 -11
- package/dist/proxy/proxy.js +0 -2633
- package/dist/proxy/response-enrichment.js +0 -32
- package/dist/proxy/response-envelope.js +0 -313
- package/dist/proxy/session-dedup.js +0 -82
- package/dist/proxy/session-legend.js +0 -30
- package/dist/proxy/session-persistence.js +0 -210
- package/dist/proxy/session-resume.js +0 -94
- package/dist/proxy/session-stats.js +0 -513
- package/dist/proxy/shell-classifier.js +0 -1346
- package/dist/proxy/shell-compression-log.js +0 -93
- package/dist/proxy/shell-compressor.js +0 -390
- package/dist/proxy/shell-graph-boost.js +0 -202
- package/dist/proxy/shell-monitor-map.js +0 -18
- package/dist/proxy/shell-stats.js +0 -54
- package/dist/proxy/shell-strategies/cloud.js +0 -215
- package/dist/proxy/shell-strategies/diff.js +0 -159
- package/dist/proxy/shell-strategies/error-diagnostic.js +0 -796
- package/dist/proxy/shell-strategies/filter-dsl.js +0 -358
- package/dist/proxy/shell-strategies/git-status.js +0 -177
- package/dist/proxy/shell-strategies/key-value.js +0 -193
- package/dist/proxy/shell-strategies/log-text.js +0 -154
- package/dist/proxy/shell-strategies/omni.js +0 -188
- package/dist/proxy/shell-strategies/progress.js +0 -55
- package/dist/proxy/shell-strategies/redact.js +0 -76
- package/dist/proxy/shell-strategies/structured.js +0 -241
- package/dist/proxy/shell-strategies/tabular.js +0 -243
- package/dist/proxy/shell-strategies/test-results-types.js +0 -13
- package/dist/proxy/shell-strategies/test-results.js +0 -784
- package/dist/proxy/shell-strategies/tree-paths.js +0 -144
- package/dist/proxy/shell-strategies/yaml.js +0 -182
- package/dist/proxy/shell-tee.js +0 -111
- package/dist/proxy/signal-dedup.js +0 -171
- package/dist/proxy/startup-renderer.js +0 -158
- package/dist/proxy/task-token-display.js +0 -38
- package/dist/proxy/token-counter.js +0 -61
- package/dist/proxy/tool-clusters.js +0 -273
- package/dist/proxy/tool-definitions.js +0 -525
- package/dist/proxy/transport-mux.js +0 -229
- package/dist/proxy/wire-cap.js +0 -268
- package/dist/rules/developer.mozilla.org.json +0 -9
- package/dist/rules/github.com.json +0 -21
- package/dist/schemas/api/skills.js +0 -19
- package/dist/schemas/common/errors.js +0 -7
- package/dist/schemas/common/headers.js +0 -5
- package/dist/schemas/entities/edge.js +0 -25
- package/dist/schemas/entities/entity.js +0 -22
- package/dist/schemas/entities/rule.js +0 -18
- package/dist/schemas/index.js +0 -14
- package/dist/server/event-bus.js +0 -59
- package/dist/server/http.js +0 -156
- package/dist/server/middleware.js +0 -70
- package/dist/server/routes/drift.js +0 -97
- package/dist/server/routes/intelligence.js +0 -1217
- package/dist/server/routes/reasoning-quality.js +0 -444
- package/dist/server/routes/session.js +0 -86
- package/dist/server/routes/stream.js +0 -120
- package/dist/server/routes/system.js +0 -73
- package/dist/server/routes/temporal.js +0 -170
- package/dist/server/routes/timeline.js +0 -232
- package/dist/server/routes/token-flow.js +0 -403
- package/dist/skills/effectiveness-tracker.js +0 -93
- package/dist/skills/local-pack.js +0 -380
- package/dist/skills/resolver.js +0 -495
- package/dist/state-detector.js +0 -83
- package/dist/timeline/intent-detector.js +0 -263
- package/dist/timeline/loop-miner.js +0 -140
- package/dist/timeline/open-threads.js +0 -49
- package/dist/timeline/signal-reinforcer.js +0 -62
- package/dist/timeline/timeline-bootstrap.js +0 -151
- package/dist/timeline/timeline-store.js +0 -618
- package/dist/tools/coding/bash.js +0 -49
- package/dist/tools/coding/file-edit.js +0 -72
- package/dist/tools/coding/file-outline.js +0 -227
- package/dist/tools/coding/file-read-protocol.js +0 -425
- package/dist/tools/coding/file-read.js +0 -35
- package/dist/tools/coding/file-write.js +0 -43
- package/dist/tools/coding/glob-tool.js +0 -109
- package/dist/tools/coding/grep.js +0 -162
- package/dist/tools/coding/index.js +0 -27
- package/dist/tools/intelligence/index.js +0 -269
- package/dist/tools/intelligence/record-fact.js +0 -48
- package/dist/tools/intelligence/timeline-markers.js +0 -130
- package/dist/tools/registry.js +0 -47
- package/dist/tools/types.js +0 -8
- package/dist/tracking/auto-snapshot-triggers.js +0 -246
- package/dist/tracking/branch-context.js +0 -115
- package/dist/tracking/branch-snapshot.js +0 -217
- package/dist/tracking/causal-bridge.js +0 -317
- package/dist/tracking/circuit-breaker.js +0 -147
- package/dist/tracking/commit-watcher.js +0 -114
- package/dist/tracking/context-ledger.js +0 -119
- package/dist/tracking/correction-detector.js +0 -324
- package/dist/tracking/drift-tracker.js +0 -874
- package/dist/tracking/durability-tracker.js +0 -94
- package/dist/tracking/entity-rewind.js +0 -200
- package/dist/tracking/file-hash-state.js +0 -114
- package/dist/tracking/git-attribution.js +0 -132
- package/dist/tracking/git-trailers.js +0 -171
- package/dist/tracking/intelligence-counter.js +0 -46
- package/dist/tracking/intent-correlator.js +0 -202
- package/dist/tracking/intent-encoder.js +0 -52
- package/dist/tracking/intent-token-tracker.js +0 -159
- package/dist/tracking/ledger-archiver.js +0 -94
- package/dist/tracking/ledger-chains.js +0 -245
- package/dist/tracking/metrics-store.js +0 -361
- package/dist/tracking/native-watcher.js +0 -131
- package/dist/tracking/offline-rewind.js +0 -295
- package/dist/tracking/pending-violations.js +0 -74
- package/dist/tracking/persistence-effectiveness.js +0 -167
- package/dist/tracking/prompt-durability.js +0 -202
- package/dist/tracking/quality-signals.js +0 -213
- package/dist/tracking/redactor.js +0 -73
- package/dist/tracking/rewind-engine.js +0 -161
- package/dist/tracking/session-history.js +0 -128
- package/dist/tracking/session-receipt.js +0 -88
- package/dist/tracking/session-summary-writer.js +0 -157
- package/dist/tracking/shadow-ledger.js +0 -321
- package/dist/tracking/stash-manager.js +0 -258
- package/dist/tracking/timeline-fork.js +0 -213
- package/dist/tracking/timeline.js +0 -69
- package/dist/tracking/token-flow.js +0 -276
- package/dist/tracking/turn-segmenter.js +0 -122
- package/dist/tracking/weekly-accumulator.js +0 -179
- package/dist/tracking/working-snapshots.js +0 -188
- package/dist/tracking/workspace-manifest.js +0 -176
- package/dist/transport/http.js +0 -102
- package/dist/utils/counterfactual.js +0 -65
- package/dist/utils/deep-link.js +0 -34
- package/dist/utils/detect.js +0 -193
- package/dist/utils/exec.js +0 -73
- package/dist/utils/file-logger.js +0 -87
- package/dist/utils/format-error.js +0 -29
- package/dist/utils/git.js +0 -181
- package/dist/utils/log.js +0 -57
- package/dist/utils/logger.js +0 -35
- package/dist/utils/mcp-content-json.js +0 -8
- package/dist/utils/session-logger.js +0 -154
- package/dist/utils/startup-log.js +0 -512
- package/dist/utils/ui.js +0 -56
|
@@ -1,586 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sprint 11: Phase 22 Blueprint Deep Dive MCP Tool Handlers.
|
|
3
|
-
*
|
|
4
|
-
* 8 tools for coding agents to consume approved architecture plans:
|
|
5
|
-
*
|
|
6
|
-
* Navigation (post-approval):
|
|
7
|
-
* - unerr_get_plan_context: Full architecture plan overview
|
|
8
|
-
* - unerr_get_next_slice: Next implementation-ready slice
|
|
9
|
-
* - unerr_check_boundary: Validate imports against boundary rules
|
|
10
|
-
* - unerr_get_design_system: Design tokens for UI implementation
|
|
11
|
-
*
|
|
12
|
-
* Implementation (post-impl-plan):
|
|
13
|
-
* - unerr_get_next_task: Highest-priority task with deps satisfied
|
|
14
|
-
* - unerr_complete_task: Mark task complete + run checks
|
|
15
|
-
* - unerr_get_sprint_context: Sprint details + agent context files
|
|
16
|
-
* - unerr_get_checkpoint_status: Checkpoint verification status
|
|
17
|
-
*
|
|
18
|
-
* All queries run against CozoDB local graph (<5ms).
|
|
19
|
-
*/
|
|
20
|
-
import { stringifyMcpToolJson } from "../utils/mcp-content-json.js";
|
|
21
|
-
// ── Tool Schemas ────────────────────────────────────────────────────
|
|
22
|
-
export const DEEP_DIVE_TOOL_DEFINITIONS = [
|
|
23
|
-
{
|
|
24
|
-
name: "unerr_get_plan_context",
|
|
25
|
-
description: "Return the complete architecture plan for the active Blueprint project including all vertical slices, dependencies, stack recommendation, and domain/stage context. Use this to understand the full system before implementing individual slices.",
|
|
26
|
-
inputSchema: {
|
|
27
|
-
type: "object",
|
|
28
|
-
properties: {
|
|
29
|
-
projectId: {
|
|
30
|
-
type: "string",
|
|
31
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: "unerr_get_next_slice",
|
|
38
|
-
description: "Return the next implementation-ready vertical slice with full architectural context. A slice is ready when all its dependency slices have status 'complete'. Includes data model, API surface, conventions, boundary rules, and design tokens.",
|
|
39
|
-
inputSchema: {
|
|
40
|
-
type: "object",
|
|
41
|
-
properties: {
|
|
42
|
-
projectId: {
|
|
43
|
-
type: "string",
|
|
44
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: "unerr_check_boundary",
|
|
51
|
-
description: "Validate whether proposed code changes respect the slice boundaries defined in the architecture plan. Returns violations if the change imports from forbidden modules or violates conventions.",
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: "object",
|
|
54
|
-
properties: {
|
|
55
|
-
projectId: {
|
|
56
|
-
type: "string",
|
|
57
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
58
|
-
},
|
|
59
|
-
sliceId: {
|
|
60
|
-
type: "string",
|
|
61
|
-
description: "The slice being implemented",
|
|
62
|
-
},
|
|
63
|
-
proposedImports: {
|
|
64
|
-
type: "array",
|
|
65
|
-
items: { type: "string" },
|
|
66
|
-
description: "Module paths the code proposes to import",
|
|
67
|
-
},
|
|
68
|
-
proposedFiles: {
|
|
69
|
-
type: "array",
|
|
70
|
-
items: { type: "string" },
|
|
71
|
-
description: "File paths the code proposes to create or modify",
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
required: ["sliceId"],
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: "unerr_get_design_system",
|
|
79
|
-
description: "Return the full design token set for the active Blueprint project. Includes color palette, typography, spacing, and component patterns. Use these tokens when implementing UI components.",
|
|
80
|
-
inputSchema: {
|
|
81
|
-
type: "object",
|
|
82
|
-
properties: {
|
|
83
|
-
projectId: {
|
|
84
|
-
type: "string",
|
|
85
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: "unerr_get_next_task",
|
|
92
|
-
description: "Return the highest-priority implementation task with all dependencies satisfied. Includes slice context, acceptance criteria, and boundary rules.",
|
|
93
|
-
inputSchema: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
projectId: {
|
|
97
|
-
type: "string",
|
|
98
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
99
|
-
},
|
|
100
|
-
sprintNumber: {
|
|
101
|
-
type: "number",
|
|
102
|
-
description: "Filter to a specific sprint (optional)",
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: "unerr_complete_task",
|
|
109
|
-
description: "Mark a task as complete and run verification checks against boundary rules and conventions. Returns pass/fail with specific feedback.",
|
|
110
|
-
inputSchema: {
|
|
111
|
-
type: "object",
|
|
112
|
-
properties: {
|
|
113
|
-
projectId: {
|
|
114
|
-
type: "string",
|
|
115
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
116
|
-
},
|
|
117
|
-
taskId: {
|
|
118
|
-
type: "string",
|
|
119
|
-
description: "Task ID to mark complete",
|
|
120
|
-
},
|
|
121
|
-
completedFiles: {
|
|
122
|
-
type: "array",
|
|
123
|
-
items: { type: "string" },
|
|
124
|
-
description: "Files that were created/modified for this task",
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
required: ["taskId"],
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
name: "unerr_get_sprint_context",
|
|
132
|
-
description: "Return full sprint context with auto-generated agent context files. Includes a CLAUDE.md snippet encoding boundaries, conventions, acceptance criteria, and design tokens.",
|
|
133
|
-
inputSchema: {
|
|
134
|
-
type: "object",
|
|
135
|
-
properties: {
|
|
136
|
-
projectId: {
|
|
137
|
-
type: "string",
|
|
138
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
139
|
-
},
|
|
140
|
-
sprintNumber: {
|
|
141
|
-
type: "number",
|
|
142
|
-
description: "Sprint number to get context for",
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
required: ["sprintNumber"],
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
name: "unerr_get_checkpoint_status",
|
|
150
|
-
description: "Return the checkpoint verification status for a sprint — which tasks are complete and which are pending.",
|
|
151
|
-
inputSchema: {
|
|
152
|
-
type: "object",
|
|
153
|
-
properties: {
|
|
154
|
-
projectId: {
|
|
155
|
-
type: "string",
|
|
156
|
-
description: "Blueprint project ID. If omitted, uses the active project.",
|
|
157
|
-
},
|
|
158
|
-
sprintNumber: {
|
|
159
|
-
type: "number",
|
|
160
|
-
description: "Sprint number to check",
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
required: ["sprintNumber"],
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
];
|
|
167
|
-
/** All 8 deep dive tool names. */
|
|
168
|
-
export const DEEP_DIVE_TOOL_NAMES = DEEP_DIVE_TOOL_DEFINITIONS.map((t) => t.name);
|
|
169
|
-
/** Navigation-phase tools (available post-approval). */
|
|
170
|
-
export const NAVIGATION_TOOL_NAMES = [
|
|
171
|
-
"unerr_get_plan_context",
|
|
172
|
-
"unerr_get_next_slice",
|
|
173
|
-
"unerr_check_boundary",
|
|
174
|
-
"unerr_get_design_system",
|
|
175
|
-
];
|
|
176
|
-
/** Implementation-phase tools (available when building). */
|
|
177
|
-
export const IMPLEMENTATION_TOOL_NAMES = [
|
|
178
|
-
"unerr_get_next_task",
|
|
179
|
-
"unerr_complete_task",
|
|
180
|
-
"unerr_get_sprint_context",
|
|
181
|
-
"unerr_get_checkpoint_status",
|
|
182
|
-
];
|
|
183
|
-
function formatResult(data) {
|
|
184
|
-
return {
|
|
185
|
-
content: [{ type: "text", text: stringifyMcpToolJson(data) }],
|
|
186
|
-
_meta: { source: "local", latency_ms: 0, format: "json" },
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
function formatError(message) {
|
|
190
|
-
return formatResult({ error: message });
|
|
191
|
-
}
|
|
192
|
-
async function resolveProject(graph, projectId) {
|
|
193
|
-
if (projectId)
|
|
194
|
-
return await graph.getDeepDiveProject(projectId);
|
|
195
|
-
return await graph.getActiveDeepDiveProject();
|
|
196
|
-
}
|
|
197
|
-
// ── Navigation Tools ────────────────────────────────────────────────
|
|
198
|
-
export async function handleGetPlanContext(graph, args) {
|
|
199
|
-
const project = await resolveProject(graph, args.projectId);
|
|
200
|
-
if (!project)
|
|
201
|
-
return formatError("No Blueprint project found.");
|
|
202
|
-
const slices = await graph.getDeepDiveSlices(project.key);
|
|
203
|
-
const sliceTree = slices.map((s) => ({
|
|
204
|
-
id: s.key,
|
|
205
|
-
name: s.name,
|
|
206
|
-
description: s.description,
|
|
207
|
-
repoTargetId: s.repoTargetId,
|
|
208
|
-
parentSliceKey: s.parentSliceKey,
|
|
209
|
-
dependencies: s.dependencies,
|
|
210
|
-
status: s.status,
|
|
211
|
-
order: s.order,
|
|
212
|
-
sliceType: s.sliceType,
|
|
213
|
-
}));
|
|
214
|
-
return formatResult({
|
|
215
|
-
project: {
|
|
216
|
-
id: project.key,
|
|
217
|
-
name: project.name,
|
|
218
|
-
description: project.description,
|
|
219
|
-
status: project.status,
|
|
220
|
-
domain: project.domain,
|
|
221
|
-
stage: project.stage,
|
|
222
|
-
stackRecommendation: project.stackRecommendation,
|
|
223
|
-
designSystem: project.designSystem,
|
|
224
|
-
healthBaseline: project.healthBaseline,
|
|
225
|
-
},
|
|
226
|
-
sliceTree,
|
|
227
|
-
totalSlices: slices.length,
|
|
228
|
-
completedSlices: slices.filter((s) => s.status === "complete").length,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
export async function handleGetNextSlice(graph, args) {
|
|
232
|
-
const project = await resolveProject(graph, args.projectId);
|
|
233
|
-
if (!project)
|
|
234
|
-
return formatError("No Blueprint project found.");
|
|
235
|
-
if (project.status !== "approved" && project.status !== "building") {
|
|
236
|
-
return formatError(`unerr_get_next_slice requires an approved project. Current status: "${project.status}".`);
|
|
237
|
-
}
|
|
238
|
-
const slices = await graph.getDeepDiveSlices(project.key);
|
|
239
|
-
const completedKeys = new Set(slices.filter((s) => s.status === "complete").map((s) => s.key));
|
|
240
|
-
const nextSlice = slices.find((s) => {
|
|
241
|
-
if (s.status !== "planned")
|
|
242
|
-
return false;
|
|
243
|
-
return s.dependencies.every((dep) => completedKeys.has(dep));
|
|
244
|
-
});
|
|
245
|
-
if (!nextSlice) {
|
|
246
|
-
return formatResult({
|
|
247
|
-
message: "All slices are complete or no ready slice found.",
|
|
248
|
-
nextSlice: null,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
return formatResult({
|
|
252
|
-
slice: {
|
|
253
|
-
id: nextSlice.key,
|
|
254
|
-
name: nextSlice.name,
|
|
255
|
-
description: nextSlice.description,
|
|
256
|
-
repoTargetId: nextSlice.repoTargetId,
|
|
257
|
-
dependencies: nextSlice.dependencies,
|
|
258
|
-
dataModel: nextSlice.dataModel,
|
|
259
|
-
apiSurface: nextSlice.apiSurface,
|
|
260
|
-
conventions: nextSlice.conventions,
|
|
261
|
-
boundaryRules: nextSlice.boundaryRules,
|
|
262
|
-
userFlows: nextSlice.userFlows,
|
|
263
|
-
uiDesign: nextSlice.uiDesign,
|
|
264
|
-
status: nextSlice.status,
|
|
265
|
-
},
|
|
266
|
-
designSystem: project.designSystem ?? null,
|
|
267
|
-
domain: project.domain,
|
|
268
|
-
stage: project.stage,
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
export async function handleCheckBoundary(graph, args) {
|
|
272
|
-
const project = await resolveProject(graph, args.projectId);
|
|
273
|
-
if (!project)
|
|
274
|
-
return formatError("No Blueprint project found.");
|
|
275
|
-
const slice = await graph.getDeepDiveSlice(args.sliceId);
|
|
276
|
-
if (!slice)
|
|
277
|
-
return formatError("Slice not found.");
|
|
278
|
-
const violations = [];
|
|
279
|
-
const imports = args.proposedImports ?? [];
|
|
280
|
-
const files = args.proposedFiles ?? [];
|
|
281
|
-
for (const rule of slice.boundaryRules) {
|
|
282
|
-
const ruleLower = rule.description.toLowerCase();
|
|
283
|
-
for (const imp of imports) {
|
|
284
|
-
if (ruleViolatesImport(ruleLower, imp.toLowerCase())) {
|
|
285
|
-
violations.push({
|
|
286
|
-
rule: rule.description,
|
|
287
|
-
description: `Import "${imp}" may violate boundary: ${rule.description}`,
|
|
288
|
-
severity: rule.enforcement === "block" ? "error" : "warning",
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
for (const conv of slice.conventions) {
|
|
294
|
-
for (const file of files) {
|
|
295
|
-
if (conv.enforcement === "block" && conv.pattern) {
|
|
296
|
-
try {
|
|
297
|
-
const re = new RegExp(conv.pattern, "i");
|
|
298
|
-
if (!re.test(file)) {
|
|
299
|
-
violations.push({
|
|
300
|
-
rule: conv.name,
|
|
301
|
-
description: `File "${file}" may violate convention: ${conv.name} (${conv.pattern})`,
|
|
302
|
-
severity: "warning",
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
catch {
|
|
307
|
-
// Invalid regex pattern — skip
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return formatResult({
|
|
313
|
-
valid: violations.length === 0,
|
|
314
|
-
violations,
|
|
315
|
-
boundaryRulesChecked: slice.boundaryRules.length,
|
|
316
|
-
conventionsChecked: slice.conventions.length,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
function ruleViolatesImport(ruleLower, importLower) {
|
|
320
|
-
const forbiddenPatterns = [
|
|
321
|
-
/cannot import from (\w+)/,
|
|
322
|
-
/must not import (\w+)/,
|
|
323
|
-
/no imports? from (\w+)/,
|
|
324
|
-
/forbidden.* (\w+)/,
|
|
325
|
-
];
|
|
326
|
-
for (const pattern of forbiddenPatterns) {
|
|
327
|
-
const match = ruleLower.match(pattern);
|
|
328
|
-
if (match?.[1] && importLower.includes(match[1]))
|
|
329
|
-
return true;
|
|
330
|
-
}
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
export async function handleGetDesignSystem(graph, args) {
|
|
334
|
-
const project = await resolveProject(graph, args.projectId);
|
|
335
|
-
if (!project)
|
|
336
|
-
return formatError("No Blueprint project found.");
|
|
337
|
-
const designSystem = await graph.getDeepDiveDesignSystem(project.key);
|
|
338
|
-
if (!designSystem) {
|
|
339
|
-
return formatResult({
|
|
340
|
-
designSystem: null,
|
|
341
|
-
message: "No design system generated for this project. This may indicate the project has no UI-bearing slices.",
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
return formatResult({ designSystem });
|
|
345
|
-
}
|
|
346
|
-
// ── Implementation Tools ────────────────────────────────────────────
|
|
347
|
-
export async function handleGetNextTask(graph, args) {
|
|
348
|
-
const project = await resolveProject(graph, args.projectId);
|
|
349
|
-
if (!project)
|
|
350
|
-
return formatError("No Blueprint project found.");
|
|
351
|
-
const tasks = await graph.getDeepDiveTasks(project.key, args.sprintNumber);
|
|
352
|
-
if (tasks.length === 0) {
|
|
353
|
-
return formatError("No tasks found. Generate an implementation plan first.");
|
|
354
|
-
}
|
|
355
|
-
const completedIds = new Set(tasks.filter((t) => t.status === "complete").map((t) => t.key));
|
|
356
|
-
const nextTask = tasks.find((t) => {
|
|
357
|
-
if (t.status === "complete")
|
|
358
|
-
return false;
|
|
359
|
-
return t.dependencies.every((dep) => completedIds.has(dep));
|
|
360
|
-
});
|
|
361
|
-
if (!nextTask) {
|
|
362
|
-
return formatResult({
|
|
363
|
-
task: null,
|
|
364
|
-
message: "All tasks are complete or no task has all dependencies satisfied.",
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
const sprintTasks = tasks.filter((t) => t.sprintNumber === nextTask.sprintNumber);
|
|
368
|
-
const sprintCompleted = sprintTasks.filter((t) => t.status === "complete").length;
|
|
369
|
-
return formatResult({
|
|
370
|
-
task: {
|
|
371
|
-
id: nextTask.key,
|
|
372
|
-
sliceName: nextTask.sliceName,
|
|
373
|
-
description: nextTask.description,
|
|
374
|
-
status: nextTask.status,
|
|
375
|
-
estimatedEffort: nextTask.estimatedEffort,
|
|
376
|
-
dependencies: nextTask.dependencies,
|
|
377
|
-
boundaryRules: nextTask.boundaryRules,
|
|
378
|
-
conventions: nextTask.conventions,
|
|
379
|
-
},
|
|
380
|
-
acceptanceCriteria: nextTask.acceptanceCriteria,
|
|
381
|
-
sprintNumber: nextTask.sprintNumber,
|
|
382
|
-
sprintTotalTasks: sprintTasks.length,
|
|
383
|
-
sprintCompletedTasks: sprintCompleted,
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
export async function handleCompleteTask(graph, args) {
|
|
387
|
-
const project = await resolveProject(graph, args.projectId);
|
|
388
|
-
if (!project)
|
|
389
|
-
return formatError("No Blueprint project found.");
|
|
390
|
-
const tasks = await graph.getDeepDiveTasks(project.key);
|
|
391
|
-
const task = tasks.find((t) => t.key === args.taskId);
|
|
392
|
-
if (!task) {
|
|
393
|
-
return formatError(`Task "${args.taskId}" not found in the implementation plan.`);
|
|
394
|
-
}
|
|
395
|
-
const checks = [];
|
|
396
|
-
if (task.boundaryRules.length > 0) {
|
|
397
|
-
checks.push({
|
|
398
|
-
name: "boundary_rules",
|
|
399
|
-
passed: true,
|
|
400
|
-
feedback: `${task.boundaryRules.length} boundary rule(s) defined. Manual verification recommended.`,
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
if (task.conventions.length > 0) {
|
|
404
|
-
checks.push({
|
|
405
|
-
name: "conventions",
|
|
406
|
-
passed: true,
|
|
407
|
-
feedback: `${task.conventions.length} convention(s) defined. Manual verification recommended.`,
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
if (args.completedFiles && args.completedFiles.length > 0) {
|
|
411
|
-
checks.push({
|
|
412
|
-
name: "files_created",
|
|
413
|
-
passed: true,
|
|
414
|
-
feedback: `${args.completedFiles.length} file(s) reported as created/modified.`,
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
await graph.completeDeepDiveTask(args.taskId, args.completedFiles);
|
|
418
|
-
const allPassed = checks.every((c) => c.passed);
|
|
419
|
-
return formatResult({
|
|
420
|
-
passed: allPassed,
|
|
421
|
-
checks,
|
|
422
|
-
taskId: args.taskId,
|
|
423
|
-
message: allPassed
|
|
424
|
-
? "Task marked complete. All checks passed."
|
|
425
|
-
: "Task marked complete with warnings.",
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
export async function handleGetSprintContext(graph, args) {
|
|
429
|
-
const project = await resolveProject(graph, args.projectId);
|
|
430
|
-
if (!project)
|
|
431
|
-
return formatError("No Blueprint project found.");
|
|
432
|
-
const tasks = await graph.getDeepDiveTasks(project.key, args.sprintNumber);
|
|
433
|
-
if (tasks.length === 0) {
|
|
434
|
-
return formatError(`Sprint ${args.sprintNumber} not found or has no tasks.`);
|
|
435
|
-
}
|
|
436
|
-
const claudeMd = generateClaudeMd(tasks, project);
|
|
437
|
-
const cursorRules = generateCursorRules(tasks, args.sprintNumber);
|
|
438
|
-
const checkpoint = tasks.length > 0
|
|
439
|
-
? tasks[0].checkpoint
|
|
440
|
-
: {};
|
|
441
|
-
return formatResult({
|
|
442
|
-
sprint: {
|
|
443
|
-
sprintNumber: args.sprintNumber,
|
|
444
|
-
tasks: tasks.map((t) => ({
|
|
445
|
-
id: t.key,
|
|
446
|
-
sliceName: t.sliceName,
|
|
447
|
-
description: t.description,
|
|
448
|
-
status: t.status,
|
|
449
|
-
estimatedEffort: t.estimatedEffort,
|
|
450
|
-
})),
|
|
451
|
-
checkpoint,
|
|
452
|
-
},
|
|
453
|
-
acceptanceCriteria: Object.fromEntries(tasks.map((t) => [t.key, t.acceptanceCriteria])),
|
|
454
|
-
agentContext: {
|
|
455
|
-
claudeMd,
|
|
456
|
-
cursorRules,
|
|
457
|
-
genericMarkdown: claudeMd,
|
|
458
|
-
},
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
export async function handleGetCheckpointStatus(graph, args) {
|
|
462
|
-
const project = await resolveProject(graph, args.projectId);
|
|
463
|
-
if (!project)
|
|
464
|
-
return formatError("No Blueprint project found.");
|
|
465
|
-
const tasks = await graph.getDeepDiveTasks(project.key, args.sprintNumber);
|
|
466
|
-
if (tasks.length === 0) {
|
|
467
|
-
return formatError(`Sprint ${args.sprintNumber} not found.`);
|
|
468
|
-
}
|
|
469
|
-
const totalTasks = tasks.length;
|
|
470
|
-
const completedTasks = tasks.filter((t) => t.status === "complete").length;
|
|
471
|
-
const checkpoint = tasks.length > 0
|
|
472
|
-
? tasks[0].checkpoint
|
|
473
|
-
: {};
|
|
474
|
-
return formatResult({
|
|
475
|
-
sprintNumber: args.sprintNumber,
|
|
476
|
-
tasksCompleted: completedTasks,
|
|
477
|
-
tasksTotal: totalTasks,
|
|
478
|
-
allTasksComplete: completedTasks === totalTasks,
|
|
479
|
-
checkpoint: checkpoint ?? { verificationItems: [] },
|
|
480
|
-
message: completedTasks === totalTasks
|
|
481
|
-
? "All tasks complete. Ready for checkpoint verification."
|
|
482
|
-
: `${totalTasks - completedTasks} task(s) remaining before checkpoint.`,
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
// ── Agent Context Generators ────────────────────────────────────────
|
|
486
|
-
function generateClaudeMd(tasks, project) {
|
|
487
|
-
const lines = [
|
|
488
|
-
`# Blueprint Sprint Context — ${project.name}`,
|
|
489
|
-
"",
|
|
490
|
-
`> Domain: ${project.domain?.primary ?? "unknown"}`,
|
|
491
|
-
`> Stage: ${project.stage?.current ?? "unknown"}`,
|
|
492
|
-
"",
|
|
493
|
-
"## Boundary Rules (STRICT — violations will be flagged)",
|
|
494
|
-
"",
|
|
495
|
-
];
|
|
496
|
-
const allBoundaryRules = new Set();
|
|
497
|
-
const allConventions = new Set();
|
|
498
|
-
for (const task of tasks) {
|
|
499
|
-
for (const r of task.boundaryRules)
|
|
500
|
-
allBoundaryRules.add(r.description);
|
|
501
|
-
for (const c of task.conventions)
|
|
502
|
-
allConventions.add(`${c.name}: ${c.pattern}`);
|
|
503
|
-
}
|
|
504
|
-
for (const rule of allBoundaryRules)
|
|
505
|
-
lines.push(`- ${rule}`);
|
|
506
|
-
if (allBoundaryRules.size === 0)
|
|
507
|
-
lines.push("- No boundary rules defined for this sprint.");
|
|
508
|
-
lines.push("", "## Conventions", "");
|
|
509
|
-
for (const conv of allConventions)
|
|
510
|
-
lines.push(`- ${conv}`);
|
|
511
|
-
if (allConventions.size === 0)
|
|
512
|
-
lines.push("- No conventions defined for this sprint.");
|
|
513
|
-
lines.push("", "## Tasks & Acceptance Criteria", "");
|
|
514
|
-
for (const task of tasks) {
|
|
515
|
-
lines.push(`### ${task.sliceName} (${task.key})`);
|
|
516
|
-
lines.push(task.description);
|
|
517
|
-
lines.push("");
|
|
518
|
-
if (task.acceptanceCriteria.length > 0) {
|
|
519
|
-
lines.push("**Acceptance Criteria:**");
|
|
520
|
-
for (const c of task.acceptanceCriteria) {
|
|
521
|
-
const criterion = c?.criterion ?? c;
|
|
522
|
-
lines.push(`- [ ] ${String(criterion)}`);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
lines.push("");
|
|
526
|
-
}
|
|
527
|
-
if (project.designSystem) {
|
|
528
|
-
lines.push("## Design Tokens", "");
|
|
529
|
-
lines.push("```json");
|
|
530
|
-
lines.push(JSON.stringify(project.designSystem).slice(0, 2000));
|
|
531
|
-
lines.push("```");
|
|
532
|
-
}
|
|
533
|
-
return lines.join("\n");
|
|
534
|
-
}
|
|
535
|
-
function generateCursorRules(tasks, sprintNumber) {
|
|
536
|
-
const lines = [
|
|
537
|
-
"---",
|
|
538
|
-
`description: Blueprint Sprint ${sprintNumber} rules`,
|
|
539
|
-
"globs:",
|
|
540
|
-
];
|
|
541
|
-
const allPaths = new Set();
|
|
542
|
-
for (const task of tasks) {
|
|
543
|
-
const sliceName = (task.sliceName ?? "").toLowerCase().replace(/\s+/g, "-");
|
|
544
|
-
if (sliceName) {
|
|
545
|
-
allPaths.add(`src/**/${sliceName}/**`);
|
|
546
|
-
allPaths.add(`app/**/${sliceName}/**`);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
for (const path of allPaths)
|
|
550
|
-
lines.push(` - "${path}"`);
|
|
551
|
-
lines.push("alwaysApply: false", "---", "");
|
|
552
|
-
const allRules = new Set();
|
|
553
|
-
for (const task of tasks) {
|
|
554
|
-
for (const r of task.boundaryRules)
|
|
555
|
-
allRules.add(r.description);
|
|
556
|
-
}
|
|
557
|
-
lines.push("# Boundary Rules");
|
|
558
|
-
for (const rule of allRules)
|
|
559
|
-
lines.push(`- ${rule}`);
|
|
560
|
-
return lines.join("\n");
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* Dispatch a deep dive tool call. Returns null if the tool name is not a deep dive tool.
|
|
564
|
-
*/
|
|
565
|
-
export async function handleDeepDiveTool(name, args, graph) {
|
|
566
|
-
switch (name) {
|
|
567
|
-
case "unerr_get_plan_context":
|
|
568
|
-
return await handleGetPlanContext(graph, args);
|
|
569
|
-
case "unerr_get_next_slice":
|
|
570
|
-
return await handleGetNextSlice(graph, args);
|
|
571
|
-
case "unerr_check_boundary":
|
|
572
|
-
return await handleCheckBoundary(graph, args);
|
|
573
|
-
case "unerr_get_design_system":
|
|
574
|
-
return await handleGetDesignSystem(graph, args);
|
|
575
|
-
case "unerr_get_next_task":
|
|
576
|
-
return await handleGetNextTask(graph, args);
|
|
577
|
-
case "unerr_complete_task":
|
|
578
|
-
return await handleCompleteTask(graph, args);
|
|
579
|
-
case "unerr_get_sprint_context":
|
|
580
|
-
return await handleGetSprintContext(graph, args);
|
|
581
|
-
case "unerr_get_checkpoint_status":
|
|
582
|
-
return await handleGetCheckpointStatus(graph, args);
|
|
583
|
-
default:
|
|
584
|
-
return null;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Code Durability Scoring — per-entity survival metric (0.0–1.0).
|
|
3
|
-
*
|
|
4
|
-
* Reads shadow ledger history to compute how long an entity survives
|
|
5
|
-
* between modifications. Higher durability = more stable code.
|
|
6
|
-
*
|
|
7
|
-
* durability = time_survived / total_observation_window
|
|
8
|
-
*
|
|
9
|
-
* Computed on-demand from ledger (not stored permanently). Cached
|
|
10
|
-
* in memory for the session.
|
|
11
|
-
*
|
|
12
|
-
* Temporal intelligence note: durability feeds into the relevance
|
|
13
|
-
* scoring engine (Section 13.3). High-durability entities get
|
|
14
|
-
* structural importance boost; low-durability entities surface
|
|
15
|
-
* as instability warnings.
|
|
16
|
-
*/
|
|
17
|
-
export function createDurabilityScorer() {
|
|
18
|
-
const cache = new Map();
|
|
19
|
-
function computeScores(entries) {
|
|
20
|
-
cache.clear();
|
|
21
|
-
const entityTimeline = new Map();
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
if (entry.tool !== "sync_local_diff")
|
|
24
|
-
continue;
|
|
25
|
-
const files = extractFiles(entry.args_summary);
|
|
26
|
-
const ts = new Date(entry.ts).getTime();
|
|
27
|
-
for (const file of files) {
|
|
28
|
-
const timeline = entityTimeline.get(file) ?? [];
|
|
29
|
-
timeline.push(ts);
|
|
30
|
-
entityTimeline.set(file, timeline);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (entries.length === 0)
|
|
34
|
-
return cache;
|
|
35
|
-
const firstTs = new Date(entries[0].ts).getTime();
|
|
36
|
-
const lastTs = new Date(entries[entries.length - 1].ts).getTime();
|
|
37
|
-
const totalWindow = Math.max(lastTs - firstTs, 1);
|
|
38
|
-
for (const [entityKey, timestamps] of entityTimeline) {
|
|
39
|
-
timestamps.sort((a, b) => a - b);
|
|
40
|
-
const modCount = timestamps.length;
|
|
41
|
-
const lastModified = new Date(timestamps[timestamps.length - 1]).toISOString();
|
|
42
|
-
let totalSurvival = 0;
|
|
43
|
-
for (let i = 1; i < timestamps.length; i++) {
|
|
44
|
-
totalSurvival += timestamps[i] - timestamps[i - 1];
|
|
45
|
-
}
|
|
46
|
-
const timeSinceLastMod = lastTs - timestamps[timestamps.length - 1];
|
|
47
|
-
totalSurvival += timeSinceLastMod;
|
|
48
|
-
const avgSurvival = modCount > 0 ? totalSurvival / modCount : totalWindow;
|
|
49
|
-
const score = Math.min(1.0, avgSurvival / Math.max(totalWindow, 1));
|
|
50
|
-
const durability = {
|
|
51
|
-
entityKey,
|
|
52
|
-
score: Math.round(score * 100) / 100,
|
|
53
|
-
modificationCount: modCount,
|
|
54
|
-
totalObservationMs: totalWindow,
|
|
55
|
-
avgSurvivalMs: Math.round(avgSurvival),
|
|
56
|
-
lastModified,
|
|
57
|
-
};
|
|
58
|
-
cache.set(entityKey, durability);
|
|
59
|
-
}
|
|
60
|
-
return cache;
|
|
61
|
-
}
|
|
62
|
-
function getScore(entityKey) {
|
|
63
|
-
return cache.get(entityKey) ?? null;
|
|
64
|
-
}
|
|
65
|
-
function getTopUnstable(limit = 10) {
|
|
66
|
-
return [...cache.values()]
|
|
67
|
-
.sort((a, b) => a.score - b.score)
|
|
68
|
-
.slice(0, limit);
|
|
69
|
-
}
|
|
70
|
-
function getTopDurable(limit = 10) {
|
|
71
|
-
return [...cache.values()]
|
|
72
|
-
.sort((a, b) => b.score - a.score)
|
|
73
|
-
.slice(0, limit);
|
|
74
|
-
}
|
|
75
|
-
return { computeScores, getScore, getTopUnstable, getTopDurable };
|
|
76
|
-
}
|
|
77
|
-
function extractFiles(args) {
|
|
78
|
-
const files = args.files;
|
|
79
|
-
if (!Array.isArray(files))
|
|
80
|
-
return [];
|
|
81
|
-
return files
|
|
82
|
-
.map((f) => typeof f === "string" ? f : (f?.path ?? ""))
|
|
83
|
-
.filter(Boolean);
|
|
84
|
-
}
|