agent-bober 0.17.0 → 0.18.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +25 -0
- package/README.md +169 -6
- package/dist/chat/answerer.d.ts +17 -0
- package/dist/chat/answerer.d.ts.map +1 -0
- package/dist/chat/answerer.js +52 -0
- package/dist/chat/answerer.js.map +1 -0
- package/dist/chat/approval-cursor.d.ts +25 -0
- package/dist/chat/approval-cursor.d.ts.map +1 -0
- package/dist/chat/approval-cursor.js +61 -0
- package/dist/chat/approval-cursor.js.map +1 -0
- package/dist/chat/approval-reader.d.ts +11 -0
- package/dist/chat/approval-reader.d.ts.map +1 -0
- package/dist/chat/approval-reader.js +20 -0
- package/dist/chat/approval-reader.js.map +1 -0
- package/dist/chat/careful-sidecar.d.ts +15 -0
- package/dist/chat/careful-sidecar.d.ts.map +1 -0
- package/dist/chat/careful-sidecar.js +39 -0
- package/dist/chat/careful-sidecar.js.map +1 -0
- package/dist/chat/chat-session.d.ts +129 -0
- package/dist/chat/chat-session.d.ts.map +1 -0
- package/dist/chat/chat-session.js +470 -0
- package/dist/chat/chat-session.js.map +1 -0
- package/dist/chat/completion-tailer.d.ts +27 -0
- package/dist/chat/completion-tailer.d.ts.map +1 -0
- package/dist/chat/completion-tailer.js +187 -0
- package/dist/chat/completion-tailer.js.map +1 -0
- package/dist/chat/conversation-store.d.ts +22 -0
- package/dist/chat/conversation-store.d.ts.map +1 -0
- package/dist/chat/conversation-store.js +66 -0
- package/dist/chat/conversation-store.js.map +1 -0
- package/dist/chat/cursor-store.d.ts +23 -0
- package/dist/chat/cursor-store.d.ts.map +1 -0
- package/dist/chat/cursor-store.js +42 -0
- package/dist/chat/cursor-store.js.map +1 -0
- package/dist/chat/pid-sidecar.d.ts +22 -0
- package/dist/chat/pid-sidecar.d.ts.map +1 -0
- package/dist/chat/pid-sidecar.js +42 -0
- package/dist/chat/pid-sidecar.js.map +1 -0
- package/dist/chat/roster-reader.d.ts +16 -0
- package/dist/chat/roster-reader.d.ts.map +1 -0
- package/dist/chat/roster-reader.js +39 -0
- package/dist/chat/roster-reader.js.map +1 -0
- package/dist/chat/run-spawner.d.ts +71 -0
- package/dist/chat/run-spawner.d.ts.map +1 -0
- package/dist/chat/run-spawner.js +121 -0
- package/dist/chat/run-spawner.js.map +1 -0
- package/dist/chat/slash-commands.d.ts +36 -0
- package/dist/chat/slash-commands.d.ts.map +1 -0
- package/dist/chat/slash-commands.js +133 -0
- package/dist/chat/slash-commands.js.map +1 -0
- package/dist/chat/steer-cleanup.d.ts +12 -0
- package/dist/chat/steer-cleanup.d.ts.map +1 -0
- package/dist/chat/steer-cleanup.js +60 -0
- package/dist/chat/steer-cleanup.js.map +1 -0
- package/dist/chat/turn-classifier.d.ts +43 -0
- package/dist/chat/turn-classifier.d.ts.map +1 -0
- package/dist/chat/turn-classifier.js +150 -0
- package/dist/chat/turn-classifier.js.map +1 -0
- package/dist/cli/commands/blackboard.d.ts +33 -0
- package/dist/cli/commands/blackboard.d.ts.map +1 -0
- package/dist/cli/commands/blackboard.js +114 -0
- package/dist/cli/commands/blackboard.js.map +1 -0
- package/dist/cli/commands/chat.d.ts +13 -0
- package/dist/cli/commands/chat.d.ts.map +1 -0
- package/dist/cli/commands/chat.js +43 -0
- package/dist/cli/commands/chat.js.map +1 -0
- package/dist/cli/commands/evolve.d.ts +18 -0
- package/dist/cli/commands/evolve.d.ts.map +1 -0
- package/dist/cli/commands/evolve.js +72 -0
- package/dist/cli/commands/evolve.js.map +1 -0
- package/dist/cli/commands/facts.d.ts +15 -0
- package/dist/cli/commands/facts.d.ts.map +1 -0
- package/dist/cli/commands/facts.js +213 -0
- package/dist/cli/commands/facts.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +1 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/medical.d.ts +24 -0
- package/dist/cli/commands/medical.d.ts.map +1 -0
- package/dist/cli/commands/medical.js +132 -0
- package/dist/cli/commands/medical.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +2 -1
- package/dist/cli/commands/memory.d.ts.map +1 -1
- package/dist/cli/commands/memory.js +94 -7
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +29 -3
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/replay.d.ts +17 -0
- package/dist/cli/commands/replay.d.ts.map +1 -0
- package/dist/cli/commands/replay.js +261 -0
- package/dist/cli/commands/replay.js.map +1 -0
- package/dist/cli/commands/run.d.ts +9 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +27 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +17 -3
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/commands/update.d.ts +18 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +81 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +15 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +8 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/role-providers.d.ts +1 -1
- package/dist/config/role-providers.d.ts.map +1 -1
- package/dist/config/role-providers.js +6 -1
- package/dist/config/role-providers.js.map +1 -1
- package/dist/config/schema.d.ts +467 -222
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +25 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/contracts/eval-result.d.ts +84 -84
- package/dist/contracts/spec.d.ts +28 -28
- package/dist/contracts/sprint-contract.d.ts +4 -4
- package/dist/fleet/critic-deep.d.ts +53 -0
- package/dist/fleet/critic-deep.d.ts.map +1 -0
- package/dist/fleet/critic-deep.js +199 -0
- package/dist/fleet/critic-deep.js.map +1 -0
- package/dist/fleet/decomposer-deep-constants.d.ts +4 -0
- package/dist/fleet/decomposer-deep-constants.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-constants.js +14 -0
- package/dist/fleet/decomposer-deep-constants.js.map +1 -0
- package/dist/fleet/decomposer-deep-types.d.ts +8 -0
- package/dist/fleet/decomposer-deep-types.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep-types.js +9 -0
- package/dist/fleet/decomposer-deep-types.js.map +1 -0
- package/dist/fleet/decomposer-deep.d.ts +51 -0
- package/dist/fleet/decomposer-deep.d.ts.map +1 -0
- package/dist/fleet/decomposer-deep.js +261 -0
- package/dist/fleet/decomposer-deep.js.map +1 -0
- package/dist/fleet/decomposer.d.ts +22 -0
- package/dist/fleet/decomposer.d.ts.map +1 -0
- package/dist/fleet/decomposer.js +144 -0
- package/dist/fleet/decomposer.js.map +1 -0
- package/dist/fleet/index.d.ts +93 -0
- package/dist/fleet/index.d.ts.map +1 -1
- package/dist/fleet/index.js +230 -2
- package/dist/fleet/index.js.map +1 -1
- package/dist/fleet/manifest-write.d.ts +30 -0
- package/dist/fleet/manifest-write.d.ts.map +1 -0
- package/dist/fleet/manifest-write.js +90 -0
- package/dist/fleet/manifest-write.js.map +1 -0
- package/dist/fleet/manifest.d.ts +6 -6
- package/dist/fleet/shared-blackboard.d.ts +51 -0
- package/dist/fleet/shared-blackboard.d.ts.map +1 -0
- package/dist/fleet/shared-blackboard.js +79 -0
- package/dist/fleet/shared-blackboard.js.map +1 -0
- package/dist/fleet/synthesis.d.ts +16 -0
- package/dist/fleet/synthesis.d.ts.map +1 -0
- package/dist/fleet/synthesis.js +22 -0
- package/dist/fleet/synthesis.js.map +1 -0
- package/dist/fleet/tier-policy.d.ts +18 -0
- package/dist/fleet/tier-policy.d.ts.map +1 -0
- package/dist/fleet/tier-policy.js +53 -0
- package/dist/fleet/tier-policy.js.map +1 -0
- package/dist/fleet/tool-role-guard.d.ts +24 -0
- package/dist/fleet/tool-role-guard.d.ts.map +1 -0
- package/dist/fleet/tool-role-guard.js +55 -0
- package/dist/fleet/tool-role-guard.js.map +1 -0
- package/dist/incident/resolution-verify.d.ts +4 -4
- package/dist/incident/types.d.ts +8 -8
- package/dist/mcp/run-manager.d.ts +9 -1
- package/dist/mcp/run-manager.d.ts.map +1 -1
- package/dist/mcp/run-manager.js.map +1 -1
- package/dist/medical/adapters/apple-health.d.ts +32 -0
- package/dist/medical/adapters/apple-health.d.ts.map +1 -0
- package/dist/medical/adapters/apple-health.js +100 -0
- package/dist/medical/adapters/apple-health.js.map +1 -0
- package/dist/medical/audit.d.ts +31 -0
- package/dist/medical/audit.d.ts.map +1 -0
- package/dist/medical/audit.js +56 -0
- package/dist/medical/audit.js.map +1 -0
- package/dist/medical/consent.d.ts +37 -0
- package/dist/medical/consent.d.ts.map +1 -0
- package/dist/medical/consent.js +73 -0
- package/dist/medical/consent.js.map +1 -0
- package/dist/medical/disclaimer.d.ts +11 -0
- package/dist/medical/disclaimer.d.ts.map +1 -0
- package/dist/medical/disclaimer.js +21 -0
- package/dist/medical/disclaimer.js.map +1 -0
- package/dist/medical/egress.d.ts +30 -0
- package/dist/medical/egress.d.ts.map +1 -0
- package/dist/medical/egress.js +50 -0
- package/dist/medical/egress.js.map +1 -0
- package/dist/medical/engine.d.ts +73 -0
- package/dist/medical/engine.d.ts.map +1 -0
- package/dist/medical/engine.js +333 -0
- package/dist/medical/engine.js.map +1 -0
- package/dist/medical/guardrails.d.ts +47 -0
- package/dist/medical/guardrails.d.ts.map +1 -0
- package/dist/medical/guardrails.js +92 -0
- package/dist/medical/guardrails.js.map +1 -0
- package/dist/medical/health-store.d.ts +80 -0
- package/dist/medical/health-store.d.ts.map +1 -0
- package/dist/medical/health-store.js +204 -0
- package/dist/medical/health-store.js.map +1 -0
- package/dist/medical/inference.d.ts +22 -0
- package/dist/medical/inference.d.ts.map +1 -0
- package/dist/medical/inference.js +39 -0
- package/dist/medical/inference.js.map +1 -0
- package/dist/medical/ingestion.d.ts +33 -0
- package/dist/medical/ingestion.d.ts.map +1 -0
- package/dist/medical/ingestion.js +52 -0
- package/dist/medical/ingestion.js.map +1 -0
- package/dist/medical/numerics.d.ts +66 -0
- package/dist/medical/numerics.d.ts.map +1 -0
- package/dist/medical/numerics.js +216 -0
- package/dist/medical/numerics.js.map +1 -0
- package/dist/medical/red-flag.d.ts +42 -0
- package/dist/medical/red-flag.d.ts.map +1 -0
- package/dist/medical/red-flag.js +161 -0
- package/dist/medical/red-flag.js.map +1 -0
- package/dist/medical/refusal.d.ts +46 -0
- package/dist/medical/refusal.d.ts.map +1 -0
- package/dist/medical/refusal.js +131 -0
- package/dist/medical/refusal.js.map +1 -0
- package/dist/medical/retrieval/grounding-critic.d.ts +34 -0
- package/dist/medical/retrieval/grounding-critic.d.ts.map +1 -0
- package/dist/medical/retrieval/grounding-critic.js +153 -0
- package/dist/medical/retrieval/grounding-critic.js.map +1 -0
- package/dist/medical/retrieval/literature.d.ts +78 -0
- package/dist/medical/retrieval/literature.d.ts.map +1 -0
- package/dist/medical/retrieval/literature.js +292 -0
- package/dist/medical/retrieval/literature.js.map +1 -0
- package/dist/medical/retrieval/medline-source.d.ts +72 -0
- package/dist/medical/retrieval/medline-source.d.ts.map +1 -0
- package/dist/medical/retrieval/medline-source.js +120 -0
- package/dist/medical/retrieval/medline-source.js.map +1 -0
- package/dist/medical/team.d.ts +15 -0
- package/dist/medical/team.d.ts.map +1 -0
- package/dist/medical/team.js +44 -0
- package/dist/medical/team.js.map +1 -0
- package/dist/medical/types.d.ts +175 -0
- package/dist/medical/types.d.ts.map +1 -0
- package/dist/medical/types.js +8 -0
- package/dist/medical/types.js.map +1 -0
- package/dist/medical/whoop/whoop-client.d.ts +114 -0
- package/dist/medical/whoop/whoop-client.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-client.js +226 -0
- package/dist/medical/whoop/whoop-client.js.map +1 -0
- package/dist/medical/whoop/whoop-sync.d.ts +25 -0
- package/dist/medical/whoop/whoop-sync.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-sync.js +97 -0
- package/dist/medical/whoop/whoop-sync.js.map +1 -0
- package/dist/medical/whoop/whoop-token.d.ts +44 -0
- package/dist/medical/whoop/whoop-token.d.ts.map +1 -0
- package/dist/medical/whoop/whoop-token.js +66 -0
- package/dist/medical/whoop/whoop-token.js.map +1 -0
- package/dist/orchestrator/context-handoff.d.ts +60 -60
- package/dist/orchestrator/contract-materialization.d.ts +33 -0
- package/dist/orchestrator/contract-materialization.d.ts.map +1 -0
- package/dist/orchestrator/contract-materialization.js +113 -0
- package/dist/orchestrator/contract-materialization.js.map +1 -0
- package/dist/orchestrator/memory/distill.d.ts +4 -1
- package/dist/orchestrator/memory/distill.d.ts.map +1 -1
- package/dist/orchestrator/memory/distill.js +41 -1
- package/dist/orchestrator/memory/distill.js.map +1 -1
- package/dist/orchestrator/memory/fact-detector.d.ts +61 -0
- package/dist/orchestrator/memory/fact-detector.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-detector.js +153 -0
- package/dist/orchestrator/memory/fact-detector.js.map +1 -0
- package/dist/orchestrator/memory/fact-judge.d.ts +19 -0
- package/dist/orchestrator/memory/fact-judge.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-judge.js +121 -0
- package/dist/orchestrator/memory/fact-judge.js.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts +52 -0
- package/dist/orchestrator/memory/fact-retrieve.d.ts.map +1 -0
- package/dist/orchestrator/memory/fact-retrieve.js +117 -0
- package/dist/orchestrator/memory/fact-retrieve.js.map +1 -0
- package/dist/orchestrator/memory/hygiene.d.ts +66 -0
- package/dist/orchestrator/memory/hygiene.d.ts.map +1 -0
- package/dist/orchestrator/memory/hygiene.js +153 -0
- package/dist/orchestrator/memory/hygiene.js.map +1 -0
- package/dist/orchestrator/memory/reconcile.d.ts +47 -0
- package/dist/orchestrator/memory/reconcile.d.ts.map +1 -0
- package/dist/orchestrator/memory/reconcile.js +116 -0
- package/dist/orchestrator/memory/reconcile.js.map +1 -0
- package/dist/orchestrator/memory/retrieve.d.ts +5 -3
- package/dist/orchestrator/memory/retrieve.d.ts.map +1 -1
- package/dist/orchestrator/memory/retrieve.js +9 -6
- package/dist/orchestrator/memory/retrieve.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +19 -3
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +63 -52
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +16 -1
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/orchestrator/selfimprove/eval-guards.d.ts +51 -0
- package/dist/orchestrator/selfimprove/eval-guards.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/eval-guards.js +120 -0
- package/dist/orchestrator/selfimprove/eval-guards.js.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts +74 -0
- package/dist/orchestrator/selfimprove/gepa.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/gepa.js +227 -0
- package/dist/orchestrator/selfimprove/gepa.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts +65 -0
- package/dist/orchestrator/selfimprove/replay-harness.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-harness.js +134 -0
- package/dist/orchestrator/selfimprove/replay-harness.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts +45 -0
- package/dist/orchestrator/selfimprove/replay-store.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-store.js +119 -0
- package/dist/orchestrator/selfimprove/replay-store.js.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts +32 -0
- package/dist/orchestrator/selfimprove/replay-types.d.ts.map +1 -0
- package/dist/orchestrator/selfimprove/replay-types.js +15 -0
- package/dist/orchestrator/selfimprove/replay-types.js.map +1 -0
- package/dist/orchestrator/workflow/engine.d.ts +3 -1
- package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.d.ts +18 -0
- package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.js +41 -0
- package/dist/orchestrator/workflow/selector.js.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/ts-engine.js +2 -2
- package/dist/orchestrator/workflow/ts-engine.js.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts +3 -1
- package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/workflow-engine.js +3 -3
- package/dist/orchestrator/workflow/workflow-engine.js.map +1 -1
- package/dist/state/facts.d.ts +110 -0
- package/dist/state/facts.d.ts.map +1 -0
- package/dist/state/facts.js +208 -0
- package/dist/state/facts.js.map +1 -0
- package/dist/state/guidance.d.ts +37 -0
- package/dist/state/guidance.d.ts.map +1 -0
- package/dist/state/guidance.js +144 -0
- package/dist/state/guidance.js.map +1 -0
- package/dist/state/history.d.ts +2 -2
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +1 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/memory.d.ts +43 -11
- package/dist/state/memory.d.ts.map +1 -1
- package/dist/state/memory.js +93 -15
- package/dist/state/memory.js.map +1 -1
- package/dist/state/pause.d.ts +47 -0
- package/dist/state/pause.d.ts.map +1 -0
- package/dist/state/pause.js +146 -0
- package/dist/state/pause.js.map +1 -0
- package/dist/state/sprint-state.d.ts +8 -0
- package/dist/state/sprint-state.d.ts.map +1 -1
- package/dist/state/sprint-state.js +32 -1
- package/dist/state/sprint-state.js.map +1 -1
- package/dist/teams/registry.d.ts +16 -0
- package/dist/teams/registry.d.ts.map +1 -0
- package/dist/teams/registry.js +53 -0
- package/dist/teams/registry.js.map +1 -0
- package/dist/teams/types.d.ts +25 -0
- package/dist/teams/types.d.ts.map +1 -0
- package/dist/teams/types.js +2 -0
- package/dist/teams/types.js.map +1 -0
- package/package.json +3 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* lessonId is a sha256 content-hash of category+tags+sourceEntryRefs — never derived from time.
|
|
7
7
|
*
|
|
8
8
|
* IMPORTANT — this distills from the data shapes the REAL pipeline actually produces, NOT
|
|
9
|
-
* an invented vocabulary. The
|
|
9
|
+
* an invented vocabulary. The four signals are:
|
|
10
10
|
* (a) recurring failed-criterion categories — from eval results' criteriaResults[].result==="fail",
|
|
11
11
|
* grouped by the criterion's verificationMethod (resolved from the owning contract).
|
|
12
12
|
* (b) repeated failing eval strategies — from eval results' strategyResults[].result==="fail",
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* (c) sprints that needed rework — from contract.iterationHistory entries whose
|
|
15
15
|
* result==="fail" (real shape: { iteration, evalId, result }), reinforced by history
|
|
16
16
|
* entries with phase==="rework" && event==="evaluation-failed".
|
|
17
|
+
* (d) fail→pass contrast — from contract.iterationHistory where at least one
|
|
18
|
+
* result==="fail" is FOLLOWED (in iteration order) by a result==="pass", capturing the
|
|
19
|
+
* sprint provenance and which iterations flipped.
|
|
17
20
|
*
|
|
18
21
|
* The eval-result inputs are read LENIENTLY (see DistillableEval) because the on-disk
|
|
19
22
|
* .bober/eval-results/*.json files and the compiled EvalResultSchema use different shapes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/memory/distill.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/memory/distill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAezD;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC,CAAC;IACH,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AA2CD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,cAAc,EAAE,EAC3B,WAAW,GAAE,eAAe,EAAO,GAClC,WAAW,EAAE,CAoKf"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* lessonId is a sha256 content-hash of category+tags+sourceEntryRefs — never derived from time.
|
|
7
7
|
*
|
|
8
8
|
* IMPORTANT — this distills from the data shapes the REAL pipeline actually produces, NOT
|
|
9
|
-
* an invented vocabulary. The
|
|
9
|
+
* an invented vocabulary. The four signals are:
|
|
10
10
|
* (a) recurring failed-criterion categories — from eval results' criteriaResults[].result==="fail",
|
|
11
11
|
* grouped by the criterion's verificationMethod (resolved from the owning contract).
|
|
12
12
|
* (b) repeated failing eval strategies — from eval results' strategyResults[].result==="fail",
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* (c) sprints that needed rework — from contract.iterationHistory entries whose
|
|
15
15
|
* result==="fail" (real shape: { iteration, evalId, result }), reinforced by history
|
|
16
16
|
* entries with phase==="rework" && event==="evaluation-failed".
|
|
17
|
+
* (d) fail→pass contrast — from contract.iterationHistory where at least one
|
|
18
|
+
* result==="fail" is FOLLOWED (in iteration order) by a result==="pass", capturing the
|
|
19
|
+
* sprint provenance and which iterations flipped.
|
|
17
20
|
*
|
|
18
21
|
* The eval-result inputs are read LENIENTLY (see DistillableEval) because the on-disk
|
|
19
22
|
* .bober/eval-results/*.json files and the compiled EvalResultSchema use different shapes;
|
|
@@ -134,6 +137,43 @@ export function distill(history, contracts, evalResults = []) {
|
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
}
|
|
140
|
+
// ── (d) fail→pass contrast (per contract iterationHistory) ─────────────
|
|
141
|
+
// Detects sprints that initially failed but eventually passed, capturing the
|
|
142
|
+
// transition as a 'fix-contrast' lesson. A transition requires at least one
|
|
143
|
+
// result==='fail' FOLLOWED (in array/iteration order) by a result==='pass'.
|
|
144
|
+
// A first-iteration pass, an all-fail history, or a pass-before-any-fail are NOT transitions.
|
|
145
|
+
for (const contract of contracts) {
|
|
146
|
+
const iters = Array.isArray(contract.iterationHistory)
|
|
147
|
+
? contract.iterationHistory
|
|
148
|
+
: [];
|
|
149
|
+
let sawFail = false;
|
|
150
|
+
let flipped = false;
|
|
151
|
+
const failedRefs = [];
|
|
152
|
+
let passRef;
|
|
153
|
+
for (const it of iters) {
|
|
154
|
+
if (!isRecord(it))
|
|
155
|
+
continue;
|
|
156
|
+
const n = typeof it["iteration"] === "number" ? it["iteration"] : "?";
|
|
157
|
+
if (it["result"] === "fail") {
|
|
158
|
+
sawFail = true;
|
|
159
|
+
failedRefs.push(`${contract.contractId}:iteration-${n}`);
|
|
160
|
+
}
|
|
161
|
+
else if (it["result"] === "pass" && sawFail) {
|
|
162
|
+
flipped = true;
|
|
163
|
+
passRef = `${contract.contractId}:iteration-${n}`;
|
|
164
|
+
break; // first pass after a fail is the flip point
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (flipped && passRef !== undefined) {
|
|
168
|
+
const category = `fix-contrast:${contract.contractId}`;
|
|
169
|
+
const tags = ["phase:fix-contrast", `sprintId:${contract.contractId}`];
|
|
170
|
+
const summary = `Sprint '${contract.contractId}' flipped from fail to pass after ${failedRefs.length} iteration(s)`;
|
|
171
|
+
for (const ref of failedRefs) {
|
|
172
|
+
upsertGroup(category, tags, summary, ref);
|
|
173
|
+
}
|
|
174
|
+
upsertGroup(category, tags, summary, passRef);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
137
177
|
// ── (c, fallback) rework signal straight from history events ────────────
|
|
138
178
|
// The real pipeline writes { event:"evaluation-failed", phase:"rework", sprintId, details:{iteration} }.
|
|
139
179
|
// Only used for sprints not already accounted for via iterationHistory (avoids double-count).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distill.js","sourceRoot":"","sources":["../../../src/orchestrator/memory/distill.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"distill.js","sourceRoot":"","sources":["../../../src/orchestrator/memory/distill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PURE deterministic project-fact detector.
|
|
3
|
+
*
|
|
4
|
+
* PURE — no fs reads, no Date.now(), no createClient, no network access, no side effects.
|
|
5
|
+
* Takes already-parsed manifests/config as inputs and returns FactDraft[] deterministically.
|
|
6
|
+
* The thin IO caller (seedProjectFacts) handles all fs reads and clock-stamping.
|
|
7
|
+
*
|
|
8
|
+
* Mirror of distill.ts: the pure fn is separate from the IO boundary.
|
|
9
|
+
*/
|
|
10
|
+
import type { FactInput } from "../../state/facts.js";
|
|
11
|
+
/** Already-parsed manifests/config passed in by the thin IO caller. */
|
|
12
|
+
export interface ProjectInputs {
|
|
13
|
+
/** Parsed package.json content (or null if absent). */
|
|
14
|
+
packageJson: Record<string, unknown> | null;
|
|
15
|
+
/** Parsed bober.config.json content (optional). */
|
|
16
|
+
boberConfig?: Record<string, unknown> | null;
|
|
17
|
+
/**
|
|
18
|
+
* Lockfile presence flags, computed by the caller (no fs in the pure fn).
|
|
19
|
+
* First truthy flag in order npm → yarn → pnpm determines packageManager.
|
|
20
|
+
*/
|
|
21
|
+
lockfiles?: {
|
|
22
|
+
npm?: boolean;
|
|
23
|
+
yarn?: boolean;
|
|
24
|
+
pnpm?: boolean;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A fact draft — everything EXCEPT the injected timestamps, which the caller stamps.
|
|
29
|
+
* Mirrors the FactInput shape but without tValid and tCreated.
|
|
30
|
+
*/
|
|
31
|
+
export type FactDraft = Omit<FactInput, "tValid" | "tCreated">;
|
|
32
|
+
/**
|
|
33
|
+
* PURE: map parsed manifests/config into project-fact drafts.
|
|
34
|
+
* NO fs read, NO Date.now(), NO LLM. Returns [] when nothing is detectable.
|
|
35
|
+
*
|
|
36
|
+
* Detection rules:
|
|
37
|
+
* project/testCommand ← packageJson.scripts.test (if truthy)
|
|
38
|
+
* project/buildCommand ← packageJson.scripts.build (if truthy)
|
|
39
|
+
* project/packageManager ← first lockfile present: npm > yarn > pnpm
|
|
40
|
+
* project/framework ← first dep/devDep found: next > react > vue
|
|
41
|
+
*
|
|
42
|
+
* Scope convention: scope="" (default/programming team) per memoryDir mapping
|
|
43
|
+
* in src/state/memory.ts:27-32. Namespace is a SEPARATE axis (DB file location).
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectProjectFacts(inputs: ProjectInputs, scope?: string): FactDraft[];
|
|
46
|
+
/**
|
|
47
|
+
* Thin IO wrapper: reads manifests from disk, calls the PURE detectProjectFacts,
|
|
48
|
+
* then stamps wall-clock time and writes each draft through writeFact (idempotent).
|
|
49
|
+
*
|
|
50
|
+
* This is the ONLY function in this module that touches the filesystem or the clock.
|
|
51
|
+
* It is extracted here so both pipeline.ts and chat-session.ts can reuse one helper
|
|
52
|
+
* without duplicating the IO pattern.
|
|
53
|
+
*
|
|
54
|
+
* A missing package.json or bober.config.json is NORMAL — the detector returns a
|
|
55
|
+
* partial set of drafts. Never throws for missing files.
|
|
56
|
+
*
|
|
57
|
+
* @param projectRoot - Absolute path to the project root
|
|
58
|
+
* @param namespace - Memory namespace (undefined → default .bober/memory/)
|
|
59
|
+
*/
|
|
60
|
+
export declare function seedProjectFacts(projectRoot: string, namespace?: string): Promise<void>;
|
|
61
|
+
//# sourceMappingURL=fact-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-detector.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/memory/fact-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAUtD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/D;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;AAI/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,SAAK,GAAG,SAAS,EAAE,CAkDjF;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAsDf"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PURE deterministic project-fact detector.
|
|
3
|
+
*
|
|
4
|
+
* PURE — no fs reads, no Date.now(), no createClient, no network access, no side effects.
|
|
5
|
+
* Takes already-parsed manifests/config as inputs and returns FactDraft[] deterministically.
|
|
6
|
+
* The thin IO caller (seedProjectFacts) handles all fs reads and clock-stamping.
|
|
7
|
+
*
|
|
8
|
+
* Mirror of distill.ts: the pure fn is separate from the IO boundary.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile, access } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { FactStore, factsDbPath, ensureFactsDir, writeFact, } from "../../state/facts.js";
|
|
13
|
+
// ── Pure detector ─────────────────────────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* PURE: map parsed manifests/config into project-fact drafts.
|
|
16
|
+
* NO fs read, NO Date.now(), NO LLM. Returns [] when nothing is detectable.
|
|
17
|
+
*
|
|
18
|
+
* Detection rules:
|
|
19
|
+
* project/testCommand ← packageJson.scripts.test (if truthy)
|
|
20
|
+
* project/buildCommand ← packageJson.scripts.build (if truthy)
|
|
21
|
+
* project/packageManager ← first lockfile present: npm > yarn > pnpm
|
|
22
|
+
* project/framework ← first dep/devDep found: next > react > vue
|
|
23
|
+
*
|
|
24
|
+
* Scope convention: scope="" (default/programming team) per memoryDir mapping
|
|
25
|
+
* in src/state/memory.ts:27-32. Namespace is a SEPARATE axis (DB file location).
|
|
26
|
+
*/
|
|
27
|
+
export function detectProjectFacts(inputs, scope = "") {
|
|
28
|
+
const drafts = [];
|
|
29
|
+
const pkg = inputs.packageJson;
|
|
30
|
+
// ── Scripts → testCommand / buildCommand ─────────────────────────
|
|
31
|
+
const scripts = pkg !== null && typeof pkg === "object" && pkg !== undefined
|
|
32
|
+
? pkg.scripts
|
|
33
|
+
: undefined;
|
|
34
|
+
if (scripts !== undefined && scripts !== null) {
|
|
35
|
+
const testCmd = typeof scripts.test === "string" ? scripts.test : undefined;
|
|
36
|
+
if (testCmd) {
|
|
37
|
+
drafts.push(makeDraft(scope, "project", "project/testCommand", testCmd));
|
|
38
|
+
}
|
|
39
|
+
const buildCmd = typeof scripts.build === "string" ? scripts.build : undefined;
|
|
40
|
+
if (buildCmd) {
|
|
41
|
+
drafts.push(makeDraft(scope, "project", "project/buildCommand", buildCmd));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// ── Lockfile presence → packageManager ───────────────────────────
|
|
45
|
+
// bober: deterministic order: npm first, then yarn, then pnpm; first match wins
|
|
46
|
+
const lockfiles = inputs.lockfiles ?? {};
|
|
47
|
+
if (lockfiles.npm) {
|
|
48
|
+
drafts.push(makeDraft(scope, "project", "project/packageManager", "npm"));
|
|
49
|
+
}
|
|
50
|
+
else if (lockfiles.yarn) {
|
|
51
|
+
drafts.push(makeDraft(scope, "project", "project/packageManager", "yarn"));
|
|
52
|
+
}
|
|
53
|
+
else if (lockfiles.pnpm) {
|
|
54
|
+
drafts.push(makeDraft(scope, "project", "project/packageManager", "pnpm"));
|
|
55
|
+
}
|
|
56
|
+
// ── Dependencies → framework ──────────────────────────────────────
|
|
57
|
+
// Check deps + devDeps in fixed order: next before react (next implies react)
|
|
58
|
+
if (pkg !== null && pkg !== undefined) {
|
|
59
|
+
const deps = pkg.dependencies ?? {};
|
|
60
|
+
const devDeps = pkg.devDependencies ?? {};
|
|
61
|
+
const allDeps = { ...deps, ...devDeps };
|
|
62
|
+
if ("next" in allDeps) {
|
|
63
|
+
drafts.push(makeDraft(scope, "project", "project/framework", "next"));
|
|
64
|
+
}
|
|
65
|
+
else if ("react" in allDeps) {
|
|
66
|
+
drafts.push(makeDraft(scope, "project", "project/framework", "react"));
|
|
67
|
+
}
|
|
68
|
+
else if ("vue" in allDeps) {
|
|
69
|
+
drafts.push(makeDraft(scope, "project", "project/framework", "vue"));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return drafts;
|
|
73
|
+
}
|
|
74
|
+
// ── Helper ────────────────────────────────────────────────────────────
|
|
75
|
+
function makeDraft(scope, subject, predicate, value) {
|
|
76
|
+
return {
|
|
77
|
+
scope,
|
|
78
|
+
subject,
|
|
79
|
+
predicate,
|
|
80
|
+
value,
|
|
81
|
+
confidence: 1,
|
|
82
|
+
sourceRunId: null,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// ── IO seed (thin caller) ─────────────────────────────────────────────
|
|
86
|
+
/**
|
|
87
|
+
* Thin IO wrapper: reads manifests from disk, calls the PURE detectProjectFacts,
|
|
88
|
+
* then stamps wall-clock time and writes each draft through writeFact (idempotent).
|
|
89
|
+
*
|
|
90
|
+
* This is the ONLY function in this module that touches the filesystem or the clock.
|
|
91
|
+
* It is extracted here so both pipeline.ts and chat-session.ts can reuse one helper
|
|
92
|
+
* without duplicating the IO pattern.
|
|
93
|
+
*
|
|
94
|
+
* A missing package.json or bober.config.json is NORMAL — the detector returns a
|
|
95
|
+
* partial set of drafts. Never throws for missing files.
|
|
96
|
+
*
|
|
97
|
+
* @param projectRoot - Absolute path to the project root
|
|
98
|
+
* @param namespace - Memory namespace (undefined → default .bober/memory/)
|
|
99
|
+
*/
|
|
100
|
+
export async function seedProjectFacts(projectRoot, namespace) {
|
|
101
|
+
// ── Read manifests (best-effort; missing files → null/false) ─────
|
|
102
|
+
let packageJson = null;
|
|
103
|
+
try {
|
|
104
|
+
const raw = await readFile(join(projectRoot, "package.json"), "utf-8");
|
|
105
|
+
const parsed = JSON.parse(raw);
|
|
106
|
+
packageJson = typeof parsed === "object" && parsed !== null
|
|
107
|
+
? parsed
|
|
108
|
+
: null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Missing or unparseable package.json → leave null
|
|
112
|
+
}
|
|
113
|
+
let boberConfig = null;
|
|
114
|
+
try {
|
|
115
|
+
const raw = await readFile(join(projectRoot, "bober.config.json"), "utf-8");
|
|
116
|
+
const parsed = JSON.parse(raw);
|
|
117
|
+
boberConfig = typeof parsed === "object" && parsed !== null
|
|
118
|
+
? parsed
|
|
119
|
+
: null;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Missing or unparseable bober.config.json → leave null
|
|
123
|
+
}
|
|
124
|
+
// ── Detect lockfile presence (fs.access is synchronous-ish, but async) ──
|
|
125
|
+
const [npmExists, yarnExists, pnpmExists] = await Promise.all([
|
|
126
|
+
access(join(projectRoot, "package-lock.json")).then(() => true).catch(() => false),
|
|
127
|
+
access(join(projectRoot, "yarn.lock")).then(() => true).catch(() => false),
|
|
128
|
+
access(join(projectRoot, "pnpm-lock.yaml")).then(() => true).catch(() => false),
|
|
129
|
+
]);
|
|
130
|
+
const inputs = {
|
|
131
|
+
packageJson,
|
|
132
|
+
boberConfig,
|
|
133
|
+
lockfiles: { npm: npmExists, yarn: yarnExists, pnpm: pnpmExists },
|
|
134
|
+
};
|
|
135
|
+
// ── Detect (PURE) ─────────────────────────────────────────────────
|
|
136
|
+
const drafts = detectProjectFacts(inputs);
|
|
137
|
+
if (drafts.length === 0)
|
|
138
|
+
return;
|
|
139
|
+
// ── Write through reconcile (idempotent — NOOP on unchanged) ─────
|
|
140
|
+
// Stamp wall-clock once at the IO boundary (NEVER inside the pure fn).
|
|
141
|
+
const now = new Date().toISOString();
|
|
142
|
+
await ensureFactsDir(projectRoot, namespace);
|
|
143
|
+
const store = new FactStore(factsDbPath(projectRoot, namespace));
|
|
144
|
+
try {
|
|
145
|
+
for (const draft of drafts) {
|
|
146
|
+
await writeFact(store, { ...draft, tValid: now, tCreated: now }, { now });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
store.close();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=fact-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-detector.js","sourceRoot":"","sources":["../../../src/orchestrator/memory/fact-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FactInput, FactRecord } from "../../state/facts.js";
|
|
2
|
+
import type { ReconcileAction } from "./reconcile.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interface for resolving ambiguous fact collisions.
|
|
5
|
+
* The judge is consulted ONLY on a deterministic normalized-key collision
|
|
6
|
+
* where no exact (scope,subject,predicate) match exists.
|
|
7
|
+
*/
|
|
8
|
+
export interface FactJudge {
|
|
9
|
+
resolve(incoming: FactInput, candidate: FactRecord): Promise<ReconcileAction>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build an LLM-backed FactJudge.
|
|
13
|
+
* Mirrors the createClient pattern from src/orchestrator/architect-agent.ts:195-203.
|
|
14
|
+
* Honoring BOBER_TEST_DETERMINISTIC=1 automatically — createClient short-circuits
|
|
15
|
+
* to a DeterministicStubClient whose response is non-JSON, causing parseJudgeAction
|
|
16
|
+
* to return the FALLBACK "add".
|
|
17
|
+
*/
|
|
18
|
+
export declare function createLLMFactJudge(provider?: string | null, endpoint?: string | null, providerConfig?: Record<string, unknown>, model?: string): FactJudge;
|
|
19
|
+
//# sourceMappingURL=fact-judge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-judge.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/memory/fact-judge.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC/E;AA6GD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,CAAC,EAAE,MAAM,GACb,SAAS,CAUX"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ── fact-judge.ts ──────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// LLM-backed FactJudge for resolving normalized-key ambiguity during
|
|
4
|
+
// fact reconciliation. The ONLY place in the reconcile layer that imports
|
|
5
|
+
// createClient or touches the network.
|
|
6
|
+
//
|
|
7
|
+
// On ANY parse failure or thrown error, resolve() returns "add" — never
|
|
8
|
+
// lets the LLM corrupt the store.
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { createClient } from "../../providers/factory.js";
|
|
11
|
+
import { resolveModel } from "../model-resolver.js";
|
|
12
|
+
// ── Zod schema ─────────────────────────────────────────────────────────
|
|
13
|
+
const JudgeResponseSchema = z.object({
|
|
14
|
+
action: z.enum(["add", "update", "delete", "noop"]),
|
|
15
|
+
});
|
|
16
|
+
const FALLBACK = "add";
|
|
17
|
+
// ── Helpers (mirrored from turn-classifier.ts) ─────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Strip code fences (```json ... ``` or ``` ... ```) from a string.
|
|
20
|
+
*/
|
|
21
|
+
function stripCodeFences(text) {
|
|
22
|
+
return text.replace(/```(?:json)?\s*([\s\S]*?)```/g, "$1").trim();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Extract the first balanced {...} JSON object substring.
|
|
26
|
+
* Returns null if no balanced object found.
|
|
27
|
+
*/
|
|
28
|
+
function extractFirstObject(text) {
|
|
29
|
+
const start = text.indexOf("{");
|
|
30
|
+
if (start === -1)
|
|
31
|
+
return null;
|
|
32
|
+
let depth = 0;
|
|
33
|
+
for (let i = start; i < text.length; i++) {
|
|
34
|
+
if (text[i] === "{")
|
|
35
|
+
depth++;
|
|
36
|
+
else if (text[i] === "}") {
|
|
37
|
+
depth--;
|
|
38
|
+
if (depth === 0)
|
|
39
|
+
return text.slice(start, i + 1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Defensively parse text into a ReconcileAction.
|
|
46
|
+
* Returns FALLBACK ("add") on any error.
|
|
47
|
+
*/
|
|
48
|
+
function parseJudgeAction(text) {
|
|
49
|
+
try {
|
|
50
|
+
const stripped = stripCodeFences(text);
|
|
51
|
+
const extracted = extractFirstObject(stripped) ?? stripped;
|
|
52
|
+
const parsed = JSON.parse(extracted);
|
|
53
|
+
const result = JudgeResponseSchema.safeParse(parsed);
|
|
54
|
+
if (result.success) {
|
|
55
|
+
return result.data.action;
|
|
56
|
+
}
|
|
57
|
+
return FALLBACK;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return FALLBACK;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ── LLMFactJudge ──────────────────────────────────────────────────────
|
|
64
|
+
class LLMFactJudge {
|
|
65
|
+
llm;
|
|
66
|
+
model;
|
|
67
|
+
constructor(llm, model) {
|
|
68
|
+
this.llm = llm;
|
|
69
|
+
this.model = model;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve an ambiguous fact collision using an LLM judgment.
|
|
73
|
+
* Uses jsonObjectMode:true for provider parity.
|
|
74
|
+
* On ANY failure (network, parse error), returns "add" — never corrupts the store.
|
|
75
|
+
*/
|
|
76
|
+
async resolve(incoming, candidate) {
|
|
77
|
+
const system = [
|
|
78
|
+
"You are a fact-reconciliation judge for a semantic knowledge store.",
|
|
79
|
+
"Given an INCOMING fact and a CANDIDATE active fact with the same normalized subject+predicate,",
|
|
80
|
+
"decide whether to add, update, delete, or ignore the incoming fact.",
|
|
81
|
+
"",
|
|
82
|
+
"Respond ONLY with a JSON object with an 'action' field:",
|
|
83
|
+
' {"action":"add"} — insert the incoming fact as a new active fact (both will coexist)',
|
|
84
|
+
' {"action":"update"} — supersede the candidate with the incoming fact',
|
|
85
|
+
' {"action":"delete"} — invalidate the candidate, do not insert incoming',
|
|
86
|
+
' {"action":"noop"} — discard the incoming fact, keep the candidate unchanged',
|
|
87
|
+
"",
|
|
88
|
+
"Return ONLY the JSON object, no other text.",
|
|
89
|
+
].join("\n");
|
|
90
|
+
const userContent = [
|
|
91
|
+
`INCOMING: subject="${incoming.subject}", predicate="${incoming.predicate}", value="${incoming.value}"`,
|
|
92
|
+
`CANDIDATE: subject="${candidate.subject}", predicate="${candidate.predicate}", value="${candidate.value}"`,
|
|
93
|
+
].join("\n");
|
|
94
|
+
try {
|
|
95
|
+
const response = await this.llm.chat({
|
|
96
|
+
model: this.model,
|
|
97
|
+
system,
|
|
98
|
+
messages: [{ role: "user", content: userContent }],
|
|
99
|
+
jsonObjectMode: true,
|
|
100
|
+
});
|
|
101
|
+
return parseJudgeAction(response.text);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return FALLBACK;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// ── Factory ────────────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* Build an LLM-backed FactJudge.
|
|
111
|
+
* Mirrors the createClient pattern from src/orchestrator/architect-agent.ts:195-203.
|
|
112
|
+
* Honoring BOBER_TEST_DETERMINISTIC=1 automatically — createClient short-circuits
|
|
113
|
+
* to a DeterministicStubClient whose response is non-JSON, causing parseJudgeAction
|
|
114
|
+
* to return the FALLBACK "add".
|
|
115
|
+
*/
|
|
116
|
+
export function createLLMFactJudge(provider, endpoint, providerConfig, model) {
|
|
117
|
+
const client = createClient(provider ?? null, endpoint ?? null, providerConfig, model, "FactJudge");
|
|
118
|
+
const resolvedModel = resolveModel(model ?? "sonnet");
|
|
119
|
+
return new LLMFactJudge(client, resolvedModel);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=fact-judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-judge.js","sourceRoot":"","sources":["../../../src/orchestrator/memory/fact-judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PURE deterministic, STORE-ONLY retrieval of relevant project facts for the planner.
|
|
3
|
+
*
|
|
4
|
+
* Opens the FactStore once, reads active facts for the requested scope, then
|
|
5
|
+
* performs all ranking in memory (pure). Mirrors the retrieve.ts pattern for lessons.
|
|
6
|
+
*
|
|
7
|
+
* PURE beyond the single store open/read/close — no network, no Date.now(), no LLM.
|
|
8
|
+
*/
|
|
9
|
+
import type { FactRecord } from "../../state/facts.js";
|
|
10
|
+
/**
|
|
11
|
+
* Load and rank at most `topK` active facts from the store that are relevant
|
|
12
|
+
* to the given `keywords` and `scope`.
|
|
13
|
+
*
|
|
14
|
+
* ONE store open/read/close, then pure ranking. Scope isolation is enforced by
|
|
15
|
+
* the SQL WHERE clause in FactStore.getActiveFacts(scope) — facts in scope A
|
|
16
|
+
* NEVER surface when querying scope B.
|
|
17
|
+
*
|
|
18
|
+
* Scoring: deterministic token-overlap between lowercased keyword tokens and
|
|
19
|
+
* each record's subject + predicate + value tokens.
|
|
20
|
+
* Sort: score DESC, then id ASC (byte-stable tiebreak, mirrors retrieve.ts:103).
|
|
21
|
+
*
|
|
22
|
+
* Design note: when keywords is empty, keywordTokens.size === 0, scoreFact
|
|
23
|
+
* returns 0 for all records, and the score > 0 filter yields an empty result.
|
|
24
|
+
* This matches retrieve.ts behaviour. Project facts are few and always written
|
|
25
|
+
* with known predicates, so callers should pass relevant keywords (e.g. from
|
|
26
|
+
* the user prompt) to surface them.
|
|
27
|
+
*
|
|
28
|
+
* @param projectRoot - Absolute path to the project root containing .bober/
|
|
29
|
+
* @param scope - Fact scope (e.g. "" for default/programming team)
|
|
30
|
+
* @param keywords - Keywords to rank against (e.g. from the user prompt)
|
|
31
|
+
* @param options - topK cap and optional namespace (selects DB file location)
|
|
32
|
+
*/
|
|
33
|
+
export declare function retrieveRelevantFacts(projectRoot: string, scope: string, keywords: string[], { topK, namespace, }?: {
|
|
34
|
+
topK?: number;
|
|
35
|
+
namespace?: string;
|
|
36
|
+
}): Promise<FactRecord[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Render a compact planner context block from an array of FactRecord values.
|
|
39
|
+
*
|
|
40
|
+
* Mirrors serializeLessonsForPlanner (retrieve.ts:122-144):
|
|
41
|
+
* - Empty input → ""
|
|
42
|
+
* - Header line + one "- subject/predicate: value" line per fact
|
|
43
|
+
* - Hard charBudget slice (output length is GUARANTEED ≤ charBudget)
|
|
44
|
+
*
|
|
45
|
+
* @param records - Already-ranked records (from retrieveRelevantFacts)
|
|
46
|
+
* @param options - charBudget: hard character limit (default DEFAULT_CHAR_BUDGET)
|
|
47
|
+
* @returns Compact string block, at most charBudget characters
|
|
48
|
+
*/
|
|
49
|
+
export declare function serializeFactsForContext(records: FactRecord[], { charBudget }?: {
|
|
50
|
+
charBudget?: number;
|
|
51
|
+
}): string;
|
|
52
|
+
//# sourceMappingURL=fact-retrieve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-retrieve.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/memory/fact-retrieve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAiDvD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,EAClB,EACE,IAAoB,EACpB,SAAS,GACV,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,OAAO,CAAC,UAAU,EAAE,CAAC,CAuBvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,UAAU,EAAE,EACrB,EAAE,UAAgC,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjE,MAAM,CAgBR"}
|