sensorium-mcp 3.1.2 → 3.1.3-board.10
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/Install-Sensorium.ps1 +257 -43
- package/README.md +2 -0
- package/dist/board/api/api.js +84 -0
- package/dist/board/api/api.test.ts +23 -0
- package/dist/board/api/client.js +113 -0
- package/dist/board/components/BottomNav.js +32 -0
- package/dist/board/components/Card.js +78 -0
- package/dist/board/components/Combobox.js +79 -0
- package/dist/board/components/CommentComposer.js +29 -0
- package/dist/board/components/CommentList.js +42 -0
- package/dist/board/components/DirTreePicker.js +128 -0
- package/dist/board/components/Dropdown.js +67 -0
- package/dist/board/components/Lane.js +47 -0
- package/dist/board/components/PriorityChip.js +20 -0
- package/dist/board/components/ProfileSummary.js +89 -0
- package/dist/board/components/StateBanner.js +24 -0
- package/dist/board/components/StatusChip.js +26 -0
- package/dist/board/components/rateLimit.js +32 -0
- package/dist/board/components/rateLimit.test.ts +16 -0
- package/dist/board/components/time.js +14 -0
- package/dist/board/config.js +56 -0
- package/dist/board/index.html +18 -0
- package/dist/board/main.js +37 -0
- package/dist/board/mock/api.mock.js +491 -0
- package/dist/board/mock/api.mock.test.ts +460 -0
- package/dist/board/mock/fixtures.js +512 -0
- package/dist/board/schema/policy.js +261 -0
- package/dist/board/state/recur.js +24 -0
- package/dist/board/state/recur.test.ts +24 -0
- package/dist/board/state/useBoard.js +161 -0
- package/dist/board/state/useBuilder.js +357 -0
- package/dist/board/state/useBuilder.test.ts +468 -0
- package/dist/board/state/useCard.js +193 -0
- package/dist/board/state/useCard.test.ts +435 -0
- package/dist/board/state/useDirBrowser.js +23 -0
- package/dist/board/styles/board.css +2885 -0
- package/dist/board/styles/tokens.css +72 -0
- package/dist/board/vendor/vue.esm-browser.js +9 -0
- package/dist/board/views/App.js +61 -0
- package/dist/board/views/BoardView.js +153 -0
- package/dist/board/views/BuilderView.js +582 -0
- package/dist/board/views/CardView.js +382 -0
- package/dist/board/views/SettingsView.js +152 -0
- package/dist/config/agent-settings.d.ts +11 -0
- package/dist/config/agent-settings.d.ts.map +1 -1
- package/dist/config/agent-settings.js +79 -0
- package/dist/config/agent-settings.js.map +1 -1
- package/dist/config/detail-grant.d.ts +7 -16
- package/dist/config/detail-grant.d.ts.map +1 -1
- package/dist/config/detail-grant.js +12 -35
- package/dist/config/detail-grant.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +17 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/mcp-settings.d.ts +7 -1
- package/dist/config/mcp-settings.d.ts.map +1 -1
- package/dist/config/mcp-settings.js +9 -0
- package/dist/config/mcp-settings.js.map +1 -1
- package/dist/config/misc-settings.d.ts +22 -1
- package/dist/config/misc-settings.d.ts.map +1 -1
- package/dist/config/misc-settings.js +93 -3
- package/dist/config/misc-settings.js.map +1 -1
- package/dist/config/operator-grant.d.ts +9 -0
- package/dist/config/operator-grant.d.ts.map +1 -0
- package/dist/config/operator-grant.js +24 -0
- package/dist/config/operator-grant.js.map +1 -0
- package/dist/config/voice-grant.d.ts +10 -0
- package/dist/config/voice-grant.d.ts.map +1 -0
- package/dist/config/voice-grant.js +18 -0
- package/dist/config/voice-grant.js.map +1 -0
- package/dist/dashboard/board-static.d.ts +22 -0
- package/dist/dashboard/board-static.d.ts.map +1 -0
- package/dist/dashboard/board-static.js +130 -0
- package/dist/dashboard/board-static.js.map +1 -0
- package/dist/dashboard/presets.d.ts +1 -1
- package/dist/dashboard/presets.d.ts.map +1 -1
- package/dist/dashboard/presets.js +1 -1
- package/dist/dashboard/presets.js.map +1 -1
- package/dist/dashboard/routes/agent-templates.d.ts.map +1 -1
- package/dist/dashboard/routes/agent-templates.js +6 -9
- package/dist/dashboard/routes/agent-templates.js.map +1 -1
- package/dist/dashboard/routes/board-body.d.ts +8 -0
- package/dist/dashboard/routes/board-body.d.ts.map +1 -0
- package/dist/dashboard/routes/board-body.js +20 -0
- package/dist/dashboard/routes/board-body.js.map +1 -0
- package/dist/dashboard/routes/board-dir-listing.d.ts +70 -0
- package/dist/dashboard/routes/board-dir-listing.d.ts.map +1 -0
- package/dist/dashboard/routes/board-dir-listing.js +192 -0
- package/dist/dashboard/routes/board-dir-listing.js.map +1 -0
- package/dist/dashboard/routes/board-lane-groups.d.ts +6 -0
- package/dist/dashboard/routes/board-lane-groups.d.ts.map +1 -0
- package/dist/dashboard/routes/board-lane-groups.js +52 -0
- package/dist/dashboard/routes/board-lane-groups.js.map +1 -0
- package/dist/dashboard/routes/board-policy.d.ts +224 -0
- package/dist/dashboard/routes/board-policy.d.ts.map +1 -0
- package/dist/dashboard/routes/board-policy.js +214 -0
- package/dist/dashboard/routes/board-policy.js.map +1 -0
- package/dist/dashboard/routes/board-profile-parse.d.ts +32 -0
- package/dist/dashboard/routes/board-profile-parse.d.ts.map +1 -0
- package/dist/dashboard/routes/board-profile-parse.js +338 -0
- package/dist/dashboard/routes/board-profile-parse.js.map +1 -0
- package/dist/dashboard/routes/board.d.ts +90 -0
- package/dist/dashboard/routes/board.d.ts.map +1 -0
- package/dist/dashboard/routes/board.js +721 -0
- package/dist/dashboard/routes/board.js.map +1 -0
- package/dist/dashboard/routes/codex.d.ts +14 -0
- package/dist/dashboard/routes/codex.d.ts.map +1 -0
- package/dist/dashboard/routes/codex.js +92 -0
- package/dist/dashboard/routes/codex.js.map +1 -0
- package/dist/dashboard/routes/prompts.d.ts +2 -2
- package/dist/dashboard/routes/prompts.d.ts.map +1 -1
- package/dist/dashboard/routes/prompts.js +2 -2
- package/dist/dashboard/routes/prompts.js.map +1 -1
- package/dist/dashboard/routes/settings.d.ts +2 -0
- package/dist/dashboard/routes/settings.d.ts.map +1 -1
- package/dist/dashboard/routes/settings.js +24 -1
- package/dist/dashboard/routes/settings.js.map +1 -1
- package/dist/dashboard/routes/skills.d.ts +7 -1
- package/dist/dashboard/routes/skills.d.ts.map +1 -1
- package/dist/dashboard/routes/skills.js +6 -6
- package/dist/dashboard/routes/skills.js.map +1 -1
- package/dist/dashboard/routes/snapshots.d.ts +2 -1
- package/dist/dashboard/routes/snapshots.d.ts.map +1 -1
- package/dist/dashboard/routes/snapshots.js +24 -18
- package/dist/dashboard/routes/snapshots.js.map +1 -1
- package/dist/dashboard/routes/templates.js +5 -5
- package/dist/dashboard/routes/templates.js.map +1 -1
- package/dist/dashboard/routes/threads-create.d.ts +17 -0
- package/dist/dashboard/routes/threads-create.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-create.js +32 -10
- package/dist/dashboard/routes/threads-create.js.map +1 -1
- package/dist/dashboard/routes/threads-helpers.d.ts +11 -2
- package/dist/dashboard/routes/threads-helpers.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-helpers.js +20 -3
- package/dist/dashboard/routes/threads-helpers.js.map +1 -1
- package/dist/dashboard/routes/threads-read.d.ts +16 -4
- package/dist/dashboard/routes/threads-read.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-read.js +61 -55
- package/dist/dashboard/routes/threads-read.js.map +1 -1
- package/dist/dashboard/routes/threads.d.ts +2 -2
- package/dist/dashboard/routes/threads.d.ts.map +1 -1
- package/dist/dashboard/routes/threads.js +143 -29
- package/dist/dashboard/routes/threads.js.map +1 -1
- package/dist/dashboard/routes/types.d.ts +6 -0
- package/dist/dashboard/routes/types.d.ts.map +1 -1
- package/dist/dashboard/routes/types.js.map +1 -1
- package/dist/dashboard/routes.d.ts +2 -2
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +85 -7
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/spa.html +15 -12
- package/dist/data/board/board-schema.d.ts +29 -0
- package/dist/data/board/board-schema.d.ts.map +1 -0
- package/dist/data/board/board-schema.js +202 -0
- package/dist/data/board/board-schema.js.map +1 -0
- package/dist/data/board/board-types.d.ts +175 -0
- package/dist/data/board/board-types.d.ts.map +1 -0
- package/dist/data/board/board-types.js +9 -0
- package/dist/data/board/board-types.js.map +1 -0
- package/dist/data/board/card.repository.d.ts +137 -0
- package/dist/data/board/card.repository.d.ts.map +1 -0
- package/dist/data/board/card.repository.js +470 -0
- package/dist/data/board/card.repository.js.map +1 -0
- package/dist/data/board/comment.repository.d.ts +14 -0
- package/dist/data/board/comment.repository.d.ts.map +1 -0
- package/dist/data/board/comment.repository.js +42 -0
- package/dist/data/board/comment.repository.js.map +1 -0
- package/dist/data/board/lane-group.repository.d.ts +19 -0
- package/dist/data/board/lane-group.repository.d.ts.map +1 -0
- package/dist/data/board/lane-group.repository.js +66 -0
- package/dist/data/board/lane-group.repository.js.map +1 -0
- package/dist/data/board/profile-defaults.d.ts +17 -0
- package/dist/data/board/profile-defaults.d.ts.map +1 -0
- package/dist/data/board/profile-defaults.js +107 -0
- package/dist/data/board/profile-defaults.js.map +1 -0
- package/dist/data/interfaces.d.ts +1 -0
- package/dist/data/interfaces.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.d.ts +1 -8
- package/dist/data/memory/bootstrap.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.js +27 -37
- package/dist/data/memory/bootstrap.js.map +1 -1
- package/dist/data/memory/consolidation.d.ts +9 -31
- package/dist/data/memory/consolidation.d.ts.map +1 -1
- package/dist/data/memory/consolidation.js +22 -32
- package/dist/data/memory/consolidation.js.map +1 -1
- package/dist/data/memory/db-maintenance.d.ts +54 -0
- package/dist/data/memory/db-maintenance.d.ts.map +1 -0
- package/dist/data/memory/db-maintenance.js +81 -0
- package/dist/data/memory/db-maintenance.js.map +1 -0
- package/dist/data/memory/episodes.d.ts +2 -1
- package/dist/data/memory/episodes.d.ts.map +1 -1
- package/dist/data/memory/episodes.js +5 -1
- package/dist/data/memory/episodes.js.map +1 -1
- package/dist/data/memory/index.d.ts +0 -4
- package/dist/data/memory/index.d.ts.map +1 -1
- package/dist/data/memory/index.js +0 -4
- package/dist/data/memory/index.js.map +1 -1
- package/dist/data/memory/key-knowledge.d.ts +51 -0
- package/dist/data/memory/key-knowledge.d.ts.map +1 -0
- package/dist/data/memory/key-knowledge.js +128 -0
- package/dist/data/memory/key-knowledge.js.map +1 -0
- package/dist/data/memory/migration-runner.d.ts +1 -1
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +407 -1
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/narrative-lint.d.ts +2 -2
- package/dist/data/memory/narrative-lint.d.ts.map +1 -1
- package/dist/data/memory/narrative-lint.js +23 -13
- package/dist/data/memory/narrative-lint.js.map +1 -1
- package/dist/data/memory/narrative-resolutions.d.ts +9 -2
- package/dist/data/memory/narrative-resolutions.d.ts.map +1 -1
- package/dist/data/memory/narrative-resolutions.js +9 -8
- package/dist/data/memory/narrative-resolutions.js.map +1 -1
- package/dist/data/memory/narrative-sources.d.ts +1 -1
- package/dist/data/memory/narrative-sources.d.ts.map +1 -1
- package/dist/data/memory/narrative-sources.js +8 -3
- package/dist/data/memory/narrative-sources.js.map +1 -1
- package/dist/data/memory/narrative-store.d.ts +24 -0
- package/dist/data/memory/narrative-store.d.ts.map +1 -1
- package/dist/data/memory/narrative-store.js +73 -35
- package/dist/data/memory/narrative-store.js.map +1 -1
- package/dist/data/memory/narrative.d.ts.map +1 -1
- package/dist/data/memory/narrative.js +47 -29
- package/dist/data/memory/narrative.js.map +1 -1
- package/dist/data/memory/note-archival.d.ts +1 -1
- package/dist/data/memory/note-archival.d.ts.map +1 -1
- package/dist/data/memory/note-archival.js +7 -3
- package/dist/data/memory/note-archival.js.map +1 -1
- package/dist/data/memory/note-embeddings.d.ts +7 -0
- package/dist/data/memory/note-embeddings.d.ts.map +1 -1
- package/dist/data/memory/note-embeddings.js +6 -2
- package/dist/data/memory/note-embeddings.js.map +1 -1
- package/dist/data/memory/passive-notice.repository.d.ts +70 -0
- package/dist/data/memory/passive-notice.repository.d.ts.map +1 -0
- package/dist/data/memory/passive-notice.repository.js +85 -0
- package/dist/data/memory/passive-notice.repository.js.map +1 -0
- package/dist/data/memory/schema-ddl.d.ts +120 -1
- package/dist/data/memory/schema-ddl.d.ts.map +1 -1
- package/dist/data/memory/schema-ddl.js +171 -4
- package/dist/data/memory/schema-ddl.js.map +1 -1
- package/dist/data/memory/schema-guard.d.ts.map +1 -1
- package/dist/data/memory/schema-guard.js +5 -41
- package/dist/data/memory/schema-guard.js.map +1 -1
- package/dist/data/memory/schema.d.ts.map +1 -1
- package/dist/data/memory/schema.js +10 -34
- package/dist/data/memory/schema.js.map +1 -1
- package/dist/data/memory/semantic-notes.d.ts +13 -8
- package/dist/data/memory/semantic-notes.d.ts.map +1 -1
- package/dist/data/memory/semantic-notes.js +12 -17
- package/dist/data/memory/semantic-notes.js.map +1 -1
- package/dist/data/memory/thread-registry.d.ts +330 -15
- package/dist/data/memory/thread-registry.d.ts.map +1 -1
- package/dist/data/memory/thread-registry.js +523 -67
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/data/memory/utils.d.ts +6 -0
- package/dist/data/memory/utils.d.ts.map +1 -1
- package/dist/data/memory/utils.js +13 -0
- package/dist/data/memory/utils.js.map +1 -1
- package/dist/data/memory/worker-lifecycle.repository.d.ts +308 -0
- package/dist/data/memory/worker-lifecycle.repository.d.ts.map +1 -0
- package/dist/data/memory/worker-lifecycle.repository.js +428 -0
- package/dist/data/memory/worker-lifecycle.repository.js.map +1 -0
- package/dist/data/optional.d.ts +16 -0
- package/dist/data/optional.d.ts.map +1 -0
- package/dist/data/optional.js +47 -0
- package/dist/data/optional.js.map +1 -0
- package/dist/index.js +156 -24
- package/dist/index.js.map +1 -1
- package/dist/integrations/openai/speech.d.ts.map +1 -1
- package/dist/integrations/openai/speech.js +52 -19
- package/dist/integrations/openai/speech.js.map +1 -1
- package/dist/integrations/openai/video.d.ts +1 -1
- package/dist/integrations/openai/video.d.ts.map +1 -1
- package/dist/integrations/openai/video.js +13 -8
- package/dist/integrations/openai/video.js.map +1 -1
- package/dist/integrations/telegram/types.d.ts +11 -0
- package/dist/integrations/telegram/types.d.ts.map +1 -1
- package/dist/lib/http-retry.d.ts +91 -0
- package/dist/lib/http-retry.d.ts.map +1 -0
- package/dist/lib/http-retry.js +177 -0
- package/dist/lib/http-retry.js.map +1 -0
- package/dist/lib/mcp-http-port.d.ts +12 -0
- package/dist/lib/mcp-http-port.d.ts.map +1 -0
- package/dist/lib/mcp-http-port.js +19 -0
- package/dist/lib/mcp-http-port.js.map +1 -0
- package/dist/lib/paths.d.ts +29 -4
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +31 -4
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/types.d.ts +2 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/usage-metering/pricing.js +1 -1
- package/dist/lib/usage-metering/pricing.js.map +1 -1
- package/dist/lib/usage-metering/sink.d.ts +4 -0
- package/dist/lib/usage-metering/sink.d.ts.map +1 -1
- package/dist/lib/usage-metering/sink.js +6 -4
- package/dist/lib/usage-metering/sink.js.map +1 -1
- package/dist/lib/utils.d.ts +31 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +49 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/llm/prompts/narrative.d.ts.map +1 -1
- package/dist/llm/prompts/narrative.js +27 -86
- package/dist/llm/prompts/narrative.js.map +1 -1
- package/dist/log-parsing/log-events.d.ts +38 -0
- package/dist/log-parsing/log-events.d.ts.map +1 -0
- package/dist/log-parsing/log-events.js +2 -0
- package/dist/log-parsing/log-events.js.map +1 -0
- package/dist/log-parsing/parser-registry.d.ts +4 -0
- package/dist/log-parsing/parser-registry.d.ts.map +1 -0
- package/dist/log-parsing/parser-registry.js +18 -0
- package/dist/log-parsing/parser-registry.js.map +1 -0
- package/dist/log-parsing/parsers/claude.d.ts +6 -0
- package/dist/log-parsing/parsers/claude.d.ts.map +1 -0
- package/dist/log-parsing/parsers/claude.js +100 -0
- package/dist/log-parsing/parsers/claude.js.map +1 -0
- package/dist/log-parsing/parsers/codex.d.ts +6 -0
- package/dist/log-parsing/parsers/codex.d.ts.map +1 -0
- package/dist/log-parsing/parsers/codex.js +116 -0
- package/dist/log-parsing/parsers/codex.js.map +1 -0
- package/dist/log-parsing/parsers/copilot.d.ts +6 -0
- package/dist/log-parsing/parsers/copilot.d.ts.map +1 -0
- package/dist/log-parsing/parsers/copilot.js +65 -0
- package/dist/log-parsing/parsers/copilot.js.map +1 -0
- package/dist/log-parsing/parsers/json-lines.d.ts +9 -0
- package/dist/log-parsing/parsers/json-lines.d.ts.map +1 -0
- package/dist/log-parsing/parsers/json-lines.js +25 -0
- package/dist/log-parsing/parsers/json-lines.js.map +1 -0
- package/dist/log-parsing/render.d.ts +33 -0
- package/dist/log-parsing/render.d.ts.map +1 -0
- package/dist/log-parsing/render.js +113 -0
- package/dist/log-parsing/render.js.map +1 -0
- package/dist/log-parsing/text.d.ts +8 -0
- package/dist/log-parsing/text.d.ts.map +1 -0
- package/dist/log-parsing/text.js +20 -0
- package/dist/log-parsing/text.js.map +1 -0
- package/dist/server/http-server.d.ts +8 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +41 -19
- package/dist/server/http-server.js.map +1 -1
- package/dist/server/port-holder.d.ts +94 -0
- package/dist/server/port-holder.d.ts.map +1 -0
- package/dist/server/port-holder.js +122 -0
- package/dist/server/port-holder.js.map +1 -0
- package/dist/services/agent-spawn.service.d.ts +50 -5
- package/dist/services/agent-spawn.service.d.ts.map +1 -1
- package/dist/services/agent-spawn.service.js +59 -66
- package/dist/services/agent-spawn.service.js.map +1 -1
- package/dist/services/background-runner.d.ts +0 -1
- package/dist/services/background-runner.d.ts.map +1 -1
- package/dist/services/background-runner.js +0 -58
- package/dist/services/background-runner.js.map +1 -1
- package/dist/services/board/board-signals.d.ts +45 -0
- package/dist/services/board/board-signals.d.ts.map +1 -0
- package/dist/services/board/board-signals.js +170 -0
- package/dist/services/board/board-signals.js.map +1 -0
- package/dist/services/board/card-briefing.d.ts +24 -0
- package/dist/services/board/card-briefing.d.ts.map +1 -0
- package/dist/services/board/card-briefing.js +132 -0
- package/dist/services/board/card-briefing.js.map +1 -0
- package/dist/services/board/card-diagnostics.d.ts +25 -0
- package/dist/services/board/card-diagnostics.d.ts.map +1 -0
- package/dist/services/board/card-diagnostics.js +50 -0
- package/dist/services/board/card-diagnostics.js.map +1 -0
- package/dist/services/board/live-root-thread.d.ts +8 -0
- package/dist/services/board/live-root-thread.d.ts.map +1 -0
- package/dist/services/board/live-root-thread.js +2 -0
- package/dist/services/board/live-root-thread.js.map +1 -0
- package/dist/services/board/orchestrator.service.d.ts +119 -0
- package/dist/services/board/orchestrator.service.d.ts.map +1 -0
- package/dist/services/board/orchestrator.service.js +387 -0
- package/dist/services/board/orchestrator.service.js.map +1 -0
- package/dist/services/board/release-worker.d.ts +43 -0
- package/dist/services/board/release-worker.d.ts.map +1 -0
- package/dist/services/board/release-worker.js +96 -0
- package/dist/services/board/release-worker.js.map +1 -0
- package/dist/services/board/report-capture.d.ts +94 -0
- package/dist/services/board/report-capture.d.ts.map +1 -0
- package/dist/services/board/report-capture.js +398 -0
- package/dist/services/board/report-capture.js.map +1 -0
- package/dist/services/board/worker-spawn.d.ts +89 -0
- package/dist/services/board/worker-spawn.d.ts.map +1 -0
- package/dist/services/board/worker-spawn.js +177 -0
- package/dist/services/board/worker-spawn.js.map +1 -0
- package/dist/services/board/worktree.d.ts +45 -0
- package/dist/services/board/worktree.d.ts.map +1 -0
- package/dist/services/board/worktree.js +183 -0
- package/dist/services/board/worktree.js.map +1 -0
- package/dist/services/broker-client.d.ts +84 -2
- package/dist/services/broker-client.d.ts.map +1 -1
- package/dist/services/broker-client.js +72 -6
- package/dist/services/broker-client.js.map +1 -1
- package/dist/services/claude-spawn.service.d.ts +5 -0
- package/dist/services/claude-spawn.service.d.ts.map +1 -1
- package/dist/services/claude-spawn.service.js +37 -21
- package/dist/services/claude-spawn.service.js.map +1 -1
- package/dist/services/codex-spawn.service.d.ts +8 -3
- package/dist/services/codex-spawn.service.d.ts.map +1 -1
- package/dist/services/codex-spawn.service.js +84 -67
- package/dist/services/codex-spawn.service.js.map +1 -1
- package/dist/services/consolidation.service.d.ts.map +1 -1
- package/dist/services/consolidation.service.js +5 -49
- package/dist/services/consolidation.service.js.map +1 -1
- package/dist/services/copilot-spawn.service.d.ts +1 -1
- package/dist/services/copilot-spawn.service.d.ts.map +1 -1
- package/dist/services/copilot-spawn.service.js +10 -5
- package/dist/services/copilot-spawn.service.js.map +1 -1
- package/dist/services/daily-session.d.ts +24 -11
- package/dist/services/daily-session.d.ts.map +1 -1
- package/dist/services/daily-session.js +113 -33
- package/dist/services/daily-session.js.map +1 -1
- package/dist/services/death-alert.service.d.ts +55 -0
- package/dist/services/death-alert.service.d.ts.map +1 -0
- package/dist/services/death-alert.service.js +64 -0
- package/dist/services/death-alert.service.js.map +1 -0
- package/dist/services/dispatcher/broker.d.ts +66 -0
- package/dist/services/dispatcher/broker.d.ts.map +1 -1
- package/dist/services/dispatcher/broker.js +60 -52
- package/dist/services/dispatcher/broker.js.map +1 -1
- package/dist/services/dispatcher/poller.d.ts.map +1 -1
- package/dist/services/dispatcher/poller.js +31 -24
- package/dist/services/dispatcher/poller.js.map +1 -1
- package/dist/services/http-retry.d.ts +1 -90
- package/dist/services/http-retry.d.ts.map +1 -1
- package/dist/services/http-retry.js +1 -176
- package/dist/services/http-retry.js.map +1 -1
- package/dist/services/intent.d.ts +15 -1
- package/dist/services/intent.d.ts.map +1 -1
- package/dist/services/intent.js +39 -27
- package/dist/services/intent.js.map +1 -1
- package/dist/services/keeper.service.d.ts +76 -3
- package/dist/services/keeper.service.d.ts.map +1 -1
- package/dist/services/keeper.service.js +112 -35
- package/dist/services/keeper.service.js.map +1 -1
- package/dist/services/mcp-config.service.d.ts.map +1 -1
- package/dist/services/mcp-config.service.js +14 -1
- package/dist/services/mcp-config.service.js.map +1 -1
- package/dist/services/memory-briefing.service.d.ts +1 -1
- package/dist/services/memory-briefing.service.d.ts.map +1 -1
- package/dist/services/memory-briefing.service.js +28 -73
- package/dist/services/memory-briefing.service.js.map +1 -1
- package/dist/services/passive-notice.service.d.ts +56 -0
- package/dist/services/passive-notice.service.d.ts.map +1 -0
- package/dist/services/passive-notice.service.js +92 -0
- package/dist/services/passive-notice.service.js.map +1 -0
- package/dist/services/predefined-prompts.d.ts +11 -0
- package/dist/services/predefined-prompts.d.ts.map +1 -0
- package/dist/services/predefined-prompts.js +25 -0
- package/dist/services/predefined-prompts.js.map +1 -0
- package/dist/services/process.service.d.ts +111 -27
- package/dist/services/process.service.d.ts.map +1 -1
- package/dist/services/process.service.js +245 -173
- package/dist/services/process.service.js.map +1 -1
- package/dist/services/spawn-common.d.ts +281 -5
- package/dist/services/spawn-common.d.ts.map +1 -1
- package/dist/services/spawn-common.js +884 -188
- package/dist/services/spawn-common.js.map +1 -1
- package/dist/services/spawn-exit-watcher.d.ts +45 -35
- package/dist/services/spawn-exit-watcher.d.ts.map +1 -1
- package/dist/services/spawn-exit-watcher.js +120 -100
- package/dist/services/spawn-exit-watcher.js.map +1 -1
- package/dist/services/telegram.d.ts +31 -8
- package/dist/services/telegram.d.ts.map +1 -1
- package/dist/services/telegram.js +58 -26
- package/dist/services/telegram.js.map +1 -1
- package/dist/services/thread-health.service.d.ts +8 -0
- package/dist/services/thread-health.service.d.ts.map +1 -1
- package/dist/services/thread-health.service.js +14 -10
- package/dist/services/thread-health.service.js.map +1 -1
- package/dist/services/thread-lifecycle.service.d.ts +17 -1
- package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
- package/dist/services/thread-lifecycle.service.js +47 -6
- package/dist/services/thread-lifecycle.service.js.map +1 -1
- package/dist/services/thread-log-reader.d.ts +81 -0
- package/dist/services/thread-log-reader.d.ts.map +1 -0
- package/dist/services/thread-log-reader.js +141 -0
- package/dist/services/thread-log-reader.js.map +1 -0
- package/dist/services/thread-purge.service.d.ts +200 -0
- package/dist/services/thread-purge.service.d.ts.map +1 -0
- package/dist/services/thread-purge.service.js +644 -0
- package/dist/services/thread-purge.service.js.map +1 -0
- package/dist/services/topic.service.d.ts +44 -2
- package/dist/services/topic.service.d.ts.map +1 -1
- package/dist/services/topic.service.js +74 -13
- package/dist/services/topic.service.js.map +1 -1
- package/dist/services/usage/usage-inbox-notifier.d.ts +50 -0
- package/dist/services/usage/usage-inbox-notifier.d.ts.map +1 -0
- package/dist/services/usage/usage-inbox-notifier.js +118 -0
- package/dist/services/usage/usage-inbox-notifier.js.map +1 -0
- package/dist/services/usage/usage-poller.service.d.ts +41 -0
- package/dist/services/usage/usage-poller.service.d.ts.map +1 -0
- package/dist/services/usage/usage-poller.service.js +67 -0
- package/dist/services/usage/usage-poller.service.js.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts +40 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.js +89 -0
- package/dist/services/usage/usage-snapshot-provider.js.map +1 -0
- package/dist/services/usage/usage-types.d.ts +28 -0
- package/dist/services/usage/usage-types.d.ts.map +1 -0
- package/dist/services/usage/usage-types.js +14 -0
- package/dist/services/usage/usage-types.js.map +1 -0
- package/dist/services/worker-birth.d.ts +154 -0
- package/dist/services/worker-birth.d.ts.map +1 -0
- package/dist/services/worker-birth.js +274 -0
- package/dist/services/worker-birth.js.map +1 -0
- package/dist/services/worker-cleanup.service.d.ts +242 -19
- package/dist/services/worker-cleanup.service.d.ts.map +1 -1
- package/dist/services/worker-cleanup.service.js +893 -355
- package/dist/services/worker-cleanup.service.js.map +1 -1
- package/dist/services/worker-lifecycle-executor.d.ts +42 -0
- package/dist/services/worker-lifecycle-executor.d.ts.map +1 -0
- package/dist/services/worker-lifecycle-executor.js +63 -0
- package/dist/services/worker-lifecycle-executor.js.map +1 -0
- package/dist/services/worker-single-use.d.ts +92 -0
- package/dist/services/worker-single-use.d.ts.map +1 -0
- package/dist/services/worker-single-use.js +155 -0
- package/dist/services/worker-single-use.js.map +1 -0
- package/dist/sessions/mcp-registry.d.ts +33 -2
- package/dist/sessions/mcp-registry.d.ts.map +1 -1
- package/dist/sessions/mcp-registry.js +153 -30
- package/dist/sessions/mcp-registry.js.map +1 -1
- package/dist/test-bootstrap.d.ts +19 -12
- package/dist/test-bootstrap.d.ts.map +1 -1
- package/dist/test-bootstrap.js +69 -21
- package/dist/test-bootstrap.js.map +1 -1
- package/dist/test-tripwire.test-support.d.ts +75 -0
- package/dist/test-tripwire.test-support.d.ts.map +1 -0
- package/dist/test-tripwire.test-support.js +353 -0
- package/dist/test-tripwire.test-support.js.map +1 -0
- package/dist/tools/defs/memory-defs.d.ts.map +1 -1
- package/dist/tools/defs/memory-defs.js +12 -4
- package/dist/tools/defs/memory-defs.js.map +1 -1
- package/dist/tools/defs/session-defs.d.ts.map +1 -1
- package/dist/tools/defs/session-defs.js +26 -10
- package/dist/tools/defs/session-defs.js.map +1 -1
- package/dist/tools/defs/utility-defs.js +1 -1
- package/dist/tools/defs/utility-defs.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts +81 -1
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +840 -219
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory-tools.js +66 -9
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/response-builders.d.ts.map +1 -1
- package/dist/tools/response-builders.js +12 -8
- package/dist/tools/response-builders.js.map +1 -1
- package/dist/tools/session-tools.d.ts.map +1 -1
- package/dist/tools/session-tools.js +3 -32
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/skill-tools.js +1 -1
- package/dist/tools/skill-tools.js.map +1 -1
- package/dist/tools/start-session-tool.d.ts.map +1 -1
- package/dist/tools/start-session-tool.js +66 -20
- package/dist/tools/start-session-tool.js.map +1 -1
- package/dist/tools/utility-tools.d.ts.map +1 -1
- package/dist/tools/utility-tools.js +38 -3
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait/auto-forward.d.ts.map +1 -1
- package/dist/tools/wait/auto-forward.js +8 -3
- package/dist/tools/wait/auto-forward.js.map +1 -1
- package/dist/tools/wait/consolidation-strategy.d.ts +42 -0
- package/dist/tools/wait/consolidation-strategy.d.ts.map +1 -0
- package/dist/tools/wait/consolidation-strategy.js +50 -0
- package/dist/tools/wait/consolidation-strategy.js.map +1 -0
- package/dist/tools/wait/drive-handler.d.ts +5 -7
- package/dist/tools/wait/drive-handler.d.ts.map +1 -1
- package/dist/tools/wait/drive-handler.js +45 -59
- package/dist/tools/wait/drive-handler.js.map +1 -1
- package/dist/tools/wait/media-processor.d.ts.map +1 -1
- package/dist/tools/wait/media-processor.js +8 -4
- package/dist/tools/wait/media-processor.js.map +1 -1
- package/dist/tools/wait/message-delivery.d.ts +9 -6
- package/dist/tools/wait/message-delivery.d.ts.map +1 -1
- package/dist/tools/wait/message-delivery.js +77 -58
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/dist/tools/wait/message-processing.d.ts.map +1 -1
- package/dist/tools/wait/message-processing.js +2 -1
- package/dist/tools/wait/message-processing.js.map +1 -1
- package/dist/tools/wait/poll-loop.d.ts.map +1 -1
- package/dist/tools/wait/poll-loop.js +339 -239
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/package.json +4 -3
- package/templates/azure-devops-securevault.default.md +20 -6
- package/templates/board-quality-checklist.default.md +121 -0
- package/templates/buildless-vue-preview.default.md +47 -0
- package/templates/expert-code-review.default.md +12 -0
- package/templates/handoff.default.md +41 -18
- package/templates/increment-pr-pipeline.default.md +79 -0
- package/templates/swarm.default.md +1 -0
- package/templates/worker-autonomous.default.md +1 -0
- package/templates/worker-delegate.default.md +1 -0
- package/dist/dashboard/log-parser.d.ts +0 -65
- package/dist/dashboard/log-parser.d.ts.map +0 -1
- package/dist/dashboard/log-parser.js +0 -219
- package/dist/dashboard/log-parser.js.map +0 -1
- package/dist/data/memory/reflection-dedup.d.ts +0 -17
- package/dist/data/memory/reflection-dedup.d.ts.map +0 -1
- package/dist/data/memory/reflection-dedup.js +0 -55
- package/dist/data/memory/reflection-dedup.js.map +0 -1
- package/dist/data/memory/reflection-gates.d.ts +0 -40
- package/dist/data/memory/reflection-gates.d.ts.map +0 -1
- package/dist/data/memory/reflection-gates.js +0 -220
- package/dist/data/memory/reflection-gates.js.map +0 -1
- package/dist/data/memory/reflection-sources.d.ts +0 -13
- package/dist/data/memory/reflection-sources.d.ts.map +0 -1
- package/dist/data/memory/reflection-sources.js +0 -115
- package/dist/data/memory/reflection-sources.js.map +0 -1
- package/dist/data/memory/reflection.d.ts +0 -43
- package/dist/data/memory/reflection.d.ts.map +0 -1
- package/dist/data/memory/reflection.js +0 -329
- package/dist/data/memory/reflection.js.map +0 -1
- package/dist/llm/prompts/reflection.d.ts +0 -6
- package/dist/llm/prompts/reflection.d.ts.map +0 -1
- package/dist/llm/prompts/reflection.js +0 -77
- package/dist/llm/prompts/reflection.js.map +0 -1
- package/dist/services/memory-pruning.service.d.ts +0 -12
- package/dist/services/memory-pruning.service.d.ts.map +0 -1
- package/dist/services/memory-pruning.service.js +0 -179
- package/dist/services/memory-pruning.service.js.map +0 -1
- package/templates/daily-review.default.md +0 -26
- package/templates/fire-and-forget.default.md +0 -76
- package/templates/offload.default.md +0 -33
- package/templates/sensorium-repair.default.md +0 -114
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test, { type TestContext } from "node:test";
|
|
3
|
+
|
|
4
|
+
import type { ExecutionProfile, NamedProfile } from "../api/contract.js";
|
|
5
|
+
import { evaluateField, profileFromHow, slugifyProfileName, useBuilder } from "./useBuilder.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A single-slot fake for the debounce timer: setTimeout stores the pending
|
|
9
|
+
* callback, clearTimeout drops it, and fire() runs it once (one-shot, like a
|
|
10
|
+
* real timeout). A rescheduled debounce clears the previous slot first, so at
|
|
11
|
+
* most one callback is ever pending — exactly what the composable relies on.
|
|
12
|
+
*/
|
|
13
|
+
function fakeTimers() {
|
|
14
|
+
let pending: { id: number; cb: () => void } | undefined;
|
|
15
|
+
let nextId = 1;
|
|
16
|
+
return {
|
|
17
|
+
setTimeout: (cb: () => void) => {
|
|
18
|
+
const id = nextId++;
|
|
19
|
+
pending = { id, cb };
|
|
20
|
+
return id;
|
|
21
|
+
},
|
|
22
|
+
clearTimeout: (id: number) => {
|
|
23
|
+
if (pending && pending.id === id) pending = undefined;
|
|
24
|
+
},
|
|
25
|
+
fire() {
|
|
26
|
+
if (!pending) throw new Error("no pending debounce timer to fire");
|
|
27
|
+
const { cb } = pending;
|
|
28
|
+
pending = undefined;
|
|
29
|
+
cb();
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type PreviewOutcome = string | Promise<string> | Error;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A programmable previewBriefing stub that replays an ordered list of outcomes —
|
|
38
|
+
* a briefing string, a pending promise (to control in-flight timing), or an
|
|
39
|
+
* Error to reject with — one per call, in call order. Lets a test arrange
|
|
40
|
+
* "in-flight then superseded" without hand-rolling a call counter in the body.
|
|
41
|
+
*/
|
|
42
|
+
function previewFeed(outcomes: PreviewOutcome[]) {
|
|
43
|
+
const queue = [...outcomes];
|
|
44
|
+
let calls = 0;
|
|
45
|
+
return {
|
|
46
|
+
api: {
|
|
47
|
+
previewBriefing: async () => {
|
|
48
|
+
calls += 1;
|
|
49
|
+
const outcome = queue.shift();
|
|
50
|
+
if (outcome === undefined) throw new Error("previewFeed ran out of scripted responses");
|
|
51
|
+
if (outcome instanceof Error) throw outcome;
|
|
52
|
+
return outcome;
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
get calls() {
|
|
56
|
+
return calls;
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A programmable saveProfile stub: it records every input it receives and replays
|
|
63
|
+
* a single scripted outcome — the saved NamedProfile to resolve with, or an Error
|
|
64
|
+
* to reject with. Lets a test assert the exact call shape (id/name/profile) or the
|
|
65
|
+
* failure path without a hand-rolled counter in the body.
|
|
66
|
+
*/
|
|
67
|
+
function saveFeed(outcome: NamedProfile | Error) {
|
|
68
|
+
const calls: Array<{ id: string; name: string; profile: ExecutionProfile }> = [];
|
|
69
|
+
return {
|
|
70
|
+
api: {
|
|
71
|
+
saveProfile: async (input: { id: string; name: string; profile: ExecutionProfile }) => {
|
|
72
|
+
calls.push(input);
|
|
73
|
+
if (outcome instanceof Error) throw outcome;
|
|
74
|
+
return outcome;
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
calls,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Build a directly-mounted builder store wired to the scripted save feed. The
|
|
83
|
+
* preview watcher is a live resource, so its teardown is registered here via
|
|
84
|
+
* t.after — the test body stays free of cleanup calls.
|
|
85
|
+
*/
|
|
86
|
+
function openSavingBuilder(t: TestContext, outcome: NamedProfile | Error) {
|
|
87
|
+
const feed = saveFeed(outcome);
|
|
88
|
+
const store = useBuilder({ api: feed.api, timers: fakeTimers() });
|
|
89
|
+
t.after(() => store.stopPreview());
|
|
90
|
+
return { store, feed };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function deferred() {
|
|
94
|
+
let resolve!: (value: string) => void;
|
|
95
|
+
const promise = new Promise<string>((done) => {
|
|
96
|
+
resolve = done;
|
|
97
|
+
});
|
|
98
|
+
return { promise, resolve };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function flush() {
|
|
102
|
+
return new Promise<void>((resolve) => setImmediate(resolve));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Build a directly-mounted builder store wired to the scripted preview feed and
|
|
107
|
+
* a fake debounce timer. Teardown (stop the watcher + pending timer) is
|
|
108
|
+
* registered here via t.after, so every test body stays free of cleanup calls.
|
|
109
|
+
*/
|
|
110
|
+
function openBuilder(t: TestContext, outcomes: PreviewOutcome[]) {
|
|
111
|
+
const timers = fakeTimers();
|
|
112
|
+
const feed = previewFeed(outcomes);
|
|
113
|
+
const store = useBuilder({ api: feed.api, timers });
|
|
114
|
+
t.after(() => store.stopPreview());
|
|
115
|
+
return { store, timers, feed };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
test("useBuilder load keys named profiles by id", async (t) => {
|
|
119
|
+
const store = useBuilder({
|
|
120
|
+
api: {
|
|
121
|
+
listLaneGroups: async () => [],
|
|
122
|
+
getProfiles: async () => [
|
|
123
|
+
{ id: "default", name: "Default", profile: { runTests: true }, builtin: true },
|
|
124
|
+
{ id: "research", name: "Research", profile: { runTests: false }, builtin: true },
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
timers: fakeTimers(),
|
|
128
|
+
});
|
|
129
|
+
t.after(() => store.stopPreview());
|
|
130
|
+
|
|
131
|
+
await store.load();
|
|
132
|
+
|
|
133
|
+
assert.deepEqual(store.profiles.value, {
|
|
134
|
+
default: { runTests: true },
|
|
135
|
+
research: { runTests: false },
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("useBuilder debounces rapid draft edits into a single preview compile", async (t) => {
|
|
140
|
+
// Three keystrokes before the debounce elapses must yield ONE endpoint call.
|
|
141
|
+
const { store, timers, feed } = openBuilder(t, ["briefing"]);
|
|
142
|
+
|
|
143
|
+
store.draft.title = "M";
|
|
144
|
+
await flush();
|
|
145
|
+
store.draft.title = "Mi";
|
|
146
|
+
await flush();
|
|
147
|
+
store.draft.title = "Migrate";
|
|
148
|
+
await flush();
|
|
149
|
+
timers.fire();
|
|
150
|
+
await flush();
|
|
151
|
+
|
|
152
|
+
assert.equal(feed.calls, 1);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("useBuilder exposes the compiled briefing as preview.text", async (t) => {
|
|
156
|
+
const { store, timers } = openBuilder(t, ["# Task Board card (preview): Migrate auth"]);
|
|
157
|
+
|
|
158
|
+
store.draft.title = "Migrate auth";
|
|
159
|
+
await flush();
|
|
160
|
+
timers.fire();
|
|
161
|
+
await flush();
|
|
162
|
+
|
|
163
|
+
assert.equal(store.preview.text, "# Task Board card (preview): Migrate auth");
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("useBuilder raises preview.loading while a compile is in flight", async (t) => {
|
|
167
|
+
const inFlight = deferred();
|
|
168
|
+
const { store, timers } = openBuilder(t, [inFlight.promise]);
|
|
169
|
+
|
|
170
|
+
store.draft.title = "x";
|
|
171
|
+
await flush();
|
|
172
|
+
timers.fire();
|
|
173
|
+
await flush();
|
|
174
|
+
|
|
175
|
+
assert.equal(store.preview.loading, true);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("useBuilder lowers preview.loading once the compile settles", async (t) => {
|
|
179
|
+
const inFlight = deferred();
|
|
180
|
+
const { store, timers } = openBuilder(t, [inFlight.promise]);
|
|
181
|
+
store.draft.title = "x";
|
|
182
|
+
await flush();
|
|
183
|
+
timers.fire();
|
|
184
|
+
await flush();
|
|
185
|
+
|
|
186
|
+
inFlight.resolve("done");
|
|
187
|
+
await flush();
|
|
188
|
+
|
|
189
|
+
assert.equal(store.preview.loading, false);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("useBuilder surfaces a failed compile as preview.error", async (t) => {
|
|
193
|
+
const { store, timers } = openBuilder(t, [new Error("preview offline")]);
|
|
194
|
+
|
|
195
|
+
store.draft.title = "x";
|
|
196
|
+
await flush();
|
|
197
|
+
timers.fire();
|
|
198
|
+
await flush();
|
|
199
|
+
|
|
200
|
+
assert.equal(store.preview.error, "preview offline");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("useBuilder ignores a stale compile that resolves after a newer draft", async (t) => {
|
|
204
|
+
// The first (slow) compile must not overwrite the newer draft's briefing.
|
|
205
|
+
const stale = deferred();
|
|
206
|
+
const { store, timers } = openBuilder(t, [stale.promise, "fresh-briefing"]);
|
|
207
|
+
store.draft.title = "v1";
|
|
208
|
+
await flush();
|
|
209
|
+
timers.fire(); // gen 1 — left in flight on stale.promise
|
|
210
|
+
await flush();
|
|
211
|
+
store.draft.title = "v2";
|
|
212
|
+
await flush();
|
|
213
|
+
timers.fire(); // gen 2 — resolves immediately with "fresh-briefing"
|
|
214
|
+
await flush();
|
|
215
|
+
|
|
216
|
+
stale.resolve("stale-briefing"); // late, superseded
|
|
217
|
+
await flush();
|
|
218
|
+
|
|
219
|
+
assert.equal(store.preview.text, "fresh-briefing");
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test("profileFromHow maps the verifyDone toggle into the profile", () => {
|
|
223
|
+
const profile = profileFromHow({ verifyDone: true });
|
|
224
|
+
|
|
225
|
+
assert.equal(profile.verifyDone, true);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("profileFromHow keeps the model alias when its showWhen holds (provider Claude)", () => {
|
|
229
|
+
const fields = [{ key: "model", showWhen: { key: "provider", equals: "Claude" } }];
|
|
230
|
+
|
|
231
|
+
const profile = profileFromHow({ provider: "Claude", model: " claude-opus-4-8 " }, fields);
|
|
232
|
+
|
|
233
|
+
assert.equal(profile.model, "claude-opus-4-8");
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("profileFromHow drops the model alias when its showWhen is unmet (provider not Claude)", () => {
|
|
237
|
+
// The model field's showWhen hides it off Claude, so a leftover alias from
|
|
238
|
+
// before a provider switch is never persisted for Copilot/Codex.
|
|
239
|
+
const fields = [{ key: "model", showWhen: { key: "provider", equals: "Claude" } }];
|
|
240
|
+
|
|
241
|
+
const profile = profileFromHow({ provider: "Copilot", model: "claude-opus-4.8" }, fields);
|
|
242
|
+
|
|
243
|
+
assert.ok(!("model" in profile));
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("profileFromHow skips any control whose field is hidden by showWhen, keyed off the field key", () => {
|
|
247
|
+
// Generic, not model-specific: worktree is dropped purely because its own
|
|
248
|
+
// showWhen is unmet — the engine never special-cases a field key.
|
|
249
|
+
const fields = [{ key: "worktree", showWhen: { key: "autonomy", equals: "Collaborative" } }];
|
|
250
|
+
|
|
251
|
+
const profile = profileFromHow({ worktree: true, autonomy: "Autonomous" }, fields);
|
|
252
|
+
|
|
253
|
+
assert.ok(!("worktree" in profile));
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("profileFromHow with no schema fields imposes no constraints and persists every control", () => {
|
|
257
|
+
const profile = profileFromHow({ provider: "Copilot", model: "gpt-5.2", worktree: true }, []);
|
|
258
|
+
|
|
259
|
+
assert.deepEqual(profile, { agentType: "copilot", model: "gpt-5.2", worktree: true });
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("profileFromHow maps Ephemeral memory to just its mode", () => {
|
|
263
|
+
const profile = profileFromHow({ memory: { mode: "Ephemeral", threadId: null } });
|
|
264
|
+
|
|
265
|
+
assert.deepEqual(profile.memory, { mode: "Ephemeral" });
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("profileFromHow strips the transient auto/_id keys from mapped phases", () => {
|
|
269
|
+
const profile = profileFromHow({
|
|
270
|
+
phases: [
|
|
271
|
+
{ name: "Plan", review: true, provider: "Inherit", model: "", auto: false, _id: "ph1" },
|
|
272
|
+
],
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
assert.deepEqual(profile.phases, [
|
|
276
|
+
{ name: "Plan", review: true, provider: "Inherit", model: "" },
|
|
277
|
+
]);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("profileFromHow drops the synthetic auto Review row the widget inserts for display", () => {
|
|
281
|
+
// Toggling review inserts a visual-only {name:"Review", auto:true} row after the
|
|
282
|
+
// parent; it must never persist — the parent's review:true already encodes it.
|
|
283
|
+
const profile = profileFromHow({
|
|
284
|
+
phases: [
|
|
285
|
+
{ name: "Plan", review: true, provider: "Inherit", model: "" },
|
|
286
|
+
{ name: "Review", review: false, provider: "Inherit", model: "", auto: true },
|
|
287
|
+
],
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
assert.deepEqual(profile.phases, [
|
|
291
|
+
{ name: "Plan", review: true, provider: "Inherit", model: "" },
|
|
292
|
+
]);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("profileFromHow drops a half-added phase row whose name is blank", () => {
|
|
296
|
+
const profile = profileFromHow({
|
|
297
|
+
phases: [
|
|
298
|
+
{ name: "Implement", review: false, provider: "Claude", model: "" },
|
|
299
|
+
{ name: " ", review: false, provider: "Inherit", model: "" },
|
|
300
|
+
],
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
assert.deepEqual(profile.phases, [
|
|
304
|
+
{ name: "Implement", review: false, provider: "Claude", model: "" },
|
|
305
|
+
]);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
test("profileFromHow omits phases entirely when every row is blank", () => {
|
|
309
|
+
const profile = profileFromHow({
|
|
310
|
+
phases: [{ name: "", review: false, provider: "Inherit", model: "" }],
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
assert.ok(!("phases" in profile));
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
test("evaluateField shows a field with no constraints and leaves it enabled", () => {
|
|
317
|
+
const result = evaluateField({}, {});
|
|
318
|
+
|
|
319
|
+
assert.deepEqual(result, { visible: true, disabled: false, reason: "" });
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test("evaluateField hides a field whose showWhen equals condition is unmet", () => {
|
|
323
|
+
const field = { showWhen: { key: "provider", equals: "Claude" } };
|
|
324
|
+
|
|
325
|
+
const result = evaluateField(field, { provider: "Copilot" });
|
|
326
|
+
|
|
327
|
+
assert.equal(result.visible, false);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test("evaluateField shows a field whose showWhen equals condition holds", () => {
|
|
331
|
+
const field = { showWhen: { key: "provider", equals: "Claude" } };
|
|
332
|
+
|
|
333
|
+
const result = evaluateField(field, { provider: "Claude" });
|
|
334
|
+
|
|
335
|
+
assert.equal(result.visible, true);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("evaluateField requires every condition of an AND-array showWhen to hold", () => {
|
|
339
|
+
const field = {
|
|
340
|
+
showWhen: [
|
|
341
|
+
{ key: "provider", equals: "Claude" },
|
|
342
|
+
{ key: "openPr", equals: true },
|
|
343
|
+
],
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const result = evaluateField(field, { provider: "Claude", openPr: false });
|
|
347
|
+
|
|
348
|
+
assert.equal(result.visible, false);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("evaluateField shows a field when every condition of an AND-array showWhen holds", () => {
|
|
352
|
+
const field = {
|
|
353
|
+
showWhen: [
|
|
354
|
+
{ key: "provider", equals: "Claude" },
|
|
355
|
+
{ key: "openPr", equals: true },
|
|
356
|
+
],
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const result = evaluateField(field, { provider: "Claude", openPr: true });
|
|
360
|
+
|
|
361
|
+
assert.equal(result.visible, true);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("evaluateField matches a showWhen `in` condition when the value is one of the options", () => {
|
|
365
|
+
const field = { showWhen: { key: "provider", in: ["Claude", "Codex"] } };
|
|
366
|
+
|
|
367
|
+
const result = evaluateField(field, { provider: "Codex" });
|
|
368
|
+
|
|
369
|
+
assert.equal(result.visible, true);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test("evaluateField fails a showWhen `in` condition when the value is not among the options", () => {
|
|
373
|
+
const field = { showWhen: { key: "provider", in: ["Claude", "Codex"] } };
|
|
374
|
+
|
|
375
|
+
const result = evaluateField(field, { provider: "Copilot" });
|
|
376
|
+
|
|
377
|
+
assert.equal(result.visible, false);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test("evaluateField honors a legacy visibleIf as showWhen", () => {
|
|
381
|
+
const field = { visibleIf: { key: "provider", equals: "Claude" } };
|
|
382
|
+
|
|
383
|
+
const result = evaluateField(field, { provider: "Copilot" });
|
|
384
|
+
|
|
385
|
+
assert.equal(result.visible, false);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
test("evaluateField disables a visible field when a requires condition is unmet", () => {
|
|
389
|
+
const field = { requires: { key: "openPr", equals: true } };
|
|
390
|
+
|
|
391
|
+
const result = evaluateField(field, { openPr: false });
|
|
392
|
+
|
|
393
|
+
assert.deepEqual(result, { visible: true, disabled: true, reason: "Requires openPr = true" });
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test("evaluateField enables a field when its requires condition holds", () => {
|
|
397
|
+
const field = { requires: { key: "openPr", equals: true } };
|
|
398
|
+
|
|
399
|
+
const result = evaluateField(field, { openPr: true });
|
|
400
|
+
|
|
401
|
+
assert.equal(result.disabled, false);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test("evaluateField disables a visible field when a conflicts condition holds", () => {
|
|
405
|
+
const field = { conflicts: { key: "worktree", equals: true } };
|
|
406
|
+
|
|
407
|
+
const result = evaluateField(field, { worktree: true });
|
|
408
|
+
|
|
409
|
+
assert.deepEqual(result, {
|
|
410
|
+
visible: true,
|
|
411
|
+
disabled: true,
|
|
412
|
+
reason: "Conflicts with worktree = true",
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
test("slugifyProfileName kebab-cases a name: lowercase, non-alphanumerics to single dashes, trimmed", () => {
|
|
417
|
+
assert.equal(slugifyProfileName("Nightly CI"), "nightly-ci");
|
|
418
|
+
assert.equal(slugifyProfileName(" Bug + Fix!! "), "bug-fix");
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test("useBuilder.saveProfile sends the slugified id, trimmed name and profileFromHow profile", async (t) => {
|
|
422
|
+
const saved: NamedProfile = {
|
|
423
|
+
id: "nightly-ci",
|
|
424
|
+
name: "Nightly CI",
|
|
425
|
+
profile: { verifyDone: true },
|
|
426
|
+
builtin: false,
|
|
427
|
+
};
|
|
428
|
+
const { store, feed } = openSavingBuilder(t, saved);
|
|
429
|
+
|
|
430
|
+
await store.saveProfile(" Nightly CI ", { verifyDone: true });
|
|
431
|
+
|
|
432
|
+
assert.deepEqual(feed.calls, [
|
|
433
|
+
{ id: "nightly-ci", name: "Nightly CI", profile: { verifyDone: true } },
|
|
434
|
+
]);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
test("useBuilder.saveProfile on success records the saved name and merges the profile into profiles.value", async (t) => {
|
|
438
|
+
const saved: NamedProfile = {
|
|
439
|
+
id: "nightly-ci",
|
|
440
|
+
name: "Nightly CI",
|
|
441
|
+
profile: { verifyDone: true },
|
|
442
|
+
builtin: false,
|
|
443
|
+
};
|
|
444
|
+
const { store } = openSavingBuilder(t, saved);
|
|
445
|
+
|
|
446
|
+
await store.saveProfile("Nightly CI", { verifyDone: true });
|
|
447
|
+
|
|
448
|
+
assert.equal(store.profileSave.savedName, "Nightly CI");
|
|
449
|
+
assert.deepEqual(store.profiles.value["nightly-ci"], { verifyDone: true });
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
test("useBuilder.saveProfile surfaces a rejected save as an error and leaves the saved name empty", async (t) => {
|
|
453
|
+
const { store } = openSavingBuilder(t, new Error("A profile with this name already exists"));
|
|
454
|
+
|
|
455
|
+
await store.saveProfile("Nightly CI", { verifyDone: true });
|
|
456
|
+
|
|
457
|
+
assert.equal(store.profileSave.error, "A profile with this name already exists");
|
|
458
|
+
assert.equal(store.profileSave.savedName, "");
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
test("useBuilder.saveProfile makes no api call for a blank name", async (t) => {
|
|
462
|
+
const saved: NamedProfile = { id: "x", name: "x", profile: {}, builtin: false };
|
|
463
|
+
const { store, feed } = openSavingBuilder(t, saved);
|
|
464
|
+
|
|
465
|
+
await store.saveProfile(" ", { verifyDone: true });
|
|
466
|
+
|
|
467
|
+
assert.equal(feed.calls.length, 0);
|
|
468
|
+
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-card store — card + comments + worker health/log, plus operator actions.
|
|
3
|
+
* FROZEN SEAM: P3 adds richer logs without changing existing return fields.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { onUnmounted, ref } from "../vendor/vue.esm-browser.js";
|
|
7
|
+
import { api } from "../api/api.js";
|
|
8
|
+
|
|
9
|
+
const LOG_POLL_INTERVAL_MS = 4000;
|
|
10
|
+
const LOG_VISIBLE_STATUSES = new Set(["in_progress", "decision_needed", "blocked", "rate_limited"]);
|
|
11
|
+
|
|
12
|
+
function logStatus(card, running) {
|
|
13
|
+
if (card?.status === "blocked") return "HALTED";
|
|
14
|
+
if (card?.status !== "in_progress") return "PAUSED";
|
|
15
|
+
return running === false ? "IDLE" : "LIVE";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function useCard(cardId, dependencies = {}) {
|
|
19
|
+
const id = Number(cardId);
|
|
20
|
+
const apiClient = dependencies.api || api;
|
|
21
|
+
const pollIntervalMs = dependencies.pollIntervalMs || LOG_POLL_INTERVAL_MS;
|
|
22
|
+
const timers = dependencies.timers || globalThis;
|
|
23
|
+
const card = ref(null);
|
|
24
|
+
const comments = ref([]);
|
|
25
|
+
const running = ref(null);
|
|
26
|
+
const loading = ref(false);
|
|
27
|
+
const error = ref(null);
|
|
28
|
+
// The answer the operator just submitted. Survives the card resuming to
|
|
29
|
+
// backlog so the view can show an in-place "answer saved" confirmation; a
|
|
30
|
+
// fresh load() (reopening the card, or any other action) clears it.
|
|
31
|
+
const submittedDecision = ref(null);
|
|
32
|
+
const log = ref({ text: "", nextOffset: 0, hasMore: false, status: "PAUSED" });
|
|
33
|
+
const logView = ref("assistant");
|
|
34
|
+
// Real fetch state for the designed loading/error/last-updated cues. These are
|
|
35
|
+
// ADDITIVE seam fields (P3): the existing `log` shape is unchanged.
|
|
36
|
+
const logLoading = ref(false);
|
|
37
|
+
const logError = ref(null);
|
|
38
|
+
const lastUpdated = ref(null);
|
|
39
|
+
let logTimer = null;
|
|
40
|
+
let logGen = 0;
|
|
41
|
+
let loadingOlder = false;
|
|
42
|
+
let newestLog = { text: "", nextOffset: 0, hasMore: false };
|
|
43
|
+
let olderLogs = [];
|
|
44
|
+
|
|
45
|
+
function canPollLogs() {
|
|
46
|
+
return !!(card.value && LOG_VISIBLE_STATUSES.has(card.value.status) && card.value.workerThreadId != null);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function syncLog() {
|
|
50
|
+
const lastOlderLog = olderLogs.at(-1);
|
|
51
|
+
log.value = {
|
|
52
|
+
text: [newestLog.text, ...olderLogs.map((page) => page.text)].filter(Boolean).join("\n"),
|
|
53
|
+
nextOffset: lastOlderLog ? lastOlderLog.nextOffset : newestLog.nextOffset,
|
|
54
|
+
hasMore: lastOlderLog ? lastOlderLog.hasMore : newestLog.hasMore,
|
|
55
|
+
status: logStatus(card.value, running.value),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resetLogPages() {
|
|
60
|
+
newestLog = { text: "", nextOffset: 0, hasMore: false };
|
|
61
|
+
olderLogs = [];
|
|
62
|
+
syncLog();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// A response is stale once the view/thread/generation moved on while it was in
|
|
66
|
+
// flight; a stale response must never clobber newer state (log OR fetch flags).
|
|
67
|
+
function isStaleLog(gen, view, thread) {
|
|
68
|
+
return gen !== logGen || view !== logView.value || thread !== card.value?.workerThreadId;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// `silent` background polls refresh the log WITHOUT raising logLoading, so a
|
|
72
|
+
// live-but-empty log never blinks its "no output yet" panel to the loading
|
|
73
|
+
// skeleton every tick. Only foreground fetches (first load, view switch, retry)
|
|
74
|
+
// drive the loading state; logError/lastUpdated are still updated either way.
|
|
75
|
+
async function fetchLog(offset = 0, { silent = false } = {}) {
|
|
76
|
+
if (!canPollLogs()) return;
|
|
77
|
+
const gen = logGen;
|
|
78
|
+
const view = logView.value;
|
|
79
|
+
const thread = card.value.workerThreadId;
|
|
80
|
+
const isNewest = offset === 0;
|
|
81
|
+
const showLoading = isNewest && !silent;
|
|
82
|
+
if (showLoading) logLoading.value = true;
|
|
83
|
+
try {
|
|
84
|
+
const result = await apiClient.threadLogs(thread, { view, offset });
|
|
85
|
+
if (isStaleLog(gen, view, thread)) return;
|
|
86
|
+
if (isNewest) {
|
|
87
|
+
newestLog = result;
|
|
88
|
+
} else {
|
|
89
|
+
olderLogs.push(result);
|
|
90
|
+
}
|
|
91
|
+
syncLog();
|
|
92
|
+
logError.value = null;
|
|
93
|
+
lastUpdated.value = new Date().toISOString();
|
|
94
|
+
} catch (e) {
|
|
95
|
+
// Surface the failure instead of swallowing it, but keep the poll loop
|
|
96
|
+
// alive — the next tick may recover. A stale rejection is ignored.
|
|
97
|
+
if (isStaleLog(gen, view, thread)) return;
|
|
98
|
+
logError.value = (e && e.message) || String(e);
|
|
99
|
+
} finally {
|
|
100
|
+
if (showLoading && !isStaleLog(gen, view, thread)) logLoading.value = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function stopLogPolling() {
|
|
105
|
+
logGen += 1;
|
|
106
|
+
if (logTimer) timers.clearInterval(logTimer);
|
|
107
|
+
logTimer = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function startLogPolling() {
|
|
111
|
+
stopLogPolling();
|
|
112
|
+
if (!canPollLogs()) return;
|
|
113
|
+
// Foreground first fetch drives the loading skeleton; interval polls refresh
|
|
114
|
+
// silently so an empty log's panel never flashes back to the skeleton.
|
|
115
|
+
// fetchLog owns its own error handling now (it sets logError, never rejects),
|
|
116
|
+
// so callers no longer swallow failures blindly.
|
|
117
|
+
fetchLog();
|
|
118
|
+
logTimer = timers.setInterval(() => fetchLog(0, { silent: true }), pollIntervalMs);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Re-fetch the newest page for the current view after a failure. Bumps the
|
|
122
|
+
// generation so any in-flight (failing) poll can't clobber the retry result.
|
|
123
|
+
async function retryLog() {
|
|
124
|
+
logGen += 1;
|
|
125
|
+
await fetchLog();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function setLogView(view) {
|
|
129
|
+
logGen += 1;
|
|
130
|
+
logView.value = view === "full" ? "full" : "assistant";
|
|
131
|
+
resetLogPages();
|
|
132
|
+
await fetchLog();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function loadOlderLogs() {
|
|
136
|
+
if (loadingOlder || !log.value.hasMore) return;
|
|
137
|
+
loadingOlder = true;
|
|
138
|
+
try {
|
|
139
|
+
await fetchLog(log.value.nextOffset);
|
|
140
|
+
} finally {
|
|
141
|
+
loadingOlder = false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function load() {
|
|
146
|
+
logGen += 1;
|
|
147
|
+
stopLogPolling();
|
|
148
|
+
resetLogPages();
|
|
149
|
+
submittedDecision.value = null;
|
|
150
|
+
logError.value = null;
|
|
151
|
+
lastUpdated.value = null;
|
|
152
|
+
logLoading.value = false;
|
|
153
|
+
loading.value = true;
|
|
154
|
+
error.value = null;
|
|
155
|
+
try {
|
|
156
|
+
const detail = await apiClient.getCard(id);
|
|
157
|
+
card.value = detail.card;
|
|
158
|
+
comments.value = detail.comments;
|
|
159
|
+
if (detail.card.status === "in_progress" && detail.card.workerThreadId != null) {
|
|
160
|
+
running.value = await apiClient.threadRunning(detail.card.workerThreadId).catch(() => null);
|
|
161
|
+
} else {
|
|
162
|
+
running.value = null;
|
|
163
|
+
}
|
|
164
|
+
syncLog();
|
|
165
|
+
startLogPolling();
|
|
166
|
+
} catch (e) {
|
|
167
|
+
error.value = (e && e.message) || String(e);
|
|
168
|
+
} finally {
|
|
169
|
+
loading.value = false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const actions = {
|
|
174
|
+
reload: load,
|
|
175
|
+
retryLog,
|
|
176
|
+
comment: async (content) => { await apiClient.addComment(id, content); await load(); },
|
|
177
|
+
decide: async (answer) => {
|
|
178
|
+
const submitted = String(answer);
|
|
179
|
+
await apiClient.postDecision(id, answer);
|
|
180
|
+
await load();
|
|
181
|
+
submittedDecision.value = submitted;
|
|
182
|
+
},
|
|
183
|
+
move: async (status) => { await apiClient.updateCard(id, { status }); await load(); },
|
|
184
|
+
stop: async () => { await apiClient.stopCard(id); await load(); },
|
|
185
|
+
archive: async () => { await apiClient.updateCard(id, { archivedAt: new Date().toISOString() }); await load(); },
|
|
186
|
+
remove: async () => { await apiClient.deleteCard(id); },
|
|
187
|
+
save: async (patch) => { await apiClient.updateCard(id, patch); await load(); },
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
onUnmounted(stopLogPolling);
|
|
191
|
+
|
|
192
|
+
return { card, comments, running, loading, error, submittedDecision, load, log, logView, setLogView, loadOlderLogs, logLoading, logError, lastUpdated, startLogPolling, stopLogPolling, actions };
|
|
193
|
+
}
|