@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,20 +1,49 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
|
-
import * as os from "node:os";
|
|
3
2
|
import * as path from "node:path";
|
|
3
|
+
import { getConfigRootDir } from "@sayknow-cli/utils";
|
|
4
4
|
import type { WorkflowHudSummary } from "../skill-state/active-state";
|
|
5
5
|
import { buildUltragoalHudSummary as buildWorkflowUltragoalHudSummary } from "../skill-state/workflow-hud";
|
|
6
6
|
import { renderCliWriteReceipt } from "./cli-write-receipt";
|
|
7
7
|
import { DEFAULT_ULTRAGOAL_OBJECTIVE } from "./goal-mode-request";
|
|
8
8
|
import {
|
|
9
|
+
assertCwdMatchesRepositoryBinding,
|
|
10
|
+
captureRepositoryBinding,
|
|
11
|
+
parseRepositoryBinding,
|
|
12
|
+
type RepositoryBinding,
|
|
13
|
+
} from "./repository-binding";
|
|
14
|
+
import {
|
|
15
|
+
CRITIC_GATE_HARD_STOP_EVENT,
|
|
16
|
+
CRITIC_GATE_OVERRIDE_EVENT,
|
|
17
|
+
CRITIC_VERDICT_EVENT,
|
|
18
|
+
type CriticVerdict,
|
|
19
|
+
computeCriticVerdictPlanGeneration,
|
|
9
20
|
computeUltragoalPlanGeneration,
|
|
21
|
+
countNonOkayTerminalCriticVerdicts,
|
|
22
|
+
finalAggregateReceiptMissingCriticOkay,
|
|
10
23
|
findFreshBatchCloseReceipt,
|
|
11
24
|
findLedgerReceiptEvent,
|
|
25
|
+
isCleanPauseCriticVerdictShape,
|
|
12
26
|
requiredUltragoalGoals,
|
|
27
|
+
TERMINAL_CRITIC_CEILING,
|
|
28
|
+
terminalCriticCeilingReached,
|
|
29
|
+
terminalCriticGateOverridden,
|
|
30
|
+
terminalCriticHardStopReached,
|
|
13
31
|
validateDeferredMemberReceiptFresh,
|
|
14
32
|
validateReceiptFreshBase,
|
|
15
33
|
} from "./ultragoal-receipt-freshness";
|
|
16
34
|
|
|
17
|
-
export {
|
|
35
|
+
export {
|
|
36
|
+
CRITIC_GATE_HARD_STOP_EVENT,
|
|
37
|
+
CRITIC_GATE_OVERRIDE_EVENT,
|
|
38
|
+
CRITIC_VERDICT_EVENT,
|
|
39
|
+
type CriticVerdict,
|
|
40
|
+
computeUltragoalPlanGeneration,
|
|
41
|
+
countTerminalCriticVerdicts,
|
|
42
|
+
receiptRelevantGoals,
|
|
43
|
+
TERMINAL_CRITIC_CEILING,
|
|
44
|
+
terminalCriticCeilingReached,
|
|
45
|
+
terminalCriticGateOverridden,
|
|
46
|
+
} from "./ultragoal-receipt-freshness";
|
|
18
47
|
|
|
19
48
|
import { sessionUltragoalDir, skcRoot } from "./session-layout";
|
|
20
49
|
import {
|
|
@@ -170,6 +199,8 @@ export interface UltragoalPlan {
|
|
|
170
199
|
skcObjective: string;
|
|
171
200
|
skcObjectiveAliases?: string[];
|
|
172
201
|
goals: UltragoalGoal[];
|
|
202
|
+
/** Authoritative repository identity for multi-repo fail-closed spawn (#2901). */
|
|
203
|
+
repositoryBinding?: RepositoryBinding;
|
|
173
204
|
createdAt: string;
|
|
174
205
|
updatedAt: string;
|
|
175
206
|
[key: string]: unknown;
|
|
@@ -427,7 +458,6 @@ export const DEFAULT_ULTRAGOAL_NUDGE_BUDGET = 10;
|
|
|
427
458
|
export function countUltragoalNudges(ledger: readonly UltragoalLedgerEvent[], goalId: string): number {
|
|
428
459
|
return ledger.filter(event => event.event === "nudge" && event.goalId === goalId).length;
|
|
429
460
|
}
|
|
430
|
-
|
|
431
461
|
function parseNudgeBudgetValue(value: unknown): number | null {
|
|
432
462
|
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : null;
|
|
433
463
|
}
|
|
@@ -461,8 +491,7 @@ export async function resolveUltragoalNudgeBudget(cwd: string): Promise<{ budget
|
|
|
461
491
|
const projectPath = path.join(skcRoot(cwd), "settings.json");
|
|
462
492
|
const project = await readSettingsNudgeBudget(projectPath);
|
|
463
493
|
if (project !== null) return { budget: project, source: projectPath };
|
|
464
|
-
const
|
|
465
|
-
const userPath = path.join(userDir, "settings.json");
|
|
494
|
+
const userPath = path.join(getConfigRootDir(), "settings.json");
|
|
466
495
|
const user = await readSettingsNudgeBudget(userPath);
|
|
467
496
|
if (user !== null) return { budget: user, source: userPath };
|
|
468
497
|
return { budget: DEFAULT_ULTRAGOAL_NUDGE_BUDGET, source: "default" };
|
|
@@ -1328,6 +1357,10 @@ function normalizePlan(raw: unknown): UltragoalPlan {
|
|
|
1328
1357
|
(value): value is string => typeof value === "string" && value.trim().length > 0,
|
|
1329
1358
|
)
|
|
1330
1359
|
: undefined;
|
|
1360
|
+
let repositoryBinding: RepositoryBinding | undefined;
|
|
1361
|
+
if (record.repositoryBinding !== undefined) {
|
|
1362
|
+
repositoryBinding = parseRepositoryBinding(record.repositoryBinding);
|
|
1363
|
+
}
|
|
1331
1364
|
return {
|
|
1332
1365
|
version: 1,
|
|
1333
1366
|
brief,
|
|
@@ -1337,6 +1370,7 @@ function normalizePlan(raw: unknown): UltragoalPlan {
|
|
|
1337
1370
|
goals,
|
|
1338
1371
|
createdAt,
|
|
1339
1372
|
updatedAt,
|
|
1373
|
+
...(repositoryBinding ? { repositoryBinding } : {}),
|
|
1340
1374
|
...(typeof record.state_revision === "number" && Number.isFinite(record.state_revision)
|
|
1341
1375
|
? { state_revision: record.state_revision }
|
|
1342
1376
|
: {}),
|
|
@@ -1537,12 +1571,16 @@ export async function createUltragoalPlan(input: {
|
|
|
1537
1571
|
goal.validationBatch = validationBatchByGoalId.get(goal.id);
|
|
1538
1572
|
validateValidationBatchPipelineExclusion(goal);
|
|
1539
1573
|
}
|
|
1574
|
+
const repositoryBinding = await captureRepositoryBinding(input.cwd, {
|
|
1575
|
+
displayPath: input.cwd,
|
|
1576
|
+
});
|
|
1540
1577
|
const plan: UltragoalPlan = {
|
|
1541
1578
|
version: 1,
|
|
1542
1579
|
brief,
|
|
1543
1580
|
skcGoalMode: input.skcGoalMode ?? "aggregate",
|
|
1544
1581
|
skcObjective: DEFAULT_ULTRAGOAL_OBJECTIVE,
|
|
1545
1582
|
goals,
|
|
1583
|
+
repositoryBinding,
|
|
1546
1584
|
createdAt: now,
|
|
1547
1585
|
updatedAt: now,
|
|
1548
1586
|
};
|
|
@@ -1618,6 +1656,50 @@ export function getUltragoalRunCompletionState(
|
|
|
1618
1656
|
};
|
|
1619
1657
|
}
|
|
1620
1658
|
|
|
1659
|
+
/**
|
|
1660
|
+
* Discriminated next-action for `complete-goals` handoff (#2903).
|
|
1661
|
+
* `none` is reserved for genuine completion; `execute-goal` always carries a goal.
|
|
1662
|
+
*/
|
|
1663
|
+
export type UltragoalCompleteNextActionKind =
|
|
1664
|
+
| "none"
|
|
1665
|
+
| "execute-goal"
|
|
1666
|
+
| "retry-failed"
|
|
1667
|
+
| "resolve-blockers"
|
|
1668
|
+
| "final-aggregate-receipt";
|
|
1669
|
+
|
|
1670
|
+
export type UltragoalCompleteNextAction = {
|
|
1671
|
+
kind: UltragoalCompleteNextActionKind;
|
|
1672
|
+
goal?: UltragoalGoal;
|
|
1673
|
+
blockedGoals?: UltragoalGoal[];
|
|
1674
|
+
failedGoals?: UltragoalGoal[];
|
|
1675
|
+
};
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* Resolve the actionable next step after scheduling / complete-goals.
|
|
1679
|
+
* Blocked and review_blocked goals remain unschedulable; they surface as
|
|
1680
|
+
* `resolve-blockers` instead of a contradictory `execute-goal` without goal_id.
|
|
1681
|
+
*/
|
|
1682
|
+
export function resolveUltragoalCompleteNextAction(
|
|
1683
|
+
plan: UltragoalPlan,
|
|
1684
|
+
options: { retryFailed?: boolean; selectedGoal?: UltragoalGoal } = {},
|
|
1685
|
+
): UltragoalCompleteNextAction {
|
|
1686
|
+
const state = getUltragoalRunCompletionState(plan, { retryFailed: options.retryFailed });
|
|
1687
|
+
// Genuine completion keeps next_action=`none` (historical complete-goals contract).
|
|
1688
|
+
// final-aggregate-receipt is reserved for a future dedicated handoff; do not remap
|
|
1689
|
+
// allComplete here so aggregate runs still finish with `none` / complete text.
|
|
1690
|
+
if (state.allComplete) return { kind: "none" };
|
|
1691
|
+
const goal = options.selectedGoal ?? state.nextGoal;
|
|
1692
|
+
if (goal) return { kind: "execute-goal", goal };
|
|
1693
|
+
const blockedGoals = state.incompleteGoals.filter(
|
|
1694
|
+
item => item.status === "blocked" || item.status === "review_blocked",
|
|
1695
|
+
);
|
|
1696
|
+
if (blockedGoals.length > 0) return { kind: "resolve-blockers", blockedGoals };
|
|
1697
|
+
const failedGoals = state.incompleteGoals.filter(item => item.status === "failed");
|
|
1698
|
+
if (failedGoals.length > 0) return { kind: "retry-failed", failedGoals };
|
|
1699
|
+
// Incomplete but not schedulable (unexpected statuses): still actionable, not "none".
|
|
1700
|
+
return { kind: "resolve-blockers", blockedGoals: state.incompleteGoals };
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1621
1703
|
export async function startNextUltragoalGoal(input: {
|
|
1622
1704
|
cwd: string;
|
|
1623
1705
|
retryFailed?: boolean;
|
|
@@ -1626,11 +1708,27 @@ export async function startNextUltragoalGoal(input: {
|
|
|
1626
1708
|
plan: UltragoalPlan;
|
|
1627
1709
|
goal?: UltragoalGoal;
|
|
1628
1710
|
allComplete: boolean;
|
|
1711
|
+
nextAction: UltragoalCompleteNextAction;
|
|
1629
1712
|
}> {
|
|
1630
1713
|
const plan = await readUltragoalPlan(input.cwd, input.sessionId);
|
|
1631
1714
|
if (!plan) throw new Error("No ultragoal plan found. Run `skc ultragoal create-goals --brief ...` first.");
|
|
1632
|
-
|
|
1633
|
-
if (!
|
|
1715
|
+
// Fail closed: delegated execution requires stamped repository authority (#2901).
|
|
1716
|
+
if (!plan.repositoryBinding) {
|
|
1717
|
+
throw new Error(
|
|
1718
|
+
"Ultragoal plan is missing repositoryBinding; recreate goals so the plan is bound to an authoritative repository identity.",
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
await assertCwdMatchesRepositoryBinding(input.cwd, plan.repositoryBinding);
|
|
1722
|
+
const retryFailed = input.retryFailed === true;
|
|
1723
|
+
const goal = chooseNextGoal(plan, retryFailed);
|
|
1724
|
+
if (!goal) {
|
|
1725
|
+
const state = getUltragoalRunCompletionState(plan, { retryFailed });
|
|
1726
|
+
return {
|
|
1727
|
+
plan,
|
|
1728
|
+
allComplete: state.allComplete,
|
|
1729
|
+
nextAction: resolveUltragoalCompleteNextAction(plan, { retryFailed }),
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1634
1732
|
if (goal.status !== "active") {
|
|
1635
1733
|
const now = new Date().toISOString();
|
|
1636
1734
|
goal.status = "active";
|
|
@@ -1640,7 +1738,12 @@ export async function startNextUltragoalGoal(input: {
|
|
|
1640
1738
|
await writePlan(input.cwd, plan, input.sessionId);
|
|
1641
1739
|
await appendLedger(input.cwd, { event: "goal_started", goalId: goal.id }, input.sessionId);
|
|
1642
1740
|
}
|
|
1643
|
-
return {
|
|
1741
|
+
return {
|
|
1742
|
+
plan,
|
|
1743
|
+
goal,
|
|
1744
|
+
allComplete: false,
|
|
1745
|
+
nextAction: { kind: "execute-goal", goal },
|
|
1746
|
+
};
|
|
1644
1747
|
}
|
|
1645
1748
|
|
|
1646
1749
|
async function readStructuredValue(cwd: string, value: string): Promise<unknown> {
|
|
@@ -2514,12 +2617,23 @@ async function validateCompletionQualityGate(
|
|
|
2514
2617
|
} = {},
|
|
2515
2618
|
): Promise<void> {
|
|
2516
2619
|
const batchMode = options.goal?.validationBatch;
|
|
2620
|
+
const receiptKind =
|
|
2621
|
+
options.plan && options.goal && options.ledger
|
|
2622
|
+
? chooseReceiptKind(options.plan, options.ledger, options.goal, "complete")
|
|
2623
|
+
: undefined;
|
|
2624
|
+
const isFinalAggregate = receiptKind === "final-aggregate";
|
|
2517
2625
|
if (batchMode && options.goal && options.goal.id !== batchMode.finalGoalId) {
|
|
2518
2626
|
validateDeferredCompletionQualityGate(gate, options.goal, batchMode, options.changeSet);
|
|
2519
2627
|
return;
|
|
2520
2628
|
}
|
|
2521
2629
|
if (batchMode && options.goal && options.goal.id === batchMode.finalGoalId) {
|
|
2522
|
-
const allowedKeys = new Set([
|
|
2630
|
+
const allowedKeys = new Set([
|
|
2631
|
+
"architectReview",
|
|
2632
|
+
"executorQa",
|
|
2633
|
+
"iteration",
|
|
2634
|
+
"validationBatchClose",
|
|
2635
|
+
"criticReview",
|
|
2636
|
+
]);
|
|
2523
2637
|
const unsupportedKeys = Object.keys(gate).filter(key => !allowedKeys.has(key));
|
|
2524
2638
|
if (unsupportedKeys.length > 0)
|
|
2525
2639
|
throw new Error(`qualityGate contains unsupported keys: ${unsupportedKeys.join(", ")}`);
|
|
@@ -2534,8 +2648,8 @@ async function validateCompletionQualityGate(
|
|
|
2534
2648
|
}
|
|
2535
2649
|
const allowedKeys = new Set(
|
|
2536
2650
|
batchMode
|
|
2537
|
-
? ["architectReview", "executorQa", "iteration", "validationBatchClose"]
|
|
2538
|
-
: ["architectReview", "executorQa", "iteration"],
|
|
2651
|
+
? ["architectReview", "executorQa", "iteration", "validationBatchClose", "criticReview"]
|
|
2652
|
+
: ["architectReview", "executorQa", "iteration", "criticReview"],
|
|
2539
2653
|
);
|
|
2540
2654
|
const unsupportedKeys = Object.keys(gate).filter(key => !allowedKeys.has(key));
|
|
2541
2655
|
if (unsupportedKeys.length > 0) {
|
|
@@ -2547,6 +2661,25 @@ async function validateCompletionQualityGate(
|
|
|
2547
2661
|
if (!architectReview || !executorQa || !iteration) {
|
|
2548
2662
|
throw new Error("qualityGate requires architectReview, executorQa, and iteration objects");
|
|
2549
2663
|
}
|
|
2664
|
+
if (isFinalAggregate) {
|
|
2665
|
+
if (
|
|
2666
|
+
options.ledger &&
|
|
2667
|
+
terminalCriticCeilingReached(options.ledger) &&
|
|
2668
|
+
!terminalCriticGateOverridden(options.ledger)
|
|
2669
|
+
) {
|
|
2670
|
+
throw new Error(
|
|
2671
|
+
"checkpoint --status complete blocked: terminal-critic ceiling reached; requires human/leader skc ultragoal record-critic-gate-override before completion",
|
|
2672
|
+
);
|
|
2673
|
+
}
|
|
2674
|
+
const criticReview = qualityGateObject(gate.criticReview);
|
|
2675
|
+
if (criticReview?.verdict !== "OKAY") {
|
|
2676
|
+
throw new Error(
|
|
2677
|
+
"checkpoint --status complete (final aggregate) requires criticReview with verdict OKAY, non-empty evidence, and empty blockers",
|
|
2678
|
+
);
|
|
2679
|
+
}
|
|
2680
|
+
requireNonEmptyString(criticReview.evidence, "criticReview.evidence");
|
|
2681
|
+
requireEmptyBlockers(criticReview.blockers, "criticReview.blockers");
|
|
2682
|
+
}
|
|
2550
2683
|
if (
|
|
2551
2684
|
architectReview.architectureStatus !== CLEAN_ARCHITECT_STATUS ||
|
|
2552
2685
|
architectReview.productStatus !== CLEAN_ARCHITECT_STATUS ||
|
|
@@ -2958,8 +3091,13 @@ export async function checkpointUltragoalGoal(input: {
|
|
|
2958
3091
|
// receipt, the replay is a genuine re-verification: it must run the full
|
|
2959
3092
|
// quality gate and mint a fresh receipt, otherwise a completed goal with a
|
|
2960
3093
|
// context-staled receipt can never be repaired (different evidence is
|
|
2961
|
-
// rejected on complete goals by design). A
|
|
2962
|
-
//
|
|
3094
|
+
// rejected on complete goals by design). A final-aggregate receipt whose
|
|
3095
|
+
// recorded checkpoint gate lacks a clean criticReview OKAY is likewise
|
|
3096
|
+
// repair-eligible: it is not "stale", but the completion guard rejects it
|
|
3097
|
+
// forever (active_missing_critic_verdict), so a no-op replay would leave
|
|
3098
|
+
// the run permanently unable to complete even after the terminal critic
|
|
3099
|
+
// records OKAY. A mutated goal row keeps the fail-loud tamper handling in
|
|
3100
|
+
// the idempotent branch below.
|
|
2963
3101
|
const staleCompleteReceiptReplay =
|
|
2964
3102
|
input.status === "complete" &&
|
|
2965
3103
|
goal.status === "complete" &&
|
|
@@ -2967,13 +3105,14 @@ export async function checkpointUltragoalGoal(input: {
|
|
|
2967
3105
|
Boolean(matchingIdempotentEvent) &&
|
|
2968
3106
|
(!goal.completionVerification ||
|
|
2969
3107
|
(goal.completionVerification.verifiedAt === goal.updatedAt &&
|
|
2970
|
-
validateReceiptFreshBase({
|
|
3108
|
+
(validateReceiptFreshBase({
|
|
2971
3109
|
plan,
|
|
2972
3110
|
ledger: ledgerBefore,
|
|
2973
3111
|
goal,
|
|
2974
3112
|
receipt: goal.completionVerification,
|
|
2975
3113
|
receiptKind: goal.completionVerification.receiptKind,
|
|
2976
|
-
}) !== null
|
|
3114
|
+
}) !== null ||
|
|
3115
|
+
finalAggregateReceiptMissingCriticOkay(ledgerBefore, goal.completionVerification))));
|
|
2977
3116
|
if (
|
|
2978
3117
|
goal.status === input.status &&
|
|
2979
3118
|
goal.evidence === evidence &&
|
|
@@ -3550,10 +3689,10 @@ export async function recordUltragoalReviewBlockers(input: {
|
|
|
3550
3689
|
export type UltragoalBlockerClassification = "human_blocked" | "resolvable";
|
|
3551
3690
|
|
|
3552
3691
|
/**
|
|
3553
|
-
* Record an audited blocker triage classification in the durable ledger.
|
|
3554
|
-
* `
|
|
3555
|
-
*
|
|
3556
|
-
* audit note and never unblocks pause.
|
|
3692
|
+
* Record an audited blocker triage classification in the durable ledger. Pause
|
|
3693
|
+
* requires the latest `blocker_classified` event to be `human_blocked` and a
|
|
3694
|
+
* later clean pause terminal critic verdict bound to that classification; `resolvable`
|
|
3695
|
+
* is an audit note and never unblocks pause.
|
|
3557
3696
|
*/
|
|
3558
3697
|
export async function recordUltragoalBlockerClassification(input: {
|
|
3559
3698
|
cwd: string;
|
|
@@ -3574,6 +3713,130 @@ export async function recordUltragoalBlockerClassification(input: {
|
|
|
3574
3713
|
});
|
|
3575
3714
|
}
|
|
3576
3715
|
|
|
3716
|
+
export async function recordUltragoalCriticVerdict(input: {
|
|
3717
|
+
cwd: string;
|
|
3718
|
+
terminus: "completion" | "pause";
|
|
3719
|
+
verdict: CriticVerdict;
|
|
3720
|
+
evidence: string;
|
|
3721
|
+
blockers?: string[];
|
|
3722
|
+
goalId?: string;
|
|
3723
|
+
classificationEventId?: string;
|
|
3724
|
+
}): Promise<UltragoalLedgerEvent> {
|
|
3725
|
+
const evidence = input.evidence.trim();
|
|
3726
|
+
if (!evidence) throw new Error("record-critic-verdict --evidence is required");
|
|
3727
|
+
if (input.terminus !== "completion" && input.terminus !== "pause") {
|
|
3728
|
+
throw new Error('record-critic-verdict --terminus must be "completion" or "pause"');
|
|
3729
|
+
}
|
|
3730
|
+
if (input.verdict !== "OKAY" && input.verdict !== "ITERATE" && input.verdict !== "REJECT") {
|
|
3731
|
+
throw new Error("record-critic-verdict --verdict must be OKAY, ITERATE, or REJECT");
|
|
3732
|
+
}
|
|
3733
|
+
const blockers = stringArray(input.blockers ?? []);
|
|
3734
|
+
if (!blockers) throw new Error("record-critic-verdict --blockers-json must be a JSON string array");
|
|
3735
|
+
if (input.terminus === "completion" && input.verdict === "OKAY" && blockers.length > 0) {
|
|
3736
|
+
throw new Error("OKAY critic verdict must have empty blockers");
|
|
3737
|
+
}
|
|
3738
|
+
const classificationEventId = input.classificationEventId?.trim();
|
|
3739
|
+
if (input.terminus === "pause" && !classificationEventId) {
|
|
3740
|
+
throw new Error("record-critic-verdict --classification-event-id is required for pause verdicts");
|
|
3741
|
+
}
|
|
3742
|
+
const resolvedSessionId = resolveSkcSessionForWrite(input.cwd, {
|
|
3743
|
+
envSessionId: process.env.SKC_SESSION_ID,
|
|
3744
|
+
}).skcSessionId;
|
|
3745
|
+
const paths = getUltragoalPaths(input.cwd, resolvedSessionId);
|
|
3746
|
+
return withWorkflowStateLock(
|
|
3747
|
+
paths.ledgerPath,
|
|
3748
|
+
async () => {
|
|
3749
|
+
const plan = await readUltragoalPlan(input.cwd, resolvedSessionId);
|
|
3750
|
+
if (!plan) throw new Error("record-critic-verdict requires an active ultragoal plan");
|
|
3751
|
+
const ledger = await readUltragoalLedger(input.cwd, resolvedSessionId);
|
|
3752
|
+
if (input.terminus === "pause") {
|
|
3753
|
+
const latestClassification = [...ledger].reverse().find(event => event.event === "blocker_classified");
|
|
3754
|
+
if (
|
|
3755
|
+
latestClassification?.classification !== "human_blocked" ||
|
|
3756
|
+
latestClassification.eventId !== classificationEventId
|
|
3757
|
+
) {
|
|
3758
|
+
throw new Error(
|
|
3759
|
+
"record-critic-verdict pause requires --classification-event-id to name the latest human_blocked classification",
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
const planGeneration = computeCriticVerdictPlanGeneration(plan);
|
|
3764
|
+
if (
|
|
3765
|
+
input.terminus === "pause" &&
|
|
3766
|
+
input.verdict === "OKAY" &&
|
|
3767
|
+
!isCleanPauseCriticVerdictShape(
|
|
3768
|
+
{
|
|
3769
|
+
event: CRITIC_VERDICT_EVENT,
|
|
3770
|
+
terminus: input.terminus,
|
|
3771
|
+
verdict: input.verdict,
|
|
3772
|
+
evidence,
|
|
3773
|
+
blockers,
|
|
3774
|
+
planGeneration,
|
|
3775
|
+
classificationEventId,
|
|
3776
|
+
},
|
|
3777
|
+
planGeneration,
|
|
3778
|
+
classificationEventId!,
|
|
3779
|
+
)
|
|
3780
|
+
) {
|
|
3781
|
+
throw new Error("OKAY critic verdict must have empty blockers");
|
|
3782
|
+
}
|
|
3783
|
+
const criticVerdict = await appendLedger(
|
|
3784
|
+
input.cwd,
|
|
3785
|
+
{
|
|
3786
|
+
event: CRITIC_VERDICT_EVENT,
|
|
3787
|
+
terminus: input.terminus,
|
|
3788
|
+
verdict: input.verdict,
|
|
3789
|
+
evidence,
|
|
3790
|
+
blockers,
|
|
3791
|
+
planGeneration,
|
|
3792
|
+
...(classificationEventId ? { classificationEventId } : {}),
|
|
3793
|
+
...(input.goalId?.trim() ? { goalId: input.goalId.trim() } : {}),
|
|
3794
|
+
},
|
|
3795
|
+
resolvedSessionId,
|
|
3796
|
+
);
|
|
3797
|
+
const updatedLedger = [...ledger, criticVerdict];
|
|
3798
|
+
const count = countNonOkayTerminalCriticVerdicts(updatedLedger);
|
|
3799
|
+
if (count >= TERMINAL_CRITIC_CEILING && !terminalCriticHardStopReached(updatedLedger)) {
|
|
3800
|
+
await appendLedger(
|
|
3801
|
+
input.cwd,
|
|
3802
|
+
{
|
|
3803
|
+
event: CRITIC_GATE_HARD_STOP_EVENT,
|
|
3804
|
+
planGeneration,
|
|
3805
|
+
reason: "Terminal critic verdict ceiling reached.",
|
|
3806
|
+
count,
|
|
3807
|
+
},
|
|
3808
|
+
resolvedSessionId,
|
|
3809
|
+
);
|
|
3810
|
+
}
|
|
3811
|
+
return criticVerdict;
|
|
3812
|
+
},
|
|
3813
|
+
{ cwd: input.cwd },
|
|
3814
|
+
);
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3817
|
+
export async function recordUltragoalCriticGateOverride(input: {
|
|
3818
|
+
cwd: string;
|
|
3819
|
+
evidence: string;
|
|
3820
|
+
}): Promise<UltragoalLedgerEvent> {
|
|
3821
|
+
const evidence = input.evidence.trim();
|
|
3822
|
+
if (!evidence) throw new Error("record-critic-gate-override --evidence is required");
|
|
3823
|
+
const resolvedSessionId = resolveSkcSessionForWrite(input.cwd, {
|
|
3824
|
+
envSessionId: process.env.SKC_SESSION_ID,
|
|
3825
|
+
}).skcSessionId;
|
|
3826
|
+
const paths = getUltragoalPaths(input.cwd, resolvedSessionId);
|
|
3827
|
+
return withWorkflowStateLock(
|
|
3828
|
+
paths.ledgerPath,
|
|
3829
|
+
async () => {
|
|
3830
|
+
const ledger = await readUltragoalLedger(input.cwd, resolvedSessionId);
|
|
3831
|
+
if (!terminalCriticHardStopReached(ledger)) {
|
|
3832
|
+
throw new Error("record-critic-gate-override requires a durably recorded terminal critic hard stop");
|
|
3833
|
+
}
|
|
3834
|
+
return appendLedger(input.cwd, { event: CRITIC_GATE_OVERRIDE_EVENT, evidence }, resolvedSessionId);
|
|
3835
|
+
},
|
|
3836
|
+
{ cwd: input.cwd },
|
|
3837
|
+
);
|
|
3838
|
+
}
|
|
3839
|
+
|
|
3577
3840
|
type UltragoalReviewMode = "review-only" | "review-start";
|
|
3578
3841
|
type UltragoalReviewContractStrength = "strong" | "thin-derived";
|
|
3579
3842
|
|
|
@@ -3972,7 +4235,7 @@ function renderUltragoalHelp(args: readonly string[]): string | null {
|
|
|
3972
4235
|
" $ skc ultragoal classify-blocker --classification <human_blocked|resolvable> --evidence <text> [FLAGS]",
|
|
3973
4236
|
"",
|
|
3974
4237
|
"FLAGS",
|
|
3975
|
-
" --classification=<value> Required. human_blocked
|
|
4238
|
+
" --classification=<value> Required. human_blocked must be the latest blocker_classified event; pause also requires a later bound clean pause terminal critic OKAY verdict; resolvable never authorizes pause",
|
|
3976
4239
|
" --evidence=<value> Required. Specific blocker evidence; must name the human-only dependency for human_blocked",
|
|
3977
4240
|
" --goal-id=<value> Optional durable .skc/ultragoal goal id, e.g. G001",
|
|
3978
4241
|
" --json Output a machine-readable receipt",
|
|
@@ -3983,6 +4246,44 @@ function renderUltragoalHelp(args: readonly string[]): string | null {
|
|
|
3983
4246
|
"",
|
|
3984
4247
|
].join("\n");
|
|
3985
4248
|
}
|
|
4249
|
+
if (subject === "record-critic-verdict") {
|
|
4250
|
+
return [
|
|
4251
|
+
"Run native SKC Ultragoal workflow commands",
|
|
4252
|
+
"",
|
|
4253
|
+
"USAGE",
|
|
4254
|
+
" $ skc ultragoal record-critic-verdict --terminus <completion|pause> --verdict <OKAY|ITERATE|REJECT> --evidence <text> [--blockers-json <json>] [--goal-id <id>] [--classification-event-id <id>]",
|
|
4255
|
+
"",
|
|
4256
|
+
"FLAGS",
|
|
4257
|
+
" --terminus=<value> Required. completion or pause",
|
|
4258
|
+
" --verdict=<value> Required. OKAY, ITERATE, or REJECT",
|
|
4259
|
+
" --evidence=<value> Required. Specific evidence supporting the verdict",
|
|
4260
|
+
" --blockers-json=<value> Optional JSON string array of blockers",
|
|
4261
|
+
" --goal-id=<value> Optional durable .skc/ultragoal goal id, e.g. G001",
|
|
4262
|
+
" --classification-event-id=<id> Required for pause verdicts; binds the human_blocked classification",
|
|
4263
|
+
" --json Output a machine-readable receipt",
|
|
4264
|
+
"",
|
|
4265
|
+
"EXAMPLES",
|
|
4266
|
+
' $ skc ultragoal record-critic-verdict --terminus completion --verdict OKAY --evidence "all final-aggregate checkpoint evidence is current"',
|
|
4267
|
+
"",
|
|
4268
|
+
].join("\n");
|
|
4269
|
+
}
|
|
4270
|
+
if (subject === "record-critic-gate-override") {
|
|
4271
|
+
return [
|
|
4272
|
+
"Run native SKC Ultragoal workflow commands",
|
|
4273
|
+
"",
|
|
4274
|
+
"USAGE",
|
|
4275
|
+
" $ skc ultragoal record-critic-gate-override --evidence <text> [--json]",
|
|
4276
|
+
"",
|
|
4277
|
+
"FLAGS",
|
|
4278
|
+
" --evidence=<value> Required. Human/leader authorization evidence for the terminal-critic ceiling override",
|
|
4279
|
+
" --json Output a machine-readable receipt",
|
|
4280
|
+
"",
|
|
4281
|
+
"EXAMPLES",
|
|
4282
|
+
' $ skc ultragoal record-critic-gate-override --evidence "leader approved another terminal attempt after reviewing all five findings"',
|
|
4283
|
+
"",
|
|
4284
|
+
].join("\n");
|
|
4285
|
+
}
|
|
4286
|
+
|
|
3986
4287
|
return [
|
|
3987
4288
|
"Run native SKC Ultragoal workflow commands",
|
|
3988
4289
|
"",
|
|
@@ -3998,11 +4299,14 @@ function renderUltragoalHelp(args: readonly string[]): string | null {
|
|
|
3998
4299
|
" steer",
|
|
3999
4300
|
" record-review-blockers",
|
|
4000
4301
|
" classify-blocker",
|
|
4302
|
+
" record-critic-verdict",
|
|
4303
|
+
" record-critic-gate-override",
|
|
4304
|
+
|
|
4001
4305
|
" start-pipeline-overlap",
|
|
4002
4306
|
" join-pipeline-overlap",
|
|
4003
4307
|
" rebaseline-pipeline-overlap",
|
|
4004
4308
|
"",
|
|
4005
|
-
"Run `skc ultragoal checkpoint --help`, `skc ultragoal review --help`,
|
|
4309
|
+
"Run `skc ultragoal checkpoint --help`, `skc ultragoal review --help`, `skc ultragoal classify-blocker --help`, `skc ultragoal record-critic-verdict --help`, or `skc ultragoal record-critic-gate-override --help` for command-specific requirements.",
|
|
4006
4310
|
"",
|
|
4007
4311
|
].join("\n");
|
|
4008
4312
|
}
|
|
@@ -4021,31 +4325,111 @@ function renderStatus(summary: UltragoalStatusSummary, json: boolean): string {
|
|
|
4021
4325
|
return renderUltragoalStatusMarkdown(summary);
|
|
4022
4326
|
}
|
|
4023
4327
|
|
|
4328
|
+
function summarizeBlockedGoalForHandoff(goal: UltragoalGoal): {
|
|
4329
|
+
id: string;
|
|
4330
|
+
status: UltragoalGoalStatus;
|
|
4331
|
+
evidence?: string;
|
|
4332
|
+
} {
|
|
4333
|
+
const evidence = typeof goal.evidence === "string" && goal.evidence.trim() ? goal.evidence.trim() : undefined;
|
|
4334
|
+
return {
|
|
4335
|
+
id: goal.id,
|
|
4336
|
+
status: goal.status,
|
|
4337
|
+
...(evidence ? { evidence } : {}),
|
|
4338
|
+
};
|
|
4339
|
+
}
|
|
4340
|
+
|
|
4024
4341
|
function renderCompleteHandoff(
|
|
4025
|
-
result: {
|
|
4342
|
+
result: {
|
|
4343
|
+
plan: UltragoalPlan;
|
|
4344
|
+
goal?: UltragoalGoal;
|
|
4345
|
+
allComplete: boolean;
|
|
4346
|
+
nextAction?: UltragoalCompleteNextAction;
|
|
4347
|
+
},
|
|
4026
4348
|
json: boolean,
|
|
4027
4349
|
cwd: string,
|
|
4028
4350
|
): string {
|
|
4351
|
+
const nextAction =
|
|
4352
|
+
result.nextAction ??
|
|
4353
|
+
resolveUltragoalCompleteNextAction(result.plan, {
|
|
4354
|
+
selectedGoal: result.goal,
|
|
4355
|
+
});
|
|
4356
|
+
const goalsPath = getUltragoalPaths(cwd, currentUltragoalSessionId(cwd)).goalsPath;
|
|
4357
|
+
|
|
4029
4358
|
if (json) {
|
|
4030
|
-
|
|
4359
|
+
const receipt: Record<string, unknown> = {
|
|
4031
4360
|
ok: true,
|
|
4032
4361
|
all_complete: result.allComplete,
|
|
4033
|
-
next_action:
|
|
4034
|
-
goal_id: result.goal?.id,
|
|
4035
|
-
goal_status: result.goal?.status,
|
|
4362
|
+
next_action: nextAction.kind,
|
|
4036
4363
|
skc_objective: result.plan.skcObjective,
|
|
4037
|
-
goals_path:
|
|
4038
|
-
}
|
|
4364
|
+
goals_path: goalsPath,
|
|
4365
|
+
};
|
|
4366
|
+
if (nextAction.kind === "execute-goal" && nextAction.goal) {
|
|
4367
|
+
receipt.goal_id = nextAction.goal.id;
|
|
4368
|
+
receipt.goal_status = nextAction.goal.status;
|
|
4369
|
+
}
|
|
4370
|
+
if (nextAction.kind === "resolve-blockers" && nextAction.blockedGoals) {
|
|
4371
|
+
receipt.blocked_goals = nextAction.blockedGoals.map(summarizeBlockedGoalForHandoff);
|
|
4372
|
+
receipt.blocked_goal_ids = nextAction.blockedGoals.map(goal => goal.id);
|
|
4373
|
+
receipt.recovery_hints = [
|
|
4374
|
+
"skc ultragoal classify-blocker --help",
|
|
4375
|
+
"skc ultragoal record-review-blockers --help",
|
|
4376
|
+
"skc ultragoal steer --kind add_subgoal --help",
|
|
4377
|
+
"skc ultragoal steer --kind mark_blocked_superseded --help",
|
|
4378
|
+
];
|
|
4379
|
+
}
|
|
4380
|
+
if (nextAction.kind === "retry-failed" && nextAction.failedGoals) {
|
|
4381
|
+
receipt.failed_goal_ids = nextAction.failedGoals.map(goal => goal.id);
|
|
4382
|
+
receipt.recovery_hints = ["skc ultragoal complete-goals --retry-failed"];
|
|
4383
|
+
}
|
|
4384
|
+
if (nextAction.kind === "final-aggregate-receipt") {
|
|
4385
|
+
receipt.recovery_hints = [
|
|
4386
|
+
"Finalize the aggregate completion receipt before treating the ultragoal run as closed.",
|
|
4387
|
+
];
|
|
4388
|
+
}
|
|
4389
|
+
return renderCliWriteReceipt(receipt);
|
|
4039
4390
|
}
|
|
4040
|
-
|
|
4041
|
-
if (
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4391
|
+
|
|
4392
|
+
if (nextAction.kind === "none" || (result.allComplete && nextAction.kind !== "final-aggregate-receipt")) {
|
|
4393
|
+
return "ultragoal complete all=true\n";
|
|
4394
|
+
}
|
|
4395
|
+
if (nextAction.kind === "final-aggregate-receipt") {
|
|
4396
|
+
return [
|
|
4397
|
+
"ultragoal next-action=final-aggregate-receipt",
|
|
4398
|
+
"hint=finalize the aggregate completion receipt before treating the run as closed",
|
|
4399
|
+
"",
|
|
4400
|
+
].join("\n");
|
|
4401
|
+
}
|
|
4402
|
+
if (nextAction.kind === "execute-goal" && nextAction.goal) {
|
|
4403
|
+
return [
|
|
4404
|
+
`ultragoal next-action=execute-goal goal-id=${nextAction.goal.id}`,
|
|
4405
|
+
`objective=${nextAction.goal.objective}`,
|
|
4406
|
+
`skc-objective=${result.plan.skcObjective}`,
|
|
4407
|
+
"checkpoint requires=architectReview:CLEAR+APPROVE,executorQa:passed",
|
|
4408
|
+
"",
|
|
4409
|
+
].join("\n");
|
|
4410
|
+
}
|
|
4411
|
+
if (nextAction.kind === "resolve-blockers" && nextAction.blockedGoals && nextAction.blockedGoals.length > 0) {
|
|
4412
|
+
const ids = nextAction.blockedGoals.map(goal => goal.id).join(",");
|
|
4413
|
+
const statuses = nextAction.blockedGoals.map(goal => `${goal.id}:${goal.status}`).join(",");
|
|
4414
|
+
return [
|
|
4415
|
+
"ultragoal next-action=resolve-blockers",
|
|
4416
|
+
`blocked-goal-ids=${ids}`,
|
|
4417
|
+
`blocked-statuses=${statuses}`,
|
|
4418
|
+
"hint=resolve blockers via classify-blocker / record-review-blockers / steer --kind add_subgoal (or audited mark_blocked_superseded); blocked goals stay unschedulable",
|
|
4419
|
+
"",
|
|
4420
|
+
].join("\n");
|
|
4421
|
+
}
|
|
4422
|
+
if (nextAction.kind === "retry-failed" && nextAction.failedGoals && nextAction.failedGoals.length > 0) {
|
|
4423
|
+
const ids = nextAction.failedGoals.map(goal => goal.id).join(",");
|
|
4424
|
+
return [
|
|
4425
|
+
"ultragoal next-action=retry-failed",
|
|
4426
|
+
`failed-goal-ids=${ids}`,
|
|
4427
|
+
"hint=run `skc ultragoal complete-goals --retry-failed` after the failure is addressed",
|
|
4428
|
+
"",
|
|
4429
|
+
].join("\n");
|
|
4430
|
+
}
|
|
4431
|
+
// Fail closed: never claim complete or execute-goal without a goal id.
|
|
4432
|
+
return "ultragoal next-action=resolve-blockers\nhint=no schedulable goal; inspect goals.json and ledger\n";
|
|
4049
4433
|
}
|
|
4050
4434
|
function renderCheckpointContinuation(
|
|
4051
4435
|
result: UltragoalCheckpointContinuation,
|
|
@@ -4354,8 +4738,53 @@ async function dispatchUltragoalCommand(args: string[], cwd: string): Promise<Ul
|
|
|
4354
4738
|
ok: true,
|
|
4355
4739
|
event: "blocker_classified",
|
|
4356
4740
|
classification: event.classification,
|
|
4741
|
+
event_id: event.eventId,
|
|
4742
|
+
})
|
|
4743
|
+
: `Recorded blocker classification: ${String(event.classification)} event-id=${String(event.eventId)}.\n`,
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
4746
|
+
case "record-critic-verdict": {
|
|
4747
|
+
const blockersJson = flagValue(args, "--blockers-json");
|
|
4748
|
+
const blockers =
|
|
4749
|
+
blockersJson === undefined ? undefined : stringArray(await readStructuredValue(cwd, blockersJson));
|
|
4750
|
+
if (blockersJson !== undefined && !blockers) {
|
|
4751
|
+
throw new Error("record-critic-verdict --blockers-json must be a JSON string array");
|
|
4752
|
+
}
|
|
4753
|
+
const event = await recordUltragoalCriticVerdict({
|
|
4754
|
+
cwd,
|
|
4755
|
+
terminus: (flagValue(args, "--terminus") ?? "") as "completion" | "pause",
|
|
4756
|
+
verdict: (flagValue(args, "--verdict") ?? "") as CriticVerdict,
|
|
4757
|
+
evidence: flagValue(args, "--evidence") ?? "",
|
|
4758
|
+
blockers: blockers ?? undefined,
|
|
4759
|
+
goalId: flagValue(args, "--goal-id"),
|
|
4760
|
+
classificationEventId: flagValue(args, "--classification-event-id"),
|
|
4761
|
+
});
|
|
4762
|
+
return {
|
|
4763
|
+
status: 0,
|
|
4764
|
+
stdout: json
|
|
4765
|
+
? renderCliWriteReceipt({
|
|
4766
|
+
ok: true,
|
|
4767
|
+
event: CRITIC_VERDICT_EVENT,
|
|
4768
|
+
terminus: event.terminus,
|
|
4769
|
+
verdict: event.verdict,
|
|
4770
|
+
})
|
|
4771
|
+
: `Recorded critic verdict: ${String(event.verdict)} (${String(event.terminus)}).\n`,
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
case "record-critic-gate-override": {
|
|
4775
|
+
const event = await recordUltragoalCriticGateOverride({
|
|
4776
|
+
cwd,
|
|
4777
|
+
evidence: flagValue(args, "--evidence") ?? "",
|
|
4778
|
+
});
|
|
4779
|
+
return {
|
|
4780
|
+
status: 0,
|
|
4781
|
+
stdout: json
|
|
4782
|
+
? renderCliWriteReceipt({
|
|
4783
|
+
ok: true,
|
|
4784
|
+
event: CRITIC_GATE_OVERRIDE_EVENT,
|
|
4785
|
+
event_id: event.eventId,
|
|
4357
4786
|
})
|
|
4358
|
-
: `Recorded
|
|
4787
|
+
: `Recorded terminal critic gate override event-id=${String(event.eventId)}.\n`,
|
|
4359
4788
|
};
|
|
4360
4789
|
}
|
|
4361
4790
|
case "start-pipeline-overlap": {
|
|
@@ -4435,6 +4864,8 @@ const RECONCILE_COMMANDS = new Set([
|
|
|
4435
4864
|
"record-review-blockers",
|
|
4436
4865
|
"review",
|
|
4437
4866
|
"classify-blocker",
|
|
4867
|
+
"record-critic-verdict",
|
|
4868
|
+
"record-critic-gate-override",
|
|
4438
4869
|
"start-pipeline-overlap",
|
|
4439
4870
|
"join-pipeline-overlap",
|
|
4440
4871
|
"rebaseline-pipeline-overlap",
|