agent-bober 0.17.1 → 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/plugin.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +158 -5
- 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/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/index.js +12 -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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bober",
|
|
3
3
|
"description": "Generator-Evaluator multi-agent harness for building applications autonomously with Claude",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.18.0",
|
|
5
5
|
"author": { "name": "BOBER3r" },
|
|
6
6
|
"homepage": "https://agentbober.com",
|
|
7
7
|
"repository": "https://github.com/BOBER3r/agent-bober",
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.18.0] — 2026-06-23
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Standalone `plan` → `sprint` flow**: `plan` now materializes sprint contracts to `.bober/contracts/` after planning. Previously only the `run` pipeline did this, so a standalone `plan` followed by `sprint` failed with "No sprint contracts found." `plan answer` likewise materializes contracts when it resolves a spec to `ready`, and the next-step hints now correctly point to `npx agent-bober sprint`.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Shared `materializeContracts` helper** (`src/orchestrator/contract-materialization.ts`) used by both `plan` and the `run` pipeline as the single source of truth for spec → contract materialization. It prefers valid embedded `spec.sprints[]` (e.g. planner-authored contracts), falling back to feature-derived generation when they are absent or invalid. Contract ids are now deterministic and zero-padded (`sprint-<specId>-NN`) so `listContracts` ordering matches execution order at ten or more sprints.
|
|
19
|
+
- **`run` honors embedded `spec.sprints[]`**: when the planner emits valid embedded contracts, `run` uses them and skips the per-feature precision LLM calls.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **`sprint` scopes to the active spec**: contract selection is now filtered to the latest spec's `specId`, so stale contracts from other specs are not executed. `sprint` also refuses a `needs-clarification` spec (printing the open questions and the correct `plan answer` command) and gives a clearer empty-contracts message pointing at `plan` or `run`.
|
|
24
|
+
|
|
10
25
|
## [0.17.1] — 2026-06-13
|
|
11
26
|
|
|
12
27
|
### Added
|
package/README.md
CHANGED
|
@@ -211,15 +211,27 @@ agent-bober is **provider-agnostic**. Use any LLM provider for any agent role. M
|
|
|
211
211
|
|
|
212
212
|
### Supported Providers
|
|
213
213
|
|
|
214
|
-
| Provider | Shorthands | API Key |
|
|
214
|
+
| Provider | Shorthands | API Key (env var) |
|
|
215
215
|
|----------|-----------|---------|
|
|
216
216
|
| **Anthropic** (default) | `opus`, `sonnet`, `haiku` | `ANTHROPIC_API_KEY` |
|
|
217
|
+
| **DeepSeek** | `deepseek`, `deepseek-v4-pro`, `deepseek-v4-flash` | `DEEPSEEK_API_KEY` |
|
|
217
218
|
| **OpenAI** | Any OpenAI model ID | `OPENAI_API_KEY` |
|
|
218
219
|
| **Google Gemini** | `gemini-pro`, `gemini-flash` | `GOOGLE_API_KEY` or `GEMINI_API_KEY` |
|
|
219
|
-
| **OpenAI-Compatible** | Any model (Ollama, LM Studio, Groq,
|
|
220
|
+
| **OpenAI-Compatible** | Any model (Ollama, LM Studio, Groq, custom endpoints) | Optional (none for local servers) |
|
|
220
221
|
|
|
221
222
|
Shorthands resolve to the latest model version automatically. You can also pass any full model ID directly -- it will be sent to the provider as-is.
|
|
222
223
|
|
|
224
|
+
> **Which API key do I need? (read this first)**
|
|
225
|
+
>
|
|
226
|
+
> **The default is Anthropic, so `ANTHROPIC_API_KEY` on its own means every role calls Claude — nothing else.** Setting `ANTHROPIC_API_KEY` does **not** turn on DeepSeek. Provider selection is **config-driven, not key-driven**: a key is only used if a role is actually pointed at that provider.
|
|
227
|
+
>
|
|
228
|
+
> To use **DeepSeek** you need **three** things together:
|
|
229
|
+
> 1. `npm install openai` — the OpenAI SDK is the OpenAI-compatible client DeepSeek runs through (an optional peer dependency).
|
|
230
|
+
> 2. `export DEEPSEEK_API_KEY=sk-...` — get a key at <https://platform.deepseek.com>. (`ANTHROPIC_API_KEY` is **not** needed if no role uses Anthropic.)
|
|
231
|
+
> 3. Point one or more roles at DeepSeek in `bober.config.json` — see [DeepSeek setup (full example)](#deepseek-setup-full-example) below.
|
|
232
|
+
>
|
|
233
|
+
> DeepSeek is **not** reachable with the `--provider` CLI flag alone (that flag only swaps the provider name; DeepSeek also needs its model + endpoint) — configure it in `bober.config.json`.
|
|
234
|
+
|
|
223
235
|
### Capability Matrix
|
|
224
236
|
|
|
225
237
|
> **This matrix applies to the standalone CLI / programmatic provider layer only** (`npx agent-bober run …`), where bober calls each provider's API directly. It does **not** apply to the **Claude Code plugin**: when you run a skill like `/bober-run` inside Claude Code, the roles are spawned as Claude Code subagents on your Claude subscription, so provider selection (including `claude-code`) does not apply. See [Claude Code Plugin](#claude-code-plugin) below.
|
|
@@ -246,6 +258,65 @@ Each `claude -p` call injects approximately **40,000 tokens of system-prompt ove
|
|
|
246
258
|
|
|
247
259
|
See [`docs/providers.md`](docs/providers.md) for copy-paste config snippets for each provider.
|
|
248
260
|
|
|
261
|
+
### DeepSeek setup (full example)
|
|
262
|
+
|
|
263
|
+
DeepSeek runs through the built-in OpenAI-compatible adapter pointed at `https://api.deepseek.com`. End-to-end:
|
|
264
|
+
|
|
265
|
+
**1. Install the OpenAI-compatible client** (one-time):
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
npm install openai
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**2. Export your DeepSeek key** (get one at <https://platform.deepseek.com>):
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
export DEEPSEEK_API_KEY=sk-...
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**3a. Configure roles — shorthand (simplest).** Set only the `model`; the provider (`openai-compat`) and the `https://api.deepseek.com` endpoint are inferred automatically:
|
|
278
|
+
|
|
279
|
+
```jsonc
|
|
280
|
+
// bober.config.json — DeepSeek for every role
|
|
281
|
+
{
|
|
282
|
+
"planner": { "model": "deepseek-v4-pro" },
|
|
283
|
+
"researcher": { "model": "deepseek-v4-flash" },
|
|
284
|
+
"curator": { "model": "deepseek-v4-pro" },
|
|
285
|
+
"generator": { "model": "deepseek-v4-pro" },
|
|
286
|
+
"evaluator": { "model": "deepseek-v4-flash" }
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**3b. Configure roles — explicit (equivalent).** Spell out the provider and endpoint if you prefer — also the form to use for a self-hosted DeepSeek-compatible gateway:
|
|
291
|
+
|
|
292
|
+
```jsonc
|
|
293
|
+
{
|
|
294
|
+
"generator": {
|
|
295
|
+
"provider": "openai-compat",
|
|
296
|
+
"model": "deepseek-v4-pro",
|
|
297
|
+
"endpoint": "https://api.deepseek.com"
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**4. Run:**
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
agent-bober run "Build a REST API with auth and CRUD"
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
> Use `"provider": "openai-compat"` (as in 3b), **not** `"provider": "deepseek"` — `deepseek` is a *model* shorthand, not a provider name, so `"provider": "deepseek"` is rejected as an unsupported provider.
|
|
309
|
+
|
|
310
|
+
**Mix providers** — e.g. plan on Claude (highest quality) and generate/evaluate on DeepSeek (cheaper). You then need **both** `ANTHROPIC_API_KEY` and `DEEPSEEK_API_KEY` in your environment:
|
|
311
|
+
|
|
312
|
+
```jsonc
|
|
313
|
+
{
|
|
314
|
+
"planner": { "model": "opus" },
|
|
315
|
+
"generator": { "model": "deepseek-v4-pro" },
|
|
316
|
+
"evaluator": { "model": "deepseek-v4-flash" }
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
249
320
|
### Configuration
|
|
250
321
|
|
|
251
322
|
Set providers per agent role in `bober.config.json`:
|
|
@@ -437,15 +508,39 @@ The `/bober-principles` command also triggers auto-discovery when called with no
|
|
|
437
508
|
```bash
|
|
438
509
|
npx agent-bober init [preset] # Initialize project (with provider selection)
|
|
439
510
|
npx agent-bober update # Refresh .claude/ commands + agents after upgrading the package
|
|
440
|
-
npx agent-bober plan "feature" # Run the planner
|
|
511
|
+
npx agent-bober plan "feature" # Run the planner (also materializes sprint contracts)
|
|
441
512
|
npx agent-bober plan answer <specId> # Resolve clarification questions interactively
|
|
442
513
|
npx agent-bober plan answer <specId> <questionId> "..." # Resolve a single clarification question
|
|
443
|
-
npx agent-bober sprint # Execute next sprint
|
|
514
|
+
npx agent-bober sprint # Execute next sprint (consumes plan's contracts)
|
|
444
515
|
npx agent-bober eval # Evaluate current sprint
|
|
445
516
|
npx agent-bober run "feature" # Full autonomous loop
|
|
517
|
+
npx agent-bober run "feature" --team example # Full autonomous loop using the 'example' team
|
|
518
|
+
npx agent-bober chat # Interactive chat REPL (roster + memory aware)
|
|
519
|
+
npx agent-bober chat example # Interactive chat REPL using the 'example' team
|
|
446
520
|
npx agent-bober mcp # Start MCP server (Cursor/Windsurf)
|
|
447
521
|
```
|
|
448
522
|
|
|
523
|
+
#### Chat Steer Commands (Phase 2 — mid-flight HITL)
|
|
524
|
+
|
|
525
|
+
Inside the `bober chat` REPL you can steer in-flight runs with these commands:
|
|
526
|
+
|
|
527
|
+
| Command | Description |
|
|
528
|
+
|---|---|
|
|
529
|
+
| `/careful [on\|off]` | Toggle approval gates for new runs. When ON, new runs spawn with `--approve-gates post-research,post-plan,post-sprint` and pause at each curated gate waiting for human input. |
|
|
530
|
+
| `/approve <checkpointId>` | Approve a pending checkpoint (e.g. `post-plan`, `post-sprint`) and resume the run. |
|
|
531
|
+
| `/reject <checkpointId> [feedback]` | Reject a pending checkpoint with optional feedback for the run to use on retry. |
|
|
532
|
+
| `/tell <runId> <text>` | Queue free-text guidance for a run — applied at the next pipeline boundary. |
|
|
533
|
+
| `/pause <runId>` | Soft-pause a run at the next cooperative boundary. The process stays alive. |
|
|
534
|
+
| `/resume <runId>` | Resume a soft-paused run. |
|
|
535
|
+
| `/stop <runId>` | Hard-stop a run by killing its process (contrast with `/pause` which is cooperative). |
|
|
536
|
+
| `/runs` | List all active and recent runs. |
|
|
537
|
+
| `/help` | Show the full command list. |
|
|
538
|
+
| `/exit` | Exit the chat session. |
|
|
539
|
+
|
|
540
|
+
**Curated gates** (triggered by `--approve-gates`): `post-research`, `post-plan`, `post-sprint`. Each gate pauses the run and surfaces a notice in the next chat turn. Use `/approve` or `/reject` to resolve.
|
|
541
|
+
|
|
542
|
+
**Limitation:** Only one careful run at a time is fully supported. Pending markers are checkpointId-keyed in a shared `.bober/approvals/` directory, so two concurrent careful runs that hit the same gate id would collide. The non-chat equivalents (`list-approvals`, `approve`, `reject`) remain available as fallback. See `docs/chat-steer.md` for the full model and the documented limitations.
|
|
543
|
+
|
|
449
544
|
#### New Commands (Sprints 9–25)
|
|
450
545
|
|
|
451
546
|
The following commands were added after the initial release. Full reference in [COMMANDS.md](./COMMANDS.md).
|
|
@@ -481,7 +576,7 @@ npx agent-bober playbook search '<symptom>' # Search by symptom
|
|
|
481
576
|
|
|
482
577
|
#### Clarification gating
|
|
483
578
|
|
|
484
|
-
When the planner can't fully decompose a feature without more information, it stops with `status: "needs-clarification"` instead of fabricating sprints. The CLI surfaces the open questions and you resolve them via `plan answer`. After the last question is answered the spec auto-promotes to `status: "ready"
|
|
579
|
+
When the planner can't fully decompose a feature without more information, it stops with `status: "needs-clarification"` instead of fabricating sprints — and writes **no** contracts. The CLI surfaces the open questions and you resolve them via `plan answer`. After the last question is answered the spec auto-promotes to `status: "ready"`, its sprint contracts are materialized into `.bober/contracts/`, and the next `sprint`/`run` proceeds. See the **Architecture** section for the full lifecycle.
|
|
485
580
|
|
|
486
581
|
### Fully Autonomous Mode (no human in the loop)
|
|
487
582
|
|
|
@@ -519,6 +614,17 @@ agent-bober init nextjs
|
|
|
519
614
|
agent-bober run "Build a complete dashboard with auth, CRUD, and charts" --provider openai
|
|
520
615
|
```
|
|
521
616
|
|
|
617
|
+
For **DeepSeek**, set `DEEPSEEK_API_KEY` and point your roles at the `deepseek` model in `bober.config.json` — the `--provider` flag alone is not enough, since DeepSeek also needs its model + endpoint (see [DeepSeek setup (full example)](#deepseek-setup-full-example)):
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
npm install openai
|
|
621
|
+
export DEEPSEEK_API_KEY=sk-...
|
|
622
|
+
cd your-project
|
|
623
|
+
agent-bober init nextjs
|
|
624
|
+
# in bober.config.json set "model": "deepseek-v4-pro" on the roles you want
|
|
625
|
+
agent-bober run "Build a complete dashboard with auth, CRUD, and charts"
|
|
626
|
+
```
|
|
627
|
+
|
|
522
628
|
---
|
|
523
629
|
|
|
524
630
|
## Lens Panels (multi-perspective evaluation & architecture)
|
|
@@ -547,6 +653,38 @@ Leave `lenses` empty to use the full built-in set; `maxConcurrent` bounds how ma
|
|
|
547
653
|
|
|
548
654
|
---
|
|
549
655
|
|
|
656
|
+
## Teams
|
|
657
|
+
|
|
658
|
+
agent-bober supports domain-agnostic **teams** — named configurations that route each run or chat session to a distinct set of providers, a separate memory namespace, and a chosen pipeline shape. **Adding a team is data, not code**: declare it in `bober.config.json`, no source changes required.
|
|
659
|
+
|
|
660
|
+
```jsonc
|
|
661
|
+
{
|
|
662
|
+
"defaultTeam": "programming", // Active team when --team / chat <team> is omitted
|
|
663
|
+
"teams": {
|
|
664
|
+
"example": {
|
|
665
|
+
"displayName": "Example research team",
|
|
666
|
+
"memoryNamespace": "example", // Lessons land in .bober/memory/example/
|
|
667
|
+
"pipelineShape": "ts",
|
|
668
|
+
"providers": { "chat": "openai" }
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
npx agent-bober run "summarise research" --team example
|
|
676
|
+
npx agent-bober chat example
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
The built-in **programming** team is always available (no config entry needed) and uses
|
|
680
|
+
the default `.bober/memory/` path and the project's configured providers.
|
|
681
|
+
|
|
682
|
+
For full documentation on the three differentiation axes (provider routing / memory
|
|
683
|
+
namespace / pipeline shape), the built-in programming team, and the deferred
|
|
684
|
+
`.bober/teams/*.json` file registry, see [docs/teams.md](./docs/teams.md).
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
550
688
|
## Configuration
|
|
551
689
|
|
|
552
690
|
All configuration lives in `bober.config.json` at your project root. The `init` command creates this file from a template, and you can customize it afterward.
|
|
@@ -662,6 +800,17 @@ All configuration lives in `bober.config.json` at your project root. The `init`
|
|
|
662
800
|
"lint": "npm run lint",
|
|
663
801
|
"dev": "npm run dev",
|
|
664
802
|
"typecheck": "npx tsc --noEmit"
|
|
803
|
+
},
|
|
804
|
+
|
|
805
|
+
// -- Teams (NEW: adding a team is data, not code) ----
|
|
806
|
+
"defaultTeam": "programming", // Optional. Active team when --team / chat <team> is omitted.
|
|
807
|
+
"teams": { // Optional. Each entry is a team defined purely as DATA.
|
|
808
|
+
"example": {
|
|
809
|
+
"displayName": "Example research team",
|
|
810
|
+
"memoryNamespace": "example", // Lessons land in .bober/memory/example/
|
|
811
|
+
"pipelineShape": "ts", // "ts" | "skill" | "workflow"
|
|
812
|
+
"providers": { "chat": "openai" } // Partial role->provider override; unset roles keep defaults
|
|
813
|
+
}
|
|
665
814
|
}
|
|
666
815
|
}
|
|
667
816
|
```
|
|
@@ -957,6 +1106,10 @@ All bober state lives in the `.bober/` directory:
|
|
|
957
1106
|
briefings/ Sprint Briefings (curated codebase context per sprint)
|
|
958
1107
|
eval-results/ Evaluation result logs
|
|
959
1108
|
handoffs/ Context handoff documents
|
|
1109
|
+
memory/ Self-improvement memory (per-team namespaced)
|
|
1110
|
+
INDEX.md Distilled lessons index (planner-read)
|
|
1111
|
+
QUARANTINE.md Pruned/contradictory lessons (moved, never deleted)
|
|
1112
|
+
facts.db Bi-temporal SQLite semantic-facts store (auto-produced, planner-read)
|
|
960
1113
|
progress.md Human-readable progress tracker
|
|
961
1114
|
history.jsonl Machine-readable event log
|
|
962
1115
|
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LLMClient } from "../providers/types.js";
|
|
2
|
+
import type { TurnRecord } from "./conversation-store.js";
|
|
3
|
+
export declare class Answerer {
|
|
4
|
+
private readonly llm;
|
|
5
|
+
private readonly model;
|
|
6
|
+
constructor(llm: LLMClient, model: string);
|
|
7
|
+
/**
|
|
8
|
+
* Produce an answer to the user's input, given context.
|
|
9
|
+
*
|
|
10
|
+
* @param input - The current user message.
|
|
11
|
+
* @param rosterSummary - Compact string summary of active runs.
|
|
12
|
+
* @param memoryDistill - Compact string of lessons from .bober/memory/.
|
|
13
|
+
* @param recentHistory - Recent prior turns for conversation context.
|
|
14
|
+
*/
|
|
15
|
+
answer(input: string, rosterSummary: string, memoryDistill: string, recentHistory: TurnRecord[]): Promise<string>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=answerer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answerer.d.ts","sourceRoot":"","sources":["../../src/chat/answerer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAI1D,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM;IAKzC;;;;;;;OAOG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,UAAU,EAAE,GAC1B,OAAO,CAAC,MAAM,CAAC;CAiCnB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ── answerer.ts ──────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Composes roster summary + memory distill + recent history into one
|
|
4
|
+
// LLMClient.chat call (no jsonObjectMode) and returns the text response.
|
|
5
|
+
// ── Answerer ──────────────────────────────────────────────────────────
|
|
6
|
+
export class Answerer {
|
|
7
|
+
llm;
|
|
8
|
+
model;
|
|
9
|
+
constructor(llm, model) {
|
|
10
|
+
this.llm = llm;
|
|
11
|
+
this.model = model;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Produce an answer to the user's input, given context.
|
|
15
|
+
*
|
|
16
|
+
* @param input - The current user message.
|
|
17
|
+
* @param rosterSummary - Compact string summary of active runs.
|
|
18
|
+
* @param memoryDistill - Compact string of lessons from .bober/memory/.
|
|
19
|
+
* @param recentHistory - Recent prior turns for conversation context.
|
|
20
|
+
*/
|
|
21
|
+
async answer(input, rosterSummary, memoryDistill, recentHistory) {
|
|
22
|
+
const systemParts = [
|
|
23
|
+
"You are bober, an AI assistant integrated with the agent-bober engineering workflow.",
|
|
24
|
+
"",
|
|
25
|
+
"You have access to the following context:",
|
|
26
|
+
"",
|
|
27
|
+
"## Active Runs",
|
|
28
|
+
rosterSummary || "No runs found.",
|
|
29
|
+
"",
|
|
30
|
+
"## Project Memory (Lessons Learned)",
|
|
31
|
+
memoryDistill || "No lessons recorded yet.",
|
|
32
|
+
"",
|
|
33
|
+
"Answer the user's question concisely and helpfully.",
|
|
34
|
+
"If the user asks about runs or agents, use the Active Runs context above.",
|
|
35
|
+
"If the user asks about past mistakes or learnings, use the Project Memory context.",
|
|
36
|
+
];
|
|
37
|
+
const system = systemParts.join("\n");
|
|
38
|
+
// Build message history from stored turns + current input
|
|
39
|
+
const messages = [];
|
|
40
|
+
for (const turn of recentHistory) {
|
|
41
|
+
messages.push({ role: turn.role, content: turn.content });
|
|
42
|
+
}
|
|
43
|
+
messages.push({ role: "user", content: input });
|
|
44
|
+
const response = await this.llm.chat({
|
|
45
|
+
model: this.model,
|
|
46
|
+
system,
|
|
47
|
+
messages,
|
|
48
|
+
});
|
|
49
|
+
return response.text;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=answerer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answerer.js","sourceRoot":"","sources":["../../src/chat/answerer.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,qEAAqE;AACrE,yEAAyE;AAKzE,yEAAyE;AAEzE,MAAM,OAAO,QAAQ;IACF,GAAG,CAAY;IACf,KAAK,CAAS;IAE/B,YAAY,GAAc,EAAE,KAAa;QACvC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CACV,KAAa,EACb,aAAqB,EACrB,aAAqB,EACrB,aAA2B;QAE3B,MAAM,WAAW,GAAa;YAC5B,sFAAsF;YACtF,EAAE;YACF,2CAA2C;YAC3C,EAAE;YACF,gBAAgB;YAChB,aAAa,IAAI,gBAAgB;YACjC,EAAE;YACF,qCAAqC;YACrC,aAAa,IAAI,0BAA0B;YAC3C,EAAE;YACF,qDAAqD;YACrD,2EAA2E;YAC3E,oFAAoF;SACrF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtC,0DAA0D;QAC1D,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM;YACN,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PendingMarker } from "../state/approval-state.js";
|
|
2
|
+
/**
|
|
3
|
+
* Stable identity key for a pending marker.
|
|
4
|
+
* Changes when a gate is re-requested in a later round (different requestedAt),
|
|
5
|
+
* but is stable while the gate remains at the same requestedAt.
|
|
6
|
+
*/
|
|
7
|
+
export declare function markerKey(m: PendingMarker): string;
|
|
8
|
+
export declare class ApprovalCursor {
|
|
9
|
+
private readonly projectRoot;
|
|
10
|
+
private readonly sessionId;
|
|
11
|
+
constructor(projectRoot: string, sessionId: string);
|
|
12
|
+
private path;
|
|
13
|
+
/**
|
|
14
|
+
* Read the set of already-announced marker keys.
|
|
15
|
+
* Returns empty set on missing file or malformed JSON — never throws.
|
|
16
|
+
*/
|
|
17
|
+
private readFile;
|
|
18
|
+
/**
|
|
19
|
+
* Return the subset of markers not yet announced, and atomically record
|
|
20
|
+
* them as announced for this session. Idempotent: calling again with
|
|
21
|
+
* the same markers returns [].
|
|
22
|
+
*/
|
|
23
|
+
filterNew(markers: PendingMarker[]): Promise<PendingMarker[]>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=approval-cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-cursor.d.ts","sourceRoot":"","sources":["../../src/chat/approval-cursor.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAYhE;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAElD;AAID,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;IAGpC,OAAO,CAAC,IAAI;IASZ;;;OAGG;YACW,QAAQ;IAQtB;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAmBpE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// ── approval-cursor.ts ────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Tracks which pending markers have already been announced in chat, by
|
|
4
|
+
// key `${checkpointId}@${requestedAt}`. Persists at
|
|
5
|
+
// .bober/chat/<sessionId>.approvals-cursor.json. Mirrors cursor-store.ts.
|
|
6
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { ensureDir } from "../utils/fs.js";
|
|
9
|
+
const EMPTY = { announced: [] };
|
|
10
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Stable identity key for a pending marker.
|
|
13
|
+
* Changes when a gate is re-requested in a later round (different requestedAt),
|
|
14
|
+
* but is stable while the gate remains at the same requestedAt.
|
|
15
|
+
*/
|
|
16
|
+
export function markerKey(m) {
|
|
17
|
+
return `${m.checkpointId}@${m.requestedAt}`;
|
|
18
|
+
}
|
|
19
|
+
// ── ApprovalCursor ────────────────────────────────────────────────────
|
|
20
|
+
export class ApprovalCursor {
|
|
21
|
+
projectRoot;
|
|
22
|
+
sessionId;
|
|
23
|
+
constructor(projectRoot, sessionId) {
|
|
24
|
+
this.projectRoot = projectRoot;
|
|
25
|
+
this.sessionId = sessionId;
|
|
26
|
+
}
|
|
27
|
+
path() {
|
|
28
|
+
return join(this.projectRoot, ".bober", "chat", `${this.sessionId}.approvals-cursor.json`);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Read the set of already-announced marker keys.
|
|
32
|
+
* Returns empty set on missing file or malformed JSON — never throws.
|
|
33
|
+
*/
|
|
34
|
+
async readFile() {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(await readFile(this.path(), "utf-8"));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { ...EMPTY };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Return the subset of markers not yet announced, and atomically record
|
|
44
|
+
* them as announced for this session. Idempotent: calling again with
|
|
45
|
+
* the same markers returns [].
|
|
46
|
+
*/
|
|
47
|
+
async filterNew(markers) {
|
|
48
|
+
const file = await this.readFile();
|
|
49
|
+
const seen = new Set(file.announced);
|
|
50
|
+
const fresh = markers.filter((m) => !seen.has(markerKey(m)));
|
|
51
|
+
if (fresh.length > 0) {
|
|
52
|
+
for (const m of fresh) {
|
|
53
|
+
seen.add(markerKey(m));
|
|
54
|
+
}
|
|
55
|
+
await ensureDir(join(this.projectRoot, ".bober", "chat"));
|
|
56
|
+
await writeFile(this.path(), JSON.stringify({ announced: [...seen] }, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
|
|
57
|
+
}
|
|
58
|
+
return fresh;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=approval-cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-cursor.js","sourceRoot":"","sources":["../../src/chat/approval-cursor.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uEAAuE;AACvE,oDAAoD;AACpD,0EAA0E;AAE1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAS3C,MAAM,KAAK,GAAkB,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAE/C,yEAAyE;AAEzE;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,CAAgB;IACxC,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IAEN;IACA;IAFnB,YACmB,WAAmB,EACnB,SAAiB;QADjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEI,IAAI;QACV,OAAO,IAAI,CACT,IAAI,CAAC,WAAW,EAChB,QAAQ,EACR,MAAM,EACN,GAAG,IAAI,CAAC,SAAS,wBAAwB,CAC1C,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,QAAQ;QACpB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAkB,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,OAAwB;QACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,EAAE,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACxD,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PendingMarker } from "../state/approval-state.js";
|
|
2
|
+
export declare class ApprovalReader {
|
|
3
|
+
private readonly projectRoot;
|
|
4
|
+
constructor(projectRoot: string);
|
|
5
|
+
/**
|
|
6
|
+
* Read all pending markers from .bober/approvals/*.pending.json.
|
|
7
|
+
* Missing dir => []; corrupt files skipped silently (delegated to listPending).
|
|
8
|
+
*/
|
|
9
|
+
read(): Promise<PendingMarker[]>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=approval-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-reader.d.ts","sourceRoot":"","sources":["../../src/chat/approval-reader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAIhE,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,MAAM;IAEhD;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAGvC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ── approval-reader.ts ────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Read-only wrapper over listPending for chat context.
|
|
4
|
+
// NEVER writes approval markers (Sprint 3 owns the write path).
|
|
5
|
+
import { listPending } from "../state/approval-state.js";
|
|
6
|
+
// ── ApprovalReader ────────────────────────────────────────────────────
|
|
7
|
+
export class ApprovalReader {
|
|
8
|
+
projectRoot;
|
|
9
|
+
constructor(projectRoot) {
|
|
10
|
+
this.projectRoot = projectRoot;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Read all pending markers from .bober/approvals/*.pending.json.
|
|
14
|
+
* Missing dir => []; corrupt files skipped silently (delegated to listPending).
|
|
15
|
+
*/
|
|
16
|
+
async read() {
|
|
17
|
+
return listPending(this.projectRoot);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=approval-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-reader.js","sourceRoot":"","sources":["../../src/chat/approval-reader.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uDAAuD;AACvD,gEAAgE;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;IAAG,CAAC;IAEpD;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class CarefulSidecar {
|
|
2
|
+
private readonly projectRoot;
|
|
3
|
+
private readonly sessionId;
|
|
4
|
+
constructor(projectRoot: string, sessionId: string);
|
|
5
|
+
private path;
|
|
6
|
+
/**
|
|
7
|
+
* Read the careful flag. Missing/malformed file => false (autopilot). Never throws.
|
|
8
|
+
*/
|
|
9
|
+
isCareful(): Promise<boolean>;
|
|
10
|
+
/**
|
|
11
|
+
* Persist the careful flag atomically.
|
|
12
|
+
*/
|
|
13
|
+
setCareful(on: boolean): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=careful-sidecar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"careful-sidecar.d.ts","sourceRoot":"","sources":["../../src/chat/careful-sidecar.ts"],"names":[],"mappings":"AAYA,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;IAGpC,OAAO,CAAC,IAAI;IAIZ;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IASnC;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ7C"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ── careful-sidecar.ts ─────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Persists the per-session "careful mode" toggle at
|
|
4
|
+
// .bober/chat/<sessionId>.careful.json. Default off → autopilot (Phase 1).
|
|
5
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { ensureDir } from "../utils/fs.js";
|
|
8
|
+
// ── CarefulSidecar ────────────────────────────────────────────────────
|
|
9
|
+
export class CarefulSidecar {
|
|
10
|
+
projectRoot;
|
|
11
|
+
sessionId;
|
|
12
|
+
constructor(projectRoot, sessionId) {
|
|
13
|
+
this.projectRoot = projectRoot;
|
|
14
|
+
this.sessionId = sessionId;
|
|
15
|
+
}
|
|
16
|
+
path() {
|
|
17
|
+
return join(this.projectRoot, ".bober", "chat", `${this.sessionId}.careful.json`);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read the careful flag. Missing/malformed file => false (autopilot). Never throws.
|
|
21
|
+
*/
|
|
22
|
+
async isCareful() {
|
|
23
|
+
try {
|
|
24
|
+
const data = JSON.parse(await readFile(this.path(), "utf-8"));
|
|
25
|
+
return data.careful === true;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Persist the careful flag atomically.
|
|
33
|
+
*/
|
|
34
|
+
async setCareful(on) {
|
|
35
|
+
await ensureDir(join(this.projectRoot, ".bober", "chat"));
|
|
36
|
+
await writeFile(this.path(), JSON.stringify({ careful: on }, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=careful-sidecar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"careful-sidecar.js","sourceRoot":"","sources":["../../src/chat/careful-sidecar.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,oDAAoD;AACpD,2EAA2E;AAE3E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IAEN;IACA;IAFnB,YACmB,WAAmB,EACnB,SAAiB;QADjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEI,IAAI;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,eAAe,CAAC,CAAC;IACpF,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAA0B,CAAC;YACvF,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,EAAW;QAC1B,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,EAAE,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAC/C,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;IACJ,CAAC;CACF"}
|