@sayknow-cli/coding-agent 0.4.7 → 0.5.1
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 +122 -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 +20 -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
package/src/main.ts
CHANGED
|
@@ -11,7 +11,8 @@ import * as path from "node:path";
|
|
|
11
11
|
import { createInterface } from "node:readline/promises";
|
|
12
12
|
import type { ImageContent } from "@sayknow-cli/ai";
|
|
13
13
|
import {
|
|
14
|
-
$
|
|
14
|
+
$pickenv,
|
|
15
|
+
getAgentDir,
|
|
15
16
|
getProjectDir,
|
|
16
17
|
logger,
|
|
17
18
|
normalizePathForComparison,
|
|
@@ -534,7 +535,16 @@ interface InteractiveModeFactoryOptions {
|
|
|
534
535
|
type CreateInteractiveMode = (options: InteractiveModeFactoryOptions) => InteractiveMode;
|
|
535
536
|
|
|
536
537
|
type ResumePickerTerminalCheck = () => boolean;
|
|
537
|
-
type ListForResumePickerReadOnly = (cwd: string, sessionDir?: string) => Promise<SessionInfo[]>;
|
|
538
|
+
type ListForResumePickerReadOnly = (cwd: string, sessionDir?: string, storage?: undefined) => Promise<SessionInfo[]>;
|
|
539
|
+
|
|
540
|
+
type ListManagedForResumePickerReadOnly = (
|
|
541
|
+
cwd: string,
|
|
542
|
+
managedAgentDir?: string,
|
|
543
|
+
storage?: undefined,
|
|
544
|
+
) => Promise<SessionInfo[]>;
|
|
545
|
+
|
|
546
|
+
type ResolveManagedAgentDirForScope = (cwd: string) => string;
|
|
547
|
+
|
|
538
548
|
type SelectResumeSession = (sessions: SessionInfo[]) => Promise<SessionSelectionResult>;
|
|
539
549
|
type OpenExistingSessionStrict = (
|
|
540
550
|
identity: ResumeSessionIdentity,
|
|
@@ -546,6 +556,11 @@ type OpenExistingSessionStrict = (
|
|
|
546
556
|
export const BARE_RESUME_CONFLICT_ERROR =
|
|
547
557
|
"--resume without a session cannot be combined with --continue, --fork, or --no-session.";
|
|
548
558
|
export const BARE_RESUME_INTERACTIVE_ERROR = "--resume requires an interactive terminal; use --resume <id>.";
|
|
559
|
+
|
|
560
|
+
/** Resolves only the managed agent root needed for pre-consent picker inventory. */
|
|
561
|
+
export function resolveManagedAgentDirForScope(_cwd: string): string {
|
|
562
|
+
return getAgentDir();
|
|
563
|
+
}
|
|
549
564
|
export const BARE_RESUME_OPEN_ERROR = "Could not open the selected session. Use --resume <id>.";
|
|
550
565
|
|
|
551
566
|
function isBareResume(parsed: Args): boolean {
|
|
@@ -683,7 +698,7 @@ async function promptForkSession(session: SessionInfo): Promise<boolean> {
|
|
|
683
698
|
}
|
|
684
699
|
}
|
|
685
700
|
|
|
686
|
-
async function getChangelogForDisplay(parsed: Args): Promise<string | undefined> {
|
|
701
|
+
export async function getChangelogForDisplay(parsed: Args): Promise<string | undefined> {
|
|
687
702
|
if (parsed.continue || parsed.resume) {
|
|
688
703
|
return undefined;
|
|
689
704
|
}
|
|
@@ -695,15 +710,19 @@ async function getChangelogForDisplay(parsed: Args): Promise<string | undefined>
|
|
|
695
710
|
|
|
696
711
|
const lastVersion = settings.get("lastChangelogVersion");
|
|
697
712
|
if (!lastVersion) {
|
|
698
|
-
settings.
|
|
699
|
-
|
|
713
|
+
if (settings.canWriteDurableConfig()) {
|
|
714
|
+
settings.set("lastChangelogVersion", VERSION);
|
|
715
|
+
await flushChangelogVersion();
|
|
716
|
+
}
|
|
700
717
|
return getInstalledVersionChangelogEntry(entries, VERSION)?.content;
|
|
701
718
|
}
|
|
702
719
|
|
|
703
720
|
if (lastVersion !== VERSION) {
|
|
704
721
|
const newEntries = getNewEntries(entries, lastVersion);
|
|
705
|
-
settings.
|
|
706
|
-
|
|
722
|
+
if (settings.canWriteDurableConfig()) {
|
|
723
|
+
settings.set("lastChangelogVersion", VERSION);
|
|
724
|
+
await flushChangelogVersion();
|
|
725
|
+
}
|
|
707
726
|
if (newEntries.length > 0) {
|
|
708
727
|
return newEntries.map(e => e.content).join("\n\n");
|
|
709
728
|
}
|
|
@@ -741,7 +760,13 @@ export async function createSessionManager(
|
|
|
741
760
|
if (forkSource.includes("/") || forkSource.includes("\\") || forkSource.endsWith(".jsonl")) {
|
|
742
761
|
return await SessionManager.forkFrom(forkSource, cwd, sessionDestination(), undefined, migrationPolicy);
|
|
743
762
|
}
|
|
744
|
-
const match = await resolveResumableSession(
|
|
763
|
+
const match = await resolveResumableSession(
|
|
764
|
+
forkSource,
|
|
765
|
+
cwd,
|
|
766
|
+
parsed.sessionDir,
|
|
767
|
+
undefined,
|
|
768
|
+
parsed.sessionDir ? undefined : activeSettings.getAgentDir(),
|
|
769
|
+
);
|
|
745
770
|
if (!match) {
|
|
746
771
|
throw new Error(`Session "${forkSource}" not found.`);
|
|
747
772
|
}
|
|
@@ -754,14 +779,18 @@ export async function createSessionManager(
|
|
|
754
779
|
if (typeof parsed.resume === "string") {
|
|
755
780
|
const sessionArg = parsed.resume;
|
|
756
781
|
if (sessionArg.includes("/") || sessionArg.includes("\\") || sessionArg.endsWith(".jsonl")) {
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
SessionManager.explicitDestination(path.dirname(sessionArg))
|
|
760
|
-
|
|
761
|
-
migrationPolicy,
|
|
762
|
-
);
|
|
782
|
+
const destination = parsed.sessionDir
|
|
783
|
+
? SessionManager.explicitDestination(parsed.sessionDir)
|
|
784
|
+
: SessionManager.explicitDestination(path.dirname(sessionArg));
|
|
785
|
+
return await SessionManager.open(sessionArg, destination, undefined, migrationPolicy);
|
|
763
786
|
}
|
|
764
|
-
const match = await resolveResumableSession(
|
|
787
|
+
const match = await resolveResumableSession(
|
|
788
|
+
sessionArg,
|
|
789
|
+
cwd,
|
|
790
|
+
parsed.sessionDir,
|
|
791
|
+
undefined,
|
|
792
|
+
parsed.sessionDir ? undefined : activeSettings.getAgentDir(),
|
|
793
|
+
);
|
|
765
794
|
if (!match) {
|
|
766
795
|
throw new Error(`Session "${sessionArg}" not found.`);
|
|
767
796
|
}
|
|
@@ -1058,12 +1087,62 @@ export interface RunRootCommandDependencies {
|
|
|
1058
1087
|
runPrintMode?: RunPrintMode;
|
|
1059
1088
|
isResumePickerTerminal?: ResumePickerTerminalCheck;
|
|
1060
1089
|
listForResumePickerReadOnly?: ListForResumePickerReadOnly;
|
|
1090
|
+
listManagedForResumePickerReadOnly?: ListManagedForResumePickerReadOnly;
|
|
1091
|
+
resolveManagedAgentDirForScope?: ResolveManagedAgentDirForScope;
|
|
1061
1092
|
selectResumeSession?: SelectResumeSession;
|
|
1062
1093
|
openExistingSessionStrict?: OpenExistingSessionStrict;
|
|
1063
1094
|
initializeSettings?: typeof Settings.init;
|
|
1064
1095
|
loadSettingsForScope?: typeof Settings.loadForScope;
|
|
1065
1096
|
}
|
|
1066
1097
|
|
|
1098
|
+
export interface ModelRoleOverrides {
|
|
1099
|
+
smol?: string;
|
|
1100
|
+
slow?: string;
|
|
1101
|
+
plan?: string;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Resolve the ephemeral `smol`/`slow`/`plan` model-role overrides.
|
|
1106
|
+
*
|
|
1107
|
+
* Precedence per role is CLI flag > documented `SKC_*_MODEL` > legacy
|
|
1108
|
+
* `PI_*_MODEL`, matching the repo-wide SKC-first/PI-fallback convention.
|
|
1109
|
+
* Resolution reads the process environment via `$pickenv`, which trims values
|
|
1110
|
+
* and treats empty/whitespace as unset; it is deliberately kept separate from
|
|
1111
|
+
* credential env resolution (`$credentialEnv`/`$pickCredentialEnv`). The
|
|
1112
|
+
* function is pure and stateless, so it reads fresh each call and a later
|
|
1113
|
+
* invocation never inherits an earlier one's values.
|
|
1114
|
+
*/
|
|
1115
|
+
export function resolveModelRoleOverrides(parsed: Pick<Args, "smol" | "slow" | "plan">): ModelRoleOverrides {
|
|
1116
|
+
const overrides: ModelRoleOverrides = {};
|
|
1117
|
+
const smol = parsed.smol ?? $pickenv("SKC_SMOL_MODEL", "PI_SMOL_MODEL");
|
|
1118
|
+
const slow = parsed.slow ?? $pickenv("SKC_SLOW_MODEL", "PI_SLOW_MODEL");
|
|
1119
|
+
const plan = parsed.plan ?? $pickenv("SKC_PLAN_MODEL", "PI_PLAN_MODEL");
|
|
1120
|
+
if (smol) overrides.smol = smol;
|
|
1121
|
+
if (slow) overrides.slow = slow;
|
|
1122
|
+
if (plan) overrides.plan = plan;
|
|
1123
|
+
return overrides;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/**
|
|
1127
|
+
* Apply the `--no-pty` / `--no-title` terminal-control flags to the environment.
|
|
1128
|
+
*
|
|
1129
|
+
* Sets the canonical `SKC_*` name (so an explicit flag wins over a user-set
|
|
1130
|
+
* `SKC_*` value under the SKC-first resolver — CLI authority) and the legacy
|
|
1131
|
+
* `PI_*` name for backward compatibility. `--acp` mode implies `--no-title`.
|
|
1132
|
+
*/
|
|
1133
|
+
export function applyTerminalControlFlagsToEnv(
|
|
1134
|
+
parsed: Pick<Args, "noPty" | "noTitle" | "mode">,
|
|
1135
|
+
env: NodeJS.ProcessEnv = Bun.env,
|
|
1136
|
+
): void {
|
|
1137
|
+
if (parsed.noPty) {
|
|
1138
|
+
env.SKC_NO_PTY = "1";
|
|
1139
|
+
env.PI_NO_PTY = "1";
|
|
1140
|
+
}
|
|
1141
|
+
if (parsed.noTitle || parsed.mode === "acp") {
|
|
1142
|
+
env.SKC_NO_TITLE = "1";
|
|
1143
|
+
env.PI_NO_TITLE = "1";
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1067
1146
|
export async function runRootCommand(
|
|
1068
1147
|
parsed: Args,
|
|
1069
1148
|
rawArgs: string[],
|
|
@@ -1094,10 +1173,18 @@ export async function runRootCommand(
|
|
|
1094
1173
|
await logger.time("maybeAutoChdir", maybeAutoChdir, parsedArgs);
|
|
1095
1174
|
autoChdirApplied = true;
|
|
1096
1175
|
const resumeCwd = getProjectDir();
|
|
1097
|
-
const
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1176
|
+
const managedAgentDir = parsedArgs.sessionDir
|
|
1177
|
+
? undefined
|
|
1178
|
+
: (deps.resolveManagedAgentDirForScope ?? resolveManagedAgentDirForScope)(resumeCwd);
|
|
1179
|
+
const sessions = parsedArgs.sessionDir
|
|
1180
|
+
? await (deps.listForResumePickerReadOnly ?? SessionManager.listForResumePickerReadOnly)(
|
|
1181
|
+
resumeCwd,
|
|
1182
|
+
parsedArgs.sessionDir,
|
|
1183
|
+
)
|
|
1184
|
+
: await (deps.listManagedForResumePickerReadOnly ?? SessionManager.listManagedForResumePickerReadOnly)(
|
|
1185
|
+
resumeCwd,
|
|
1186
|
+
managedAgentDir,
|
|
1187
|
+
);
|
|
1101
1188
|
if (sessions.length === 0) {
|
|
1102
1189
|
process.stdout.write(`${chalk.dim("No sessions found")}\n`);
|
|
1103
1190
|
return;
|
|
@@ -1108,19 +1195,16 @@ export async function runRootCommand(
|
|
|
1108
1195
|
if (selection.kind === "cancelled") {
|
|
1109
1196
|
return;
|
|
1110
1197
|
}
|
|
1198
|
+
const scopedSettings = await (deps.loadSettingsForScope ?? Settings.loadForScope)({ cwd: resumeCwd });
|
|
1111
1199
|
const resumeMigrationPolicy =
|
|
1112
|
-
(
|
|
1113
|
-
"session.directoryMigration",
|
|
1114
|
-
) === "disabled"
|
|
1115
|
-
? "disabled"
|
|
1116
|
-
: "copy-retain";
|
|
1200
|
+
scopedSettings.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
|
|
1117
1201
|
let opened: StrictSessionOpenResult;
|
|
1118
1202
|
try {
|
|
1119
1203
|
opened = await (deps.openExistingSessionStrict ?? SessionManager.openExistingStrict)(
|
|
1120
1204
|
selection.identity,
|
|
1121
1205
|
parsedArgs.sessionDir
|
|
1122
1206
|
? SessionManager.explicitDestination(parsedArgs.sessionDir)
|
|
1123
|
-
: SessionManager.managedDestination(resumeCwd,
|
|
1207
|
+
: SessionManager.managedDestination(resumeCwd, scopedSettings.getAgentDir()),
|
|
1124
1208
|
undefined,
|
|
1125
1209
|
resumeMigrationPolicy,
|
|
1126
1210
|
);
|
|
@@ -1198,12 +1282,7 @@ export async function runRootCommand(
|
|
|
1198
1282
|
applyAcpDefaultSettingOverrides(settingsInstance);
|
|
1199
1283
|
}
|
|
1200
1284
|
modelRegistry.applyConfiguredModelBindings(settingsInstance);
|
|
1201
|
-
|
|
1202
|
-
Bun.env.PI_NO_PTY = "1";
|
|
1203
|
-
}
|
|
1204
|
-
if (parsedArgs.noTitle || parsedArgs.mode === "acp") {
|
|
1205
|
-
Bun.env.PI_NO_TITLE = "1";
|
|
1206
|
-
}
|
|
1285
|
+
applyTerminalControlFlagsToEnv(parsedArgs);
|
|
1207
1286
|
const hasPreparedInput = parsedArgs.messages.length > 0 || parsedArgs.fileArgs.length > 0;
|
|
1208
1287
|
const { pipedInput, fileText, fileImages } = await logger.time("prepareInitialMessage", async () => {
|
|
1209
1288
|
const pipedInput =
|
|
@@ -1254,15 +1333,14 @@ export async function runRootCommand(
|
|
|
1254
1333
|
// Auto-start Telegram Remote gateway if enabled in settings
|
|
1255
1334
|
if (!parsedArgs.print && !autoPrint) await maybeAutostartTelegramRemote();
|
|
1256
1335
|
|
|
1257
|
-
// Apply model role overrides from CLI args or env vars (ephemeral, not persisted)
|
|
1258
|
-
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
if (smolModel || slowModel || planModel) {
|
|
1336
|
+
// Apply model role overrides from CLI args or env vars (ephemeral, not persisted).
|
|
1337
|
+
// Precedence per role: CLI flag > documented SKC_*_MODEL > legacy PI_*_MODEL.
|
|
1338
|
+
const roleOverrides = resolveModelRoleOverrides(parsedArgs);
|
|
1339
|
+
if (roleOverrides.smol || roleOverrides.slow || roleOverrides.plan) {
|
|
1262
1340
|
settingsInstance.overrideModelRoles({
|
|
1263
|
-
smol:
|
|
1264
|
-
slow:
|
|
1265
|
-
plan:
|
|
1341
|
+
...(roleOverrides.smol ? { smol: roleOverrides.smol } : {}),
|
|
1342
|
+
...(roleOverrides.slow ? { slow: roleOverrides.slow } : {}),
|
|
1343
|
+
...(roleOverrides.plan ? { plan: roleOverrides.plan } : {}),
|
|
1266
1344
|
});
|
|
1267
1345
|
}
|
|
1268
1346
|
|
|
@@ -1556,9 +1634,9 @@ export async function runRootCommand(
|
|
|
1556
1634
|
process.stdout.write(`${chalk.dim(`Model scope: ${modelList} ${chalk.gray("(Alt+N to cycle)")}`)}\n`);
|
|
1557
1635
|
}
|
|
1558
1636
|
|
|
1559
|
-
if ($
|
|
1637
|
+
if ($pickenv("SKC_TIMING", "PI_TIMING")) {
|
|
1560
1638
|
logger.printTimings();
|
|
1561
|
-
exitForTiming = $
|
|
1639
|
+
exitForTiming = $pickenv("SKC_TIMING", "PI_TIMING") === "x";
|
|
1562
1640
|
}
|
|
1563
1641
|
|
|
1564
1642
|
if (!exitForTiming) {
|
|
@@ -1603,7 +1681,7 @@ export async function runRootCommand(
|
|
|
1603
1681
|
initialImages,
|
|
1604
1682
|
suppressProcessExit: deps.suppressProcessExit,
|
|
1605
1683
|
});
|
|
1606
|
-
if ($
|
|
1684
|
+
if ($pickenv("SKC_TIMING", "PI_TIMING")) {
|
|
1607
1685
|
logger.printTimings();
|
|
1608
1686
|
}
|
|
1609
1687
|
} finally {
|
package/src/memories/index.ts
CHANGED
|
@@ -976,6 +976,11 @@ function redactSecrets(input: string): string {
|
|
|
976
976
|
/(?:sk|pk|rk|tok|key|secret|token|password)[-_A-Za-z0-9]{12,}/g,
|
|
977
977
|
/[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g,
|
|
978
978
|
/(?:AKIA|ASIA)[A-Z0-9]{16}/g,
|
|
979
|
+
// GitHub tokens carry no keyword the first pattern recognizes, so without
|
|
980
|
+
// this they reached MEMORY.md and memory_summary.md verbatim — and the
|
|
981
|
+
// summary is injected into every later session. Same shapes the
|
|
982
|
+
// contribution-prep scrubber already covers.
|
|
983
|
+
/\b(?:gh[opsur]_[A-Za-z0-9_]{12,}|github_pat_[A-Za-z0-9_]{12,})\b/g,
|
|
979
984
|
];
|
|
980
985
|
for (const pattern of patterns) {
|
|
981
986
|
out = out.replace(pattern, "[REDACTED]");
|
|
@@ -983,6 +988,11 @@ function redactSecrets(input: string): string {
|
|
|
983
988
|
return out;
|
|
984
989
|
}
|
|
985
990
|
|
|
991
|
+
/** Secret scrubbing applied to every phase-2 consolidation output. Test seam. */
|
|
992
|
+
export function redactMemorySecretsForTesting(input: string): string {
|
|
993
|
+
return redactSecrets(input);
|
|
994
|
+
}
|
|
995
|
+
|
|
986
996
|
function sanitizeSkillName(name: string): string {
|
|
987
997
|
return name
|
|
988
998
|
.toLowerCase()
|
package/src/modes/DESIGN.md
CHANGED
|
@@ -94,6 +94,11 @@ empty space and list density for an operational setup flow.
|
|
|
94
94
|
removing line breaks. Notification secrets will use the dedicated masked
|
|
95
95
|
input from Work item 6; they must never appear in list values, descriptions,
|
|
96
96
|
previews, artifacts, or logs.
|
|
97
|
+
### Shortcut labels and binding authority
|
|
98
|
+
|
|
99
|
+
Keybinding configuration is a portable canonical grammar: textual key IDs use `ctrl`, `alt`, `shift`, and `super` plus a key name (for example, `ctrl+p` or `alt+enter`). Do not serialize or require display-only labels. Runtime UI renders those IDs through the shared formatter for its explicit platform context; macOS uses MacBook-style glyphs (`⌃`, `⌥`, `⇧`, `⌘`, `↩`, `⎋`, `⇥`, `⌫`, `⌦`, and arrow glyphs) while other platforms use textual labels. A glyph is never configuration syntax.
|
|
100
|
+
|
|
101
|
+
Static onboarding and generated documentation have authority only over shipped defaults. Keep generated tables host-independent by showing canonical textual IDs, not the capture host's labels. The runtime `KeybindingsManager` owns the effective binding set after user remaps and extensions load; `/hotkeys` and runtime hints must render that effective set with the platform context injected by their host. Do not let a static onboarding hint imply that it reflects remaps.
|
|
97
102
|
|
|
98
103
|
### Status, errors, confirmation, and disabled work
|
|
99
104
|
|
|
@@ -256,3 +261,50 @@ record both manifest counts as 108 plus CJK review results.
|
|
|
256
261
|
|
|
257
262
|
No raw third-party design corpus, screenshot, or reference asset is stored by
|
|
258
263
|
this workflow.
|
|
264
|
+
|
|
265
|
+
## Sticky transcript viewport contract
|
|
266
|
+
|
|
267
|
+
Live mode remains in natural terminal flow. Entering manual history makes the
|
|
268
|
+
application-owned transcript lane scrollable while the status line and every
|
|
269
|
+
later direct composer child are a fixed suffix at the bottom. PageUp/PageDown
|
|
270
|
+
move by the transcript capacity; the wheel remains three rows. A focused editor
|
|
271
|
+
keeps focus, and ordinary editor input or paste follows live before processing
|
|
272
|
+
that input.
|
|
273
|
+
|
|
274
|
+
Manual output has one bounded boolean indication, exactly **`New output — type
|
|
275
|
+
to follow`**. It is not a count. New visible agent/tool/extension output may set
|
|
276
|
+
it while manual; reflow, transient chrome, reconciliation, and user input may
|
|
277
|
+
not. Following clears it only after a successful live repaint. Manual-era output
|
|
278
|
+
is authoritative in the application transcript but is never retroactively
|
|
279
|
+
replayed into native host scrollback; subsequent ordinary live output follows
|
|
280
|
+
normal host behavior.
|
|
281
|
+
|
|
282
|
+
The transcript is the only selectable coordinate space. Pinned status/composer
|
|
283
|
+
chrome, notices, blank rows, and overlays never enter selection or copied text;
|
|
284
|
+
CJK selection clamping remains directional and grapheme/cell aware. Under
|
|
285
|
+
constrained height the notice drops first, then decorative pet and low-priority
|
|
286
|
+
hooks. Focused editor/cursor, status, and normal hooks outrank those rows; zero
|
|
287
|
+
transcript capacity is valid and must not corrupt cursor geometry.
|
|
288
|
+
|
|
289
|
+
At narrow widths use ANSI-aware terminal-cell measurement. ASCII/no-color keeps
|
|
290
|
+
textual state without SGR. Korean, Japanese, Chinese, and mixed CJK/Latin prose
|
|
291
|
+
must wrap at semantic phrase boundaries, never through an action/status label or
|
|
292
|
+
short identifier; a semantic CJK break is a visual-QA failure.
|
|
293
|
+
|
|
294
|
+
### Sticky viewport deterministic visual QA
|
|
295
|
+
|
|
296
|
+
`test/fixtures/tui/sticky-viewport-showcase.ts` is a fixed-clock, no-network,
|
|
297
|
+
first-party harness that starts the production `TUI` over a `VirtualTerminal`.
|
|
298
|
+
It constructs transcript, status, hooks, and the real composer as children,
|
|
299
|
+
then drives the live/manual viewport path before capturing the terminal frame.
|
|
300
|
+
Capture with `bun packages/coding-agent/scripts/capture-sticky-viewport-showcase.ts
|
|
301
|
+
--out .skc/qa/sticky-viewport-<run>` and verify with the paired `--root` script.
|
|
302
|
+
The immutable matrix has exactly 20 keys: `live-overflow`, `manual-history`,
|
|
303
|
+
`manual-new-output`, `multiline-editor-hooks-pet`, `capacity-many`,
|
|
304
|
+
`capacity-one`, `capacity-zero`, and `selection-boundary` at both 80x24 and
|
|
305
|
+
120x36 Unicode/color; plus `manual-new-output/80x24/ascii-no-color`,
|
|
306
|
+
`capacity-zero/48x10/ascii-no-color`,
|
|
307
|
+
`multiline-editor-hooks-pet/48x10/unicode-color`, and
|
|
308
|
+
`narrow-cjk/48x10/unicode-color`. Do not add or replace a manual-follow case.
|
|
309
|
+
|
|
310
|
+
Each key has only `terminal.txt`, ANSI-preserving `terminal-ansi.txt`, `terminal.html`, and `metadata.json`; the manifest records SHA-256 and byte length. Per-key metadata binds immutable font/render assumptions and the ANSI-aware wrapping/truncation policy. `VirtualTerminal` reconstructs ANSI from visible xterm cells, including cell padding, palette/RGB colors, attributes, and inverse video; plain text is always the stripped reconstruction. The verifier owns an independent literal 20-key oracle and fails closed unless stripped ANSI equals text, `terminal.html` equals the exported canonical `ansiToHtml(terminal-ansi.txt)` byte-for-byte (including its complete document envelope and global CSS), HTML independently preserves the ANSI style-run text, every retained row has the exact `Bun.stringWidth` cell width (including trailing spaces), and `ansi_mode` agrees with required Unicode color SGR or ASCII/no-color output. Every metadata entry has exact CJK phrase-boundary metadata: the narrow-CJK key has only the three canonical boundaries in order and every other key has `[]`. Manual captures prove successful production wheel and PageUp paths and retain observable historical transcript-row evidence. It validates exact payload paths (no duplicates or traversal), immutable source/output revisions, state/status/suffix order, notice cardinality, capacity, actual mouse-copied transcript-only selection, composer, CJK, and provenance invariants. `review-input.json` binds the exact manifest digest, capture author/executor identity, acceptance/design versions, required artifacts, narrow-CJK boundaries, and deterministic host matrix. `--require-independent-review` requires an attestation with an exact root key set; exact per-key result and artifact-check key sets; exact defect `{ description, accepted }` keys with a trimmed, nonblank description; canonical trimmed reviewer identity distinct from both bound identities; the independent-terminal-reviewer role; fixture revision; expected and observed counts of 20; exact checked keys; accepted per-key artifact-check/notes results; accepted artifact/CJK/host decisions; bound digest; and final `accept`. Any malformed, incomplete, or extra attestation content fails closed.
|