@sayknow-cli/coding-agent 0.4.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/cli.d.ts +9 -1
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-contract.d.ts +40 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +156 -10
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/extensibility/extensions/types.d.ts +43 -2
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +33 -2
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +22 -9
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/queue-pane.d.ts +8 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +5 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +13 -2
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +6 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/runtime/memory-domain.d.ts +9 -0
- package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
- package/dist/types/runtime/memory-guard.d.ts +39 -0
- package/dist/types/runtime/memory-limit.d.ts +11 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
- package/dist/types/runtime-mcp/manager.d.ts +9 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/final-text.d.ts +19 -0
- package/dist/types/sdk/acp/mcp.d.ts +23 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +52 -4
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/query/handlers.d.ts +14 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/lifecycle-session.d.ts +10 -1
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/sdk/startup-capability.d.ts +9 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +83 -24
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/fallback-chain-controller.d.ts +18 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
- package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +89 -18
- package/dist/types/session/session-storage.d.ts +31 -0
- package/dist/types/session/streaming-output.d.ts +60 -5
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
- package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
- package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
- package/dist/types/skc-runtime/state-writer.d.ts +5 -1
- package/dist/types/skc-runtime/team-launch.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
- package/dist/types/skc-runtime/team-store.d.ts +12 -0
- package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/skill-state/workflow-hud.d.ts +3 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/executor.d.ts +6 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +133 -0
- package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +22 -9
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +7 -1
- package/dist/types/tools/output-meta.d.ts +21 -1
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -1
- package/dist/types/tools/resource-gc.d.ts +23 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -12
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/compile-args.ts +0 -1
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-docs-index.ts +4 -1
- package/scripts/generate-sdk-operation-inventory.ts +9 -0
- package/scripts/run-test-manifest.ts +6 -4
- package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/capability/index.ts +58 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +16 -100
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +6 -38
- package/src/cli/read-cli.ts +2 -1
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +133 -11
- package/src/commands/daemon.ts +22 -5
- package/src/commands/deep-interview.ts +26 -1
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/sdk.ts +134 -17
- package/src/commands/team.ts +1 -1
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-contract.ts +174 -0
- package/src/config/model-profiles.ts +51 -10
- package/src/config/model-registry.ts +24 -4
- package/src/config/model-resolver.ts +2 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +157 -10
- package/src/config/settings.ts +254 -108
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
- package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
- package/src/defaults/skc/skills/team/SKILL.md +1 -1
- package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/eval/py/executor.ts +37 -13
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +42 -4
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/extensibility/shared-events.ts +5 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/internal-urls/docs-index.generated.ts +17 -16
- package/src/internal-urls/local-protocol.ts +87 -25
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +120 -42
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +52 -0
- package/src/modes/acp/acp-agent.ts +647 -83
- package/src/modes/acp/acp-event-mapper.ts +106 -12
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +1 -1
- package/src/modes/components/oauth-selector.ts +42 -12
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/queue-pane.ts +55 -9
- package/src/modes/components/queued-message-selector.ts +53 -10
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/sayknow-pet-widget.ts +27 -8
- package/src/modes/components/session-observer-overlay.ts +187 -32
- package/src/modes/components/settings-selector.ts +60 -18
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +26 -8
- package/src/modes/components/welcome.ts +50 -23
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +101 -54
- package/src/modes/controllers/event-controller.ts +119 -27
- package/src/modes/controllers/extension-ui-controller.ts +23 -12
- package/src/modes/controllers/input-controller.ts +100 -8
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +4 -1
- package/src/modes/interactive-mode.ts +201 -60
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/runtime-init.ts +20 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +6 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +99 -4
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +17 -3
- package/src/prompts/agents/critic.md +17 -2
- package/src/prompts/agents/executor.md +1 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -3
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime/memory-domain.ts +66 -0
- package/src/runtime/memory-guard-contract.ts +73 -0
- package/src/runtime/memory-guard.ts +292 -0
- package/src/runtime/memory-limit.ts +50 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
- package/src/runtime-mcp/json-rpc.ts +28 -11
- package/src/runtime-mcp/manager.ts +77 -59
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/acp/adapter.ts +8 -1
- package/src/sdk/acp/final-text.ts +40 -0
- package/src/sdk/acp/mcp.ts +26 -0
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/lifecycle.ts +293 -43
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -2
- package/src/sdk/bus/chat-daemon-control.ts +22 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +10 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +793 -121
- package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +87 -25
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/prompt-reconciliation.ts +240 -0
- package/src/sdk/bus/rate-limit-pool.ts +8 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/reconciliation-store.ts +224 -0
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
- package/src/sdk/bus/telegram-daemon-control.ts +161 -40
- package/src/sdk/bus/telegram-daemon.ts +3649 -593
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +8 -2
- package/src/sdk/host/control/operations.ts +3 -2
- package/src/sdk/host/host.ts +27 -9
- package/src/sdk/host/query/handlers.ts +125 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/lifecycle-session.ts +19 -3
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +145 -0
- package/src/sdk/protocol/operation-registry.ts +24 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +69 -8
- package/src/sdk/startup-capability.ts +15 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +1112 -314
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/fallback-chain-controller.ts +47 -8
- package/src/session/internal/managed-session-scope.ts +1426 -259
- package/src/session/internal/managed-session-storage.ts +414 -238
- package/src/session/internal/native-publish-outcome.ts +271 -0
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2079 -469
- package/src/session/session-storage.ts +151 -11
- package/src/session/streaming-output.ts +262 -43
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +49 -5
- package/src/setup/provider-presets.json +2 -1
- package/src/skc-runtime/deep-interview-runtime.ts +303 -36
- package/src/skc-runtime/deep-interview-stage.ts +1016 -0
- package/src/skc-runtime/deep-interview-state.ts +8 -5
- package/src/skc-runtime/gc-render.ts +1 -0
- package/src/skc-runtime/gc-runtime.ts +11 -1
- package/src/skc-runtime/linux-proc.ts +70 -36
- package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/skc-runtime/ralplan-runtime.ts +1057 -75
- package/src/skc-runtime/repository-binding.ts +267 -0
- package/src/skc-runtime/session-state-sidecar.ts +25 -9
- package/src/skc-runtime/state-runtime.ts +50 -12
- package/src/skc-runtime/state-writer.ts +68 -56
- package/src/skc-runtime/team-launch.ts +34 -5
- package/src/skc-runtime/team-runtime.ts +41 -1
- package/src/skc-runtime/team-store.ts +32 -0
- package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/skc-runtime/team-workers.ts +1 -0
- package/src/skc-runtime/tmux-common.ts +13 -2
- package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
- package/src/skc-runtime/tmux-sessions.ts +45 -6
- package/src/skc-runtime/ultragoal-guard.ts +93 -15
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
- package/src/skc-runtime/ultragoal-runtime.ts +469 -38
- package/src/skc-runtime/workflow-manifest.generated.json +195 -5
- package/src/skc-runtime/workflow-manifest.ts +67 -3
- package/src/skill-state/workflow-hud.ts +25 -2
- package/src/skill-state/workflow-mutation-guard.ts +104 -12
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/executor.ts +165 -47
- package/src/task/index.ts +123 -15
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/receipt.ts +3 -0
- package/src/task/render.ts +45 -26
- package/src/task/skc-command.ts +2 -2
- package/src/task/types.ts +55 -10
- package/src/task/ultragoal-redteam-activation.ts +75 -0
- package/src/tools/ask.ts +1 -1
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +127 -154
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +7 -1
- package/src/tools/output-meta.ts +176 -9
- package/src/tools/path-utils.ts +5 -1
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1544 -310
- package/src/tools/resource-gc.ts +665 -125
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
- package/src/web/search/providers/codex.ts +1 -1
- package/src/workflow/workflow-intent-diff.ts +4 -1
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
import * as fs from "node:fs/promises";
|
|
3
|
-
import * as os from "node:os";
|
|
4
3
|
import * as path from "node:path";
|
|
4
|
+
import { getConfigRootDir } from "@sayknow-cli/utils";
|
|
5
|
+
import { YAML } from "bun";
|
|
5
6
|
import { syncSkillActiveState } from "../skill-state/active-state";
|
|
6
7
|
import { deriveDeepInterviewHud } from "../skill-state/workflow-hud";
|
|
7
8
|
import { WORKFLOW_STATE_VERSION } from "../skill-state/workflow-state-contract";
|
|
8
|
-
import {
|
|
9
|
+
import { isDeepInterviewStageVerb, runDeepInterviewStageCommand } from "./deep-interview-stage";
|
|
10
|
+
import {
|
|
11
|
+
assertDeepInterviewInputWithinLimit,
|
|
12
|
+
assertDeepInterviewIntentReview,
|
|
13
|
+
type DeepInterviewIntentCategory,
|
|
14
|
+
type DeepInterviewIntentItem,
|
|
15
|
+
type DeepInterviewIntentManifest,
|
|
16
|
+
type DeepInterviewIntentReview,
|
|
17
|
+
MAX_DEEP_INTERVIEW_STRUCTURED_RESPONSE_LENGTH,
|
|
18
|
+
MAX_INITIAL_CONTEXT_LENGTH,
|
|
19
|
+
normalizeDeepInterviewEnvelope,
|
|
20
|
+
reviewDeepInterviewIntent,
|
|
21
|
+
} from "./deep-interview-state";
|
|
9
22
|
import { runNativeRalplanCommand } from "./ralplan-runtime";
|
|
10
23
|
import { modeStatePath, sessionSpecsDir } from "./session-layout";
|
|
11
24
|
import { resolveSkcSessionForWrite, writeSessionActivityMarker } from "./session-resolution";
|
|
12
25
|
import { runNativeStateCommand } from "./state-runtime";
|
|
13
26
|
import { appendJsonl, readExistingStateForMutation, writeArtifact, writeWorkflowEnvelopeAtomic } from "./state-writer";
|
|
27
|
+
import { assertSafePathComponent, CommandError, flagValue, hasFlag } from "./workflow-cli-common";
|
|
14
28
|
|
|
15
29
|
export * from "./deep-interview-recorder";
|
|
16
30
|
|
|
@@ -19,7 +33,7 @@ export * from "./deep-interview-recorder";
|
|
|
19
33
|
*
|
|
20
34
|
* The CLI itself does not run the Socratic interview; that lives inside the `/skill:deep-interview`
|
|
21
35
|
* skill executed by the agent. This handler validates the documented argument-hint surface
|
|
22
|
-
* (`[--quick|--standard|--deep] <idea>`), seeds `.skc/state/deep-interview-state.json`, and
|
|
36
|
+
* (`[--trace] [--quick|--standard|--deep] <idea>`), seeds `.skc/state/deep-interview-state.json`, and
|
|
23
37
|
* updates the shared HUD rail via `syncSkillActiveState` so the active interview is visible to
|
|
24
38
|
* the TUI.
|
|
25
39
|
*/
|
|
@@ -30,8 +44,6 @@ export interface DeepInterviewCommandResult {
|
|
|
30
44
|
stderr?: string;
|
|
31
45
|
}
|
|
32
46
|
|
|
33
|
-
const PATH_COMPONENT_RE = /^[A-Za-z0-9_-][A-Za-z0-9._-]{0,63}$/;
|
|
34
|
-
|
|
35
47
|
const DEFAULT_AMBIGUITY_THRESHOLD = 0.05;
|
|
36
48
|
|
|
37
49
|
const RESOLUTION_THRESHOLDS = {
|
|
@@ -40,14 +52,73 @@ const RESOLUTION_THRESHOLDS = {
|
|
|
40
52
|
deep: 0.35,
|
|
41
53
|
} as const;
|
|
42
54
|
|
|
55
|
+
const TRACE_MAX_RELEVANT_PATHS = 12;
|
|
56
|
+
const TRACE_MAX_PACKAGE_HINTS = 8;
|
|
57
|
+
const TRACE_MAX_DIRECTORY_VISITS = 1200;
|
|
58
|
+
const TRACE_MAX_ENTRY_VISITS = 5000;
|
|
59
|
+
const TRACE_MAX_PENDING_DIRECTORIES = 1200;
|
|
60
|
+
const TRACE_SKIP_DIRS = new Set([
|
|
61
|
+
".git",
|
|
62
|
+
".skc",
|
|
63
|
+
"node_modules",
|
|
64
|
+
"dist",
|
|
65
|
+
"build",
|
|
66
|
+
"coverage",
|
|
67
|
+
".next",
|
|
68
|
+
".turbo",
|
|
69
|
+
".cache",
|
|
70
|
+
"vendor",
|
|
71
|
+
"target",
|
|
72
|
+
".venv",
|
|
73
|
+
"venv",
|
|
74
|
+
"__pycache__",
|
|
75
|
+
".pytest_cache",
|
|
76
|
+
"tmp",
|
|
77
|
+
"temp",
|
|
78
|
+
"logs",
|
|
79
|
+
"out",
|
|
80
|
+
]);
|
|
81
|
+
const TRACE_SOURCE_EXTENSIONS = new Set([
|
|
82
|
+
".ts",
|
|
83
|
+
".tsx",
|
|
84
|
+
".js",
|
|
85
|
+
".jsx",
|
|
86
|
+
".mts",
|
|
87
|
+
".cts",
|
|
88
|
+
".py",
|
|
89
|
+
".rs",
|
|
90
|
+
".go",
|
|
91
|
+
".java",
|
|
92
|
+
".kt",
|
|
93
|
+
".swift",
|
|
94
|
+
".md",
|
|
95
|
+
".json",
|
|
96
|
+
".yml",
|
|
97
|
+
".yaml",
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
interface DeepInterviewTraceSummary {
|
|
101
|
+
enabled: true;
|
|
102
|
+
generated_at: string;
|
|
103
|
+
bounded: true;
|
|
104
|
+
limits: {
|
|
105
|
+
max_relevant_paths: number;
|
|
106
|
+
max_package_hints: number;
|
|
107
|
+
max_directory_visits: number;
|
|
108
|
+
max_entry_visits: number;
|
|
109
|
+
max_pending_directories: number;
|
|
110
|
+
};
|
|
111
|
+
idea_terms: string[];
|
|
112
|
+
project_hints: string[];
|
|
113
|
+
relevant_paths: Array<{ path: string; reason: string }>;
|
|
114
|
+
findings: string[];
|
|
115
|
+
}
|
|
116
|
+
|
|
43
117
|
type DeepInterviewResolution = keyof typeof RESOLUTION_THRESHOLDS;
|
|
44
118
|
|
|
45
|
-
class DeepInterviewCommandError extends
|
|
46
|
-
constructor(
|
|
47
|
-
|
|
48
|
-
message: string,
|
|
49
|
-
) {
|
|
50
|
-
super(message);
|
|
119
|
+
class DeepInterviewCommandError extends CommandError {
|
|
120
|
+
constructor(exitStatus: number, message: string) {
|
|
121
|
+
super(exitStatus, message);
|
|
51
122
|
this.name = "DeepInterviewCommandError";
|
|
52
123
|
}
|
|
53
124
|
}
|
|
@@ -62,22 +133,6 @@ const VALUE_FLAGS = new Set([
|
|
|
62
133
|
"--handoff",
|
|
63
134
|
]);
|
|
64
135
|
|
|
65
|
-
function flagValue(args: readonly string[], flag: string): string | undefined {
|
|
66
|
-
const index = args.indexOf(flag);
|
|
67
|
-
if (index < 0) return undefined;
|
|
68
|
-
return args[index + 1];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function hasFlag(args: readonly string[], flag: string): boolean {
|
|
72
|
-
return args.includes(flag);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function assertSafePathComponent(value: string, label: string): void {
|
|
76
|
-
if (!PATH_COMPONENT_RE.test(value) || value.includes("..")) {
|
|
77
|
-
throw new DeepInterviewCommandError(2, `invalid path component for --${label}: ${value}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
136
|
function defaultSpecSlug(now: Date = new Date()): string {
|
|
82
137
|
const yyyy = now.getUTCFullYear().toString().padStart(4, "0");
|
|
83
138
|
const mm = (now.getUTCMonth() + 1).toString().padStart(2, "0");
|
|
@@ -100,13 +155,141 @@ async function resolveSpecContent(rawSpec: string, cwd: string): Promise<string>
|
|
|
100
155
|
if (stat.isFile()) return await fs.readFile(candidate, "utf-8");
|
|
101
156
|
} catch (error) {
|
|
102
157
|
const err = error as NodeJS.ErrnoException;
|
|
103
|
-
if (err.code !== "ENOENT" && err.code !== "ENOTDIR") {
|
|
158
|
+
if (err.code !== "ENOENT" && err.code !== "ENOTDIR" && err.code !== "ENAMETOOLONG") {
|
|
104
159
|
throw new DeepInterviewCommandError(2, `failed to read --spec ${candidate}: ${err.message}`);
|
|
105
160
|
}
|
|
106
161
|
}
|
|
107
162
|
return rawSpec;
|
|
108
163
|
}
|
|
109
164
|
|
|
165
|
+
function traceTerms(idea: string): string[] {
|
|
166
|
+
const terms = new Set<string>();
|
|
167
|
+
for (const match of idea.toLowerCase().matchAll(/[a-z0-9][a-z0-9_-]{2,}/g)) {
|
|
168
|
+
const value = match[0];
|
|
169
|
+
if (["the", "and", "for", "with", "that", "this", "from", "into", "should", "would"].includes(value)) continue;
|
|
170
|
+
terms.add(value);
|
|
171
|
+
if (terms.size >= 12) break;
|
|
172
|
+
}
|
|
173
|
+
return [...terms];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function relativePathReason(relativePath: string, terms: readonly string[]): string | undefined {
|
|
177
|
+
const normalized = relativePath.toLowerCase();
|
|
178
|
+
const matched = terms.find(term => normalized.includes(term));
|
|
179
|
+
if (matched) return `path matches idea term "${matched}"`;
|
|
180
|
+
if (/deep[-_]?interview/i.test(relativePath)) return "path matches deep-interview workflow surface";
|
|
181
|
+
if (/skill|workflow|runtime|state/i.test(relativePath)) return "path matches workflow/runtime surface";
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function readPackageHints(cwd: string): Promise<string[]> {
|
|
186
|
+
const packagePath = path.join(cwd, "package.json");
|
|
187
|
+
let parsed: unknown;
|
|
188
|
+
try {
|
|
189
|
+
parsed = JSON.parse(await fs.readFile(packagePath, "utf-8"));
|
|
190
|
+
} catch {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
const manifest = parsed as {
|
|
194
|
+
name?: unknown;
|
|
195
|
+
workspaces?: unknown;
|
|
196
|
+
scripts?: Record<string, unknown>;
|
|
197
|
+
dependencies?: Record<string, unknown>;
|
|
198
|
+
devDependencies?: Record<string, unknown>;
|
|
199
|
+
};
|
|
200
|
+
const hints: string[] = [];
|
|
201
|
+
if (typeof manifest.name === "string") hints.push(`package: ${manifest.name}`);
|
|
202
|
+
if (manifest.workspaces) hints.push("workspace: package.json declares workspaces");
|
|
203
|
+
const scripts = Object.keys(manifest.scripts ?? {}).slice(0, TRACE_MAX_PACKAGE_HINTS);
|
|
204
|
+
if (scripts.length > 0) hints.push(`scripts: ${scripts.join(", ")}`);
|
|
205
|
+
const deps = [...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.devDependencies ?? {})]
|
|
206
|
+
.filter(name => /typescript|bun|react|vite|zod|winston|commander|oclif/i.test(name))
|
|
207
|
+
.slice(0, TRACE_MAX_PACKAGE_HINTS);
|
|
208
|
+
if (deps.length > 0) hints.push(`notable dependencies: ${deps.join(", ")}`);
|
|
209
|
+
return hints.slice(0, TRACE_MAX_PACKAGE_HINTS);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async function collectRelevantTracePaths(
|
|
213
|
+
cwd: string,
|
|
214
|
+
terms: readonly string[],
|
|
215
|
+
): Promise<Array<{ path: string; reason: string }>> {
|
|
216
|
+
const results: Array<{ path: string; reason: string; score: number }> = [];
|
|
217
|
+
const pending: Array<{ absolutePath: string; depth: number }> = [{ absolutePath: cwd, depth: 0 }];
|
|
218
|
+
let visitedDirectories = 0;
|
|
219
|
+
let visitedEntries = 0;
|
|
220
|
+
while (
|
|
221
|
+
pending.length > 0 &&
|
|
222
|
+
visitedDirectories < TRACE_MAX_DIRECTORY_VISITS &&
|
|
223
|
+
visitedEntries < TRACE_MAX_ENTRY_VISITS
|
|
224
|
+
) {
|
|
225
|
+
const current = pending.shift();
|
|
226
|
+
if (!current) break;
|
|
227
|
+
visitedDirectories += 1;
|
|
228
|
+
try {
|
|
229
|
+
const directory = await fs.opendir(current.absolutePath);
|
|
230
|
+
for await (const entry of directory) {
|
|
231
|
+
visitedEntries += 1;
|
|
232
|
+
if (visitedEntries > TRACE_MAX_ENTRY_VISITS) break;
|
|
233
|
+
if (TRACE_SKIP_DIRS.has(entry.name)) continue;
|
|
234
|
+
const absolutePath = path.join(current.absolutePath, entry.name);
|
|
235
|
+
const relativePath = path.relative(cwd, absolutePath).split(path.sep).join("/");
|
|
236
|
+
if (entry.isDirectory()) {
|
|
237
|
+
if (current.depth < 6 && pending.length < TRACE_MAX_PENDING_DIRECTORIES) {
|
|
238
|
+
pending.push({ absolutePath, depth: current.depth + 1 });
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (!entry.isFile() || !TRACE_SOURCE_EXTENSIONS.has(path.extname(entry.name))) continue;
|
|
243
|
+
const reason = relativePathReason(relativePath, terms);
|
|
244
|
+
if (!reason) continue;
|
|
245
|
+
const termScore = terms.reduce(
|
|
246
|
+
(score, term) => score + (relativePath.toLowerCase().includes(term) ? 2 : 0),
|
|
247
|
+
0,
|
|
248
|
+
);
|
|
249
|
+
const surfaceScore = /deep[-_]?interview|skill|workflow|runtime|state/i.test(relativePath) ? 1 : 0;
|
|
250
|
+
results.push({ path: relativePath, reason, score: termScore + surfaceScore });
|
|
251
|
+
}
|
|
252
|
+
} catch {}
|
|
253
|
+
}
|
|
254
|
+
return results
|
|
255
|
+
.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path))
|
|
256
|
+
.slice(0, TRACE_MAX_RELEVANT_PATHS)
|
|
257
|
+
.map(({ path: relativePath, reason }) => ({ path: relativePath, reason }));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function buildDeepInterviewTraceSummary(cwd: string, idea: string): Promise<DeepInterviewTraceSummary> {
|
|
261
|
+
const terms = traceTerms(idea);
|
|
262
|
+
const [projectHints, relevantPaths] = await Promise.all([
|
|
263
|
+
readPackageHints(cwd),
|
|
264
|
+
collectRelevantTracePaths(cwd, terms),
|
|
265
|
+
]);
|
|
266
|
+
const findings = [
|
|
267
|
+
projectHints.length > 0
|
|
268
|
+
? "Project manifest was summarized into bounded package/script/dependency hints."
|
|
269
|
+
: "No readable package.json manifest was found at the project root.",
|
|
270
|
+
relevantPaths.length > 0
|
|
271
|
+
? `Relevant path scan captured ${relevantPaths.length} bounded path hint(s) before interview questions.`
|
|
272
|
+
: "Relevant path scan found no matching source/documentation paths before interview questions.",
|
|
273
|
+
"Trace summary intentionally stores path-level evidence only; raw files and logs are excluded.",
|
|
274
|
+
];
|
|
275
|
+
return {
|
|
276
|
+
enabled: true,
|
|
277
|
+
generated_at: new Date().toISOString(),
|
|
278
|
+
bounded: true,
|
|
279
|
+
limits: {
|
|
280
|
+
max_relevant_paths: TRACE_MAX_RELEVANT_PATHS,
|
|
281
|
+
max_package_hints: TRACE_MAX_PACKAGE_HINTS,
|
|
282
|
+
max_directory_visits: TRACE_MAX_DIRECTORY_VISITS,
|
|
283
|
+
max_entry_visits: TRACE_MAX_ENTRY_VISITS,
|
|
284
|
+
max_pending_directories: TRACE_MAX_PENDING_DIRECTORIES,
|
|
285
|
+
},
|
|
286
|
+
idea_terms: terms,
|
|
287
|
+
project_hints: projectHints,
|
|
288
|
+
relevant_paths: relevantPaths,
|
|
289
|
+
findings,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
110
293
|
interface ResolvedDeepInterviewArgs {
|
|
111
294
|
resolution: DeepInterviewResolution;
|
|
112
295
|
threshold: number;
|
|
@@ -114,6 +297,7 @@ interface ResolvedDeepInterviewArgs {
|
|
|
114
297
|
sessionId: string;
|
|
115
298
|
idea: string;
|
|
116
299
|
language?: DeepInterviewLanguagePreference;
|
|
300
|
+
trace?: DeepInterviewTraceSummary;
|
|
117
301
|
json: boolean;
|
|
118
302
|
}
|
|
119
303
|
|
|
@@ -190,16 +374,14 @@ async function readSettingsAmbiguityThreshold(
|
|
|
190
374
|
function modernSettingsPath(): string {
|
|
191
375
|
const configDir = process.env.SKC_CODING_AGENT_DIR?.trim() || process.env.PI_CODING_AGENT_DIR?.trim();
|
|
192
376
|
if (configDir) return path.join(configDir, "config.yml");
|
|
193
|
-
|
|
194
|
-
if (configRoot) return path.join(configRoot, "agent", "config.yml");
|
|
195
|
-
return path.join(os.homedir(), ".skc", "agent", "config.yml");
|
|
377
|
+
return path.join(getConfigRootDir(), "agent", "config.yml");
|
|
196
378
|
}
|
|
197
379
|
|
|
198
380
|
async function readModernSettingsAmbiguityThreshold(): Promise<{ threshold: number; source: string } | undefined> {
|
|
199
381
|
const modernConfigPath = modernSettingsPath();
|
|
200
382
|
let parsed: unknown;
|
|
201
383
|
try {
|
|
202
|
-
parsed =
|
|
384
|
+
parsed = YAML.parse(await fs.readFile(modernConfigPath, "utf-8"));
|
|
203
385
|
} catch {
|
|
204
386
|
return undefined;
|
|
205
387
|
}
|
|
@@ -218,8 +400,7 @@ async function resolveConfiguredAmbiguityThreshold(
|
|
|
218
400
|
const projectSettings = path.join(cwd, ".skc", "settings.json");
|
|
219
401
|
const projectValue = await readSettingsAmbiguityThreshold(projectSettings);
|
|
220
402
|
if (projectValue) return projectValue;
|
|
221
|
-
const
|
|
222
|
-
const userSettings = path.join(configDir, "settings.json");
|
|
403
|
+
const userSettings = path.join(getConfigRootDir(), "settings.json");
|
|
223
404
|
return await readSettingsAmbiguityThreshold(userSettings);
|
|
224
405
|
}
|
|
225
406
|
|
|
@@ -371,6 +552,7 @@ async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): P
|
|
|
371
552
|
skipNext = true;
|
|
372
553
|
continue;
|
|
373
554
|
}
|
|
555
|
+
if (arg === "--trace") continue;
|
|
374
556
|
if (arg === "--quick" || arg === "--standard" || arg === "--deep" || arg === "--json") continue;
|
|
375
557
|
if (arg.startsWith("-")) {
|
|
376
558
|
throw new DeepInterviewCommandError(2, `unknown flag for skc deep-interview: ${arg}`);
|
|
@@ -378,7 +560,9 @@ async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): P
|
|
|
378
560
|
ideaParts.push(arg);
|
|
379
561
|
}
|
|
380
562
|
const idea = ideaParts.join(" ").trim();
|
|
563
|
+
assertDeepInterviewInputWithinLimit(idea, MAX_INITIAL_CONTEXT_LENGTH, "initial_idea");
|
|
381
564
|
const effectiveResolution: DeepInterviewResolution = resolution ?? "standard";
|
|
565
|
+
const trace = hasFlag(args, "--trace") && idea ? await buildDeepInterviewTraceSummary(cwd, idea) : undefined;
|
|
382
566
|
return {
|
|
383
567
|
resolution: effectiveResolution,
|
|
384
568
|
threshold,
|
|
@@ -386,14 +570,75 @@ async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): P
|
|
|
386
570
|
sessionId,
|
|
387
571
|
idea,
|
|
388
572
|
language: resolveDeepInterviewLanguagePreference(idea),
|
|
573
|
+
trace,
|
|
389
574
|
json: hasFlag(args, "--json"),
|
|
390
575
|
};
|
|
391
576
|
}
|
|
392
577
|
|
|
578
|
+
function intentIdsInSpec(content: string): string[] {
|
|
579
|
+
const ids = content.match(/(?:artifact|surface|integration|constraint):[a-z0-9][a-z0-9._/-]{0,127}/g) ?? [];
|
|
580
|
+
return [...new Set(ids)].sort();
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function resolveLockedIntentReview(existing: unknown, content: string): DeepInterviewIntentReview | undefined {
|
|
584
|
+
const envelope = normalizeDeepInterviewEnvelope(existing);
|
|
585
|
+
const state = envelope.state;
|
|
586
|
+
if (!state) return undefined;
|
|
587
|
+
if (state.intent_contract === undefined) {
|
|
588
|
+
if (state.intent_contract_required === true)
|
|
589
|
+
throw new DeepInterviewCommandError(
|
|
590
|
+
2,
|
|
591
|
+
"deep-interview locked intent blocks spec persistence: missing Round 0 intent contract",
|
|
592
|
+
);
|
|
593
|
+
return undefined;
|
|
594
|
+
}
|
|
595
|
+
const locked = state.intent_contract as DeepInterviewIntentManifest;
|
|
596
|
+
const observedIds = intentIdsInSpec(content);
|
|
597
|
+
const rounds = Array.isArray(state.rounds)
|
|
598
|
+
? state.rounds
|
|
599
|
+
.filter(
|
|
600
|
+
(round): round is Record<string, unknown> =>
|
|
601
|
+
Boolean(round) && typeof round === "object" && !Array.isArray(round),
|
|
602
|
+
)
|
|
603
|
+
.map(round => ({ round: round.round, answer_hash: round.answer_hash }))
|
|
604
|
+
: [];
|
|
605
|
+
try {
|
|
606
|
+
if (state.intent_review === undefined) {
|
|
607
|
+
if (locked.items.some(item => !observedIds.includes(item.id))) throw new Error("missing intent review");
|
|
608
|
+
const lockedById = new Map(locked.items.map(item => [item.id, item]));
|
|
609
|
+
const observedItems: DeepInterviewIntentItem[] = observedIds.map(id => {
|
|
610
|
+
const existingItem = lockedById.get(id);
|
|
611
|
+
if (existingItem) return existingItem;
|
|
612
|
+
return {
|
|
613
|
+
id,
|
|
614
|
+
category: id.slice(0, id.indexOf(":")) as DeepInterviewIntentCategory,
|
|
615
|
+
statement: id,
|
|
616
|
+
};
|
|
617
|
+
});
|
|
618
|
+
return reviewDeepInterviewIntent(locked, observedItems, {
|
|
619
|
+
status: "not_required",
|
|
620
|
+
supporting_substitutions: [],
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
assertDeepInterviewIntentReview(state.intent_review, locked, observedIds, rounds);
|
|
624
|
+
return state.intent_review as DeepInterviewIntentReview;
|
|
625
|
+
} catch (error) {
|
|
626
|
+
throw new DeepInterviewCommandError(
|
|
627
|
+
2,
|
|
628
|
+
`deep-interview locked intent blocks spec persistence: ${error instanceof Error ? error.message : String(error)}`,
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
393
633
|
export async function persistDeepInterviewSpec(
|
|
394
634
|
cwd: string,
|
|
395
635
|
resolved: ResolvedDeepInterviewSpecWriteArgs,
|
|
396
636
|
): Promise<PersistedDeepInterviewSpec> {
|
|
637
|
+
assertDeepInterviewInputWithinLimit(
|
|
638
|
+
resolved.spec,
|
|
639
|
+
MAX_DEEP_INTERVIEW_STRUCTURED_RESPONSE_LENGTH,
|
|
640
|
+
"structured deep-interview response",
|
|
641
|
+
);
|
|
397
642
|
const statePath = deepInterviewStatePath(cwd, resolved.sessionId);
|
|
398
643
|
const existingRead = await readExistingStateForMutation(statePath);
|
|
399
644
|
if (existingRead.kind === "corrupt" && !resolved.force) {
|
|
@@ -404,8 +649,9 @@ export async function persistDeepInterviewSpec(
|
|
|
404
649
|
}
|
|
405
650
|
const existing = existingRead.kind === "valid" ? existingRead.value : {};
|
|
406
651
|
|
|
407
|
-
const specPath = path.join(sessionSpecsDir(cwd, resolved.sessionId), `deep-interview-${resolved.slug}.md`);
|
|
408
652
|
const content = resolved.spec.endsWith("\n") ? resolved.spec : `${resolved.spec}\n`;
|
|
653
|
+
const intentReview = resolveLockedIntentReview(existing, content);
|
|
654
|
+
const specPath = path.join(sessionSpecsDir(cwd, resolved.sessionId), `deep-interview-${resolved.slug}.md`);
|
|
409
655
|
await writeArtifact(specPath, content, {
|
|
410
656
|
cwd,
|
|
411
657
|
audit: {
|
|
@@ -447,6 +693,10 @@ export async function persistDeepInterviewSpec(
|
|
|
447
693
|
spec_persisted_at: createdAt,
|
|
448
694
|
updated_at: createdAt,
|
|
449
695
|
}) as Record<string, unknown>;
|
|
696
|
+
if (intentReview) {
|
|
697
|
+
const state = payload.state as Record<string, unknown>;
|
|
698
|
+
state.intent_review = intentReview;
|
|
699
|
+
}
|
|
450
700
|
if (resolved.sessionId) payload.session_id = resolved.sessionId;
|
|
451
701
|
await writeWorkflowEnvelopeAtomic(statePath, payload, {
|
|
452
702
|
cwd,
|
|
@@ -488,6 +738,7 @@ export async function persistDeepInterviewSpec(
|
|
|
488
738
|
|
|
489
739
|
async function seedDeepInterviewState(cwd: string, resolved: ResolvedDeepInterviewArgs): Promise<string> {
|
|
490
740
|
const statePath = deepInterviewStatePath(cwd, resolved.sessionId);
|
|
741
|
+
assertDeepInterviewInputWithinLimit(resolved.idea, MAX_INITIAL_CONTEXT_LENGTH, "initial_idea");
|
|
491
742
|
const now = new Date().toISOString();
|
|
492
743
|
const payload: Record<string, unknown> = {
|
|
493
744
|
active: true,
|
|
@@ -499,6 +750,7 @@ async function seedDeepInterviewState(cwd: string, resolved: ResolvedDeepIntervi
|
|
|
499
750
|
threshold_source: resolved.thresholdSource,
|
|
500
751
|
state: {
|
|
501
752
|
initial_idea: resolved.idea,
|
|
753
|
+
intent_contract_required: true,
|
|
502
754
|
rounds: [],
|
|
503
755
|
established_facts: [],
|
|
504
756
|
current_ambiguity: 1.0,
|
|
@@ -507,6 +759,17 @@ async function seedDeepInterviewState(cwd: string, resolved: ResolvedDeepIntervi
|
|
|
507
759
|
},
|
|
508
760
|
updated_at: now,
|
|
509
761
|
};
|
|
762
|
+
if (resolved.trace) {
|
|
763
|
+
payload.trace = resolved.trace;
|
|
764
|
+
(payload.state as Record<string, unknown>).trace = resolved.trace;
|
|
765
|
+
(payload.state as Record<string, unknown>).trace_summary = resolved.trace;
|
|
766
|
+
(payload.state as Record<string, unknown>).codebase_context = {
|
|
767
|
+
source: "trace",
|
|
768
|
+
summary: resolved.trace.findings,
|
|
769
|
+
relevant_paths: resolved.trace.relevant_paths,
|
|
770
|
+
project_hints: resolved.trace.project_hints,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
510
773
|
if (resolved.language) {
|
|
511
774
|
payload.language = resolved.language;
|
|
512
775
|
(payload.state as Record<string, unknown>).language = resolved.language;
|
|
@@ -629,6 +892,8 @@ export async function runNativeDeepInterviewCommand(
|
|
|
629
892
|
cwd = process.cwd(),
|
|
630
893
|
): Promise<DeepInterviewCommandResult> {
|
|
631
894
|
try {
|
|
895
|
+
const [firstArg, ...restArgs] = args;
|
|
896
|
+
if (isDeepInterviewStageVerb(firstArg)) return await runDeepInterviewStageCommand(firstArg, restArgs, cwd);
|
|
632
897
|
if (isDeepInterviewSpecWriteInvocation(args)) return await handleSpecWrite(args, cwd);
|
|
633
898
|
const resolved = await resolveDeepInterviewArgs(args, cwd);
|
|
634
899
|
if (!resolved.idea) {
|
|
@@ -646,6 +911,7 @@ export async function runNativeDeepInterviewCommand(
|
|
|
646
911
|
threshold_source: resolved.thresholdSource,
|
|
647
912
|
idea: resolved.idea,
|
|
648
913
|
language: resolved.language,
|
|
914
|
+
trace: resolved.trace,
|
|
649
915
|
state_path: statePath,
|
|
650
916
|
handoff: "/skill:deep-interview",
|
|
651
917
|
};
|
|
@@ -654,12 +920,13 @@ export async function runNativeDeepInterviewCommand(
|
|
|
654
920
|
: [
|
|
655
921
|
`deep-interview seed state_path=${statePath}`,
|
|
656
922
|
`resolution=${resolved.resolution} threshold=${resolved.threshold} threshold_source=${resolved.thresholdSource}`,
|
|
923
|
+
resolved.trace ? `trace=enabled bounded_paths=${resolved.trace.relevant_paths.length}` : undefined,
|
|
657
924
|
"handoff=/skill:deep-interview",
|
|
658
925
|
"",
|
|
659
926
|
].join("\n");
|
|
660
927
|
return { status: 0, stdout };
|
|
661
928
|
} catch (error) {
|
|
662
|
-
if (error instanceof
|
|
929
|
+
if (error instanceof CommandError) return { status: error.exitStatus, stderr: `${error.message}\n` };
|
|
663
930
|
return { status: 1, stderr: `${error instanceof Error ? error.message : String(error)}\n` };
|
|
664
931
|
}
|
|
665
932
|
}
|