@jstn-sdk/rcs 0.1.0 → 0.1.6
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/README.md +154 -101
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +0 -101
- package/dist/agents/definitions.js.map +1 -1
- package/dist/blueprint/runtime.d.ts +52 -0
- package/dist/blueprint/runtime.d.ts.map +1 -0
- package/dist/{ralplan → blueprint}/runtime.js +19 -19
- package/dist/blueprint/runtime.js.map +1 -0
- package/dist/catalog/reader.d.ts.map +1 -1
- package/dist/catalog/reader.js +8 -2
- package/dist/catalog/reader.js.map +1 -1
- package/dist/catalog/schema.js +1 -1
- package/dist/catalog/schema.js.map +1 -1
- package/dist/cli/forge.d.ts +17 -0
- package/dist/cli/{ralph.d.ts.map → forge.d.ts.map} +1 -1
- package/dist/cli/{ralph.js → forge.js} +82 -82
- package/dist/cli/{ralph.js.map → forge.js.map} +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +20 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +2 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/star-prompt.js +2 -2
- package/dist/cli/star-prompt.js.map +1 -1
- package/dist/cli/state.js +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +3 -2
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +9 -1
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/config/generator.d.ts +1 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +1 -1
- package/dist/config/generator.js.map +1 -1
- package/dist/forge/contract.d.ts +17 -0
- package/dist/{ralph → forge}/contract.d.ts.map +1 -1
- package/dist/{ralph → forge}/contract.js +16 -16
- package/dist/{ralph → forge}/contract.js.map +1 -1
- package/dist/{ralph → forge}/persistence.d.ts +5 -5
- package/dist/{ralph → forge}/persistence.d.ts.map +1 -1
- package/dist/{ralph → forge}/persistence.js +7 -6
- package/dist/forge/persistence.js.map +1 -0
- package/dist/hooks/agents-overlay.d.ts +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +37 -31
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +82 -14
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +8 -8
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +94 -64
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +9 -11
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +10 -21
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/task-size-detector.js +2 -2
- package/dist/hooks/task-size-detector.js.map +1 -1
- package/dist/hooks/triage-state.d.ts +1 -1
- package/dist/hooks/triage-state.js +1 -1
- package/dist/hud/colors.d.ts +2 -2
- package/dist/hud/colors.js +2 -2
- package/dist/hud/render.js +21 -21
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts +3 -3
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +18 -15
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/types.d.ts +6 -6
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +36 -2
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +1 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +4 -1
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/mcp/state-server.js +2 -2
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/base.d.ts +2 -2
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +29 -26
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +7 -1
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +39 -6
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/pipeline/index.d.ts +7 -6
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +5 -4
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts +5 -5
- package/dist/pipeline/orchestrator.js +25 -25
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/blueprint.d.ts +25 -0
- package/dist/pipeline/stages/blueprint.d.ts.map +1 -0
- package/dist/pipeline/stages/{ralplan.js → blueprint.js} +16 -16
- package/dist/pipeline/stages/blueprint.js.map +1 -0
- package/dist/pipeline/stages/code-review.d.ts +2 -2
- package/dist/pipeline/stages/code-review.js +6 -6
- package/dist/pipeline/stages/code-review.js.map +1 -1
- package/dist/pipeline/stages/forge-verify.d.ts +50 -0
- package/dist/pipeline/stages/forge-verify.d.ts.map +1 -0
- package/dist/pipeline/stages/{ralph-verify.js → forge-verify.js} +21 -24
- package/dist/pipeline/stages/forge-verify.js.map +1 -0
- package/dist/pipeline/stages/team-exec.d.ts +1 -1
- package/dist/pipeline/stages/team-exec.js +19 -19
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/pipeline/types.d.ts +12 -12
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +1 -1
- package/dist/planning/artifacts.d.ts +3 -4
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +2 -3
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/question/policy.js +1 -1
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +70 -13
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/scripts/codex-native-hook.js +30 -30
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/eval/eval-cross-server-party-flow.d.ts +3 -0
- package/dist/scripts/eval/eval-cross-server-party-flow.d.ts.map +1 -0
- package/dist/scripts/eval/eval-cross-server-party-flow.js +12 -0
- package/dist/scripts/eval/eval-cross-server-party-flow.js.map +1 -0
- package/dist/scripts/eval/eval-gui-onboarding-clarity.d.ts +3 -0
- package/dist/scripts/eval/eval-gui-onboarding-clarity.d.ts.map +1 -0
- package/dist/scripts/eval/eval-gui-onboarding-clarity.js +17 -0
- package/dist/scripts/eval/eval-gui-onboarding-clarity.js.map +1 -0
- package/dist/scripts/eval/eval-liveops-reward-loop-balance.d.ts +3 -0
- package/dist/scripts/eval/eval-liveops-reward-loop-balance.d.ts.map +1 -0
- package/dist/scripts/eval/eval-liveops-reward-loop-balance.js +12 -0
- package/dist/scripts/eval/eval-liveops-reward-loop-balance.js.map +1 -0
- package/dist/scripts/eval/eval-profile-datastore-recovery.d.ts +3 -0
- package/dist/scripts/eval/eval-profile-datastore-recovery.d.ts.map +1 -0
- package/dist/scripts/eval/eval-profile-datastore-recovery.js +17 -0
- package/dist/scripts/eval/eval-profile-datastore-recovery.js.map +1 -0
- package/dist/scripts/eval/eval-remote-contract-hardening.d.ts +3 -0
- package/dist/scripts/eval/eval-remote-contract-hardening.d.ts.map +1 -0
- package/dist/scripts/eval/eval-remote-contract-hardening.js +17 -0
- package/dist/scripts/eval/eval-remote-contract-hardening.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +140 -139
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/forge-session-resume.d.ts +23 -0
- package/dist/scripts/notify-hook/{ralph-session-resume.d.ts.map → forge-session-resume.d.ts.map} +1 -1
- package/dist/scripts/notify-hook/{ralph-session-resume.js → forge-session-resume.js} +37 -36
- package/dist/scripts/notify-hook/{ralph-session-resume.js.map → forge-session-resume.js.map} +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +34 -4
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/visual-verdict.js +3 -3
- package/dist/scripts/notify-hook.js +9 -9
- package/dist/scripts/run-test-files.js +1 -1
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/surface-taxonomy.d.ts +23 -0
- package/dist/scripts/surface-taxonomy.d.ts.map +1 -0
- package/dist/scripts/surface-taxonomy.js +271 -0
- package/dist/scripts/surface-taxonomy.js.map +1 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +5 -4
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/tmux-hook-engine.d.ts +1 -1
- package/dist/scripts/tmux-hook-engine.d.ts.map +1 -1
- package/dist/scripts/tmux-hook-engine.js +29 -20
- package/dist/scripts/tmux-hook-engine.js.map +1 -1
- package/dist/state/operations.d.ts +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +18 -18
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +13 -1
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +38 -17
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition.d.ts +6 -5
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +27 -15
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/contracts.d.ts +1 -1
- package/dist/team/contracts.js +2 -2
- package/dist/team/followup-planner.d.ts +2 -2
- package/dist/team/followup-planner.d.ts.map +1 -1
- package/dist/team/followup-planner.js +16 -14
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/idle-nudge.d.ts.map +1 -1
- package/dist/team/idle-nudge.js +3 -2
- package/dist/team/idle-nudge.js.map +1 -1
- package/dist/team/leader-activity.js +1 -1
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +4 -1
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/orchestrator.js +4 -4
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/role-router.js +3 -3
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +4 -1
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/tmux-session.d.ts +4 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +42 -9
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worktree.d.ts +1 -1
- package/dist/utils/platform-command.d.ts.map +1 -1
- package/dist/utils/platform-command.js +9 -0
- package/dist/utils/platform-command.js.map +1 -1
- package/dist/verification/verifier.d.ts +1 -1
- package/dist/verification/verifier.js +2 -2
- package/docs/STATE_MODEL.md +24 -24
- package/docs/agents.html +8 -16
- package/docs/archive/README.md +15 -0
- package/docs/{prompt-migration-changelog.md → archive/prompt-migration-changelog.md} +0 -11
- package/docs/{release-body-0.9.0.md → archive/release-body-0.9.0.md} +6 -24
- package/docs/{release-body-0.9.1.md → archive/release-body-0.9.1.md} +3 -3
- package/docs/codex-native-hooks.md +4 -4
- package/docs/contracts/forge-cancel-contract.md +20 -0
- package/docs/contracts/forge-state-contract.md +52 -0
- package/docs/contracts/multi-state-transition-contract.md +5 -5
- package/docs/contracts/multi-state-transition-review.md +3 -3
- package/docs/contracts/repo-aware-team-dag-decomposition.md +1 -1
- package/docs/contracts/rust-runtime-thin-adapter-contract.md +1 -1
- package/docs/contracts/team-startup-dispatch-latency.md +1 -1
- package/docs/getting-started.html +11 -1
- package/docs/guidance-schema.md +6 -3
- package/docs/index.html +55 -4
- package/docs/integrations.html +4 -3
- package/docs/issues/team-forge-followup-team.md +38 -0
- package/docs/openclaw-integration.md +2 -2
- package/docs/prompt-guidance-contract.md +11 -11
- package/docs/prs/{dev-deprecate-team-ralph.md → dev-deprecate-team-forge.md} +27 -27
- package/docs/prs/{dev-fix-ralph-live-pane-invariant.md → dev-fix-forge-live-pane-invariant.md} +7 -7
- package/docs/prs/{dev-team-ralph-workflow-positioning.md → dev-team-forge-workflow-positioning.md} +7 -7
- package/docs/qa/forge-persistence-gate.md +20 -0
- package/docs/qa/rust-runtime-thin-adapter-gate.md +31 -40
- package/docs/readme/README.de.md +14 -0
- package/docs/readme/README.el.md +14 -0
- package/docs/readme/README.es.md +14 -0
- package/docs/readme/README.fr.md +14 -0
- package/docs/readme/README.it.md +14 -0
- package/docs/readme/README.ja.md +14 -0
- package/docs/readme/README.ko.md +14 -0
- package/docs/readme/README.pl.md +14 -0
- package/docs/readme/README.pt.md +14 -0
- package/docs/readme/README.ru.md +14 -0
- package/docs/readme/README.tr.md +14 -0
- package/docs/readme/README.uk.md +14 -0
- package/docs/readme/README.vi.md +14 -0
- package/docs/readme/README.zh-TW.md +14 -0
- package/docs/readme/README.zh.md +14 -0
- package/docs/readme/rcs-cover.svg +75 -0
- package/docs/reference/canonical-vocabulary.md +106 -0
- package/docs/reference/forge-parity-matrix.md +26 -0
- package/docs/reference/forge-upstream-baseline.md +32 -0
- package/docs/reference/rcs-config-schema-routing.md +5 -5
- package/docs/reference/roblox-pre-action-protocol.md +4 -0
- package/docs/reference/roblox-taxonomy-migration-plan.md +46 -0
- package/docs/reference/roblox-workspace-standard.md +83 -0
- package/docs/reference/robloxstudio-mcp-compatibility.md +117 -0
- package/docs/reference/semantic-design-system.md +110 -0
- package/docs/reference/surface-map.md +131 -0
- package/docs/reference/team-allocation-rebalance-policy.md +1 -1
- package/docs/release-notes-v0.1.0.md +1 -1
- package/docs/release-notes-v0.1.1.md +49 -0
- package/docs/release-notes-v0.1.6.md +27 -0
- package/docs/reports/open-prs-dev-readiness-2026-04-09.md +2 -2
- package/docs/shared/agent-tiers.md +3 -3
- package/docs/skills.html +10 -12
- package/docs/troubleshooting.md +1 -1
- package/package.json +20 -13
- package/plugins/roblox-ai-os-creator-skills/.codex-plugin/plugin.json +1 -1
- package/plugins/roblox-ai-os-creator-skills/docs/reference/roblox-pre-action-protocol.md +4 -0
- package/plugins/roblox-ai-os-creator-skills/skills/ai-slop-cleaner/SKILL.md +14 -7
- package/plugins/roblox-ai-os-creator-skills/skills/analyze/SKILL.md +9 -2
- package/plugins/roblox-ai-os-creator-skills/skills/ask-claude/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/ask-gemini/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/autoforge/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/autopilot/SKILL.md +48 -41
- package/plugins/roblox-ai-os-creator-skills/skills/autoresearch/SKILL.md +8 -1
- package/plugins/roblox-ai-os-creator-skills/skills/blueprint/SKILL.md +227 -9
- package/plugins/roblox-ai-os-creator-skills/skills/blueprint-loop/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/blueprint-psych/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/blueprint-retention/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/blueprint-social/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/brief/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/brief-audience/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/brief-motivation/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/cancel/SKILL.md +59 -52
- package/plugins/roblox-ai-os-creator-skills/skills/code-review/SKILL.md +30 -24
- package/plugins/roblox-ai-os-creator-skills/skills/configure-notifications/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/crew/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/deep-interview/SKILL.md +25 -18
- package/plugins/roblox-ai-os-creator-skills/skills/doctor/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge/SKILL.md +174 -11
- package/plugins/roblox-ai-os-creator-skills/skills/forge-community/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-daily-loop/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-event-loop/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-fomo/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-mastery/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-progression/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-reward-loop/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/forge-status/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/help/SKILL.md +8 -1
- package/plugins/roblox-ai-os-creator-skills/skills/hud/SKILL.md +16 -9
- package/plugins/roblox-ai-os-creator-skills/skills/note/SKILL.md +8 -1
- package/plugins/roblox-ai-os-creator-skills/skills/pipeline/SKILL.md +18 -11
- package/plugins/roblox-ai-os-creator-skills/skills/plan/SKILL.md +36 -29
- package/plugins/roblox-ai-os-creator-skills/skills/rcs-setup/SKILL.md +8 -1
- package/plugins/roblox-ai-os-creator-skills/skills/security-review/SKILL.md +120 -236
- package/plugins/roblox-ai-os-creator-skills/skills/skill/SKILL.md +20 -13
- package/plugins/roblox-ai-os-creator-skills/skills/team/SKILL.md +17 -11
- package/plugins/roblox-ai-os-creator-skills/skills/trace/SKILL.md +7 -0
- package/plugins/roblox-ai-os-creator-skills/skills/ultraqa/SKILL.md +10 -3
- package/plugins/roblox-ai-os-creator-skills/skills/ultrawork/SKILL.md +19 -12
- package/plugins/roblox-ai-os-creator-skills/skills/{visual-ralph → visual-forge}/SKILL.md +36 -27
- package/plugins/roblox-ai-os-creator-skills/skills/visual-verdict/SKILL.md +9 -2
- package/plugins/roblox-ai-os-creator-skills/skills/wiki/SKILL.md +10 -3
- package/plugins/roblox-ai-os-creator-skills/skills/worker/SKILL.md +16 -7
- package/plugins/roblox-ai-os-creator-skills/templates/roblox/pre-action-plan.md +1 -0
- package/prompts/analyst.md +7 -0
- package/prompts/architect.md +11 -4
- package/prompts/build-fixer.md +7 -0
- package/prompts/code-reviewer.md +9 -2
- package/prompts/code-simplifier.md +4 -0
- package/prompts/critic.md +13 -6
- package/prompts/debugger.md +8 -1
- package/prompts/dependency-expert.md +8 -1
- package/prompts/designer.md +20 -10
- package/prompts/executor.md +7 -0
- package/prompts/explore-harness.md +7 -0
- package/prompts/explore.md +7 -0
- package/prompts/git-master.md +8 -1
- package/prompts/planner.md +10 -3
- package/prompts/researcher.md +7 -0
- package/prompts/security-reviewer.md +76 -92
- package/prompts/sisyphus-lite.md +7 -0
- package/prompts/team-executor.md +7 -0
- package/prompts/team-orchestrator.md +9 -2
- package/prompts/test-engineer.md +11 -3
- package/prompts/verifier.md +7 -0
- package/prompts/vision.md +9 -2
- package/prompts/writer.md +11 -4
- package/skills/.agents/skills/roblox-animations/SKILL.md +220 -0
- package/skills/.agents/skills/roblox-datastores/SKILL.md +219 -0
- package/skills/.agents/skills/roblox-gui/SKILL.md +192 -0
- package/skills/.agents/skills/roblox-monetization/SKILL.md +208 -0
- package/skills/.agents/skills/roblox-performance/SKILL.md +230 -0
- package/skills/.agents/skills/roblox-remote-events/SKILL.md +199 -0
- package/skills/.agents/skills/roblox-security/SKILL.md +236 -0
- package/skills/ai-slop-cleaner/SKILL.md +14 -7
- package/skills/analyze/SKILL.md +9 -2
- package/skills/ask-claude/SKILL.md +7 -0
- package/skills/ask-gemini/SKILL.md +7 -0
- package/skills/autoforge/SKILL.md +7 -0
- package/skills/autopilot/SKILL.md +48 -41
- package/skills/autoresearch/SKILL.md +8 -1
- package/skills/blueprint/SKILL.md +227 -9
- package/skills/blueprint-loop/SKILL.md +7 -0
- package/skills/blueprint-psych/SKILL.md +7 -0
- package/skills/blueprint-retention/SKILL.md +7 -0
- package/skills/blueprint-social/SKILL.md +7 -0
- package/skills/brief/SKILL.md +7 -0
- package/skills/brief-audience/SKILL.md +7 -0
- package/skills/brief-motivation/SKILL.md +7 -0
- package/skills/build-fix/SKILL.md +9 -2
- package/skills/cancel/SKILL.md +59 -52
- package/skills/code-review/SKILL.md +30 -24
- package/skills/configure-notifications/SKILL.md +7 -0
- package/skills/crew/SKILL.md +7 -0
- package/skills/deep-interview/SKILL.md +25 -18
- package/skills/deepsearch/SKILL.md +7 -0
- package/skills/doctor/SKILL.md +7 -0
- package/skills/ecomode/SKILL.md +9 -2
- package/skills/forge/SKILL.md +174 -11
- package/skills/forge-community/SKILL.md +7 -0
- package/skills/forge-daily-loop/SKILL.md +7 -0
- package/skills/forge-event-loop/SKILL.md +7 -0
- package/skills/forge-fomo/SKILL.md +7 -0
- package/skills/{ralph-init → forge-init}/SKILL.md +20 -13
- package/skills/forge-mastery/SKILL.md +7 -0
- package/skills/forge-progression/SKILL.md +7 -0
- package/skills/forge-reward-loop/SKILL.md +7 -0
- package/skills/forge-status/SKILL.md +7 -0
- package/skills/git-master/SKILL.md +7 -0
- package/skills/help/SKILL.md +8 -1
- package/skills/hud/SKILL.md +16 -9
- package/skills/note/SKILL.md +8 -1
- package/skills/pipeline/SKILL.md +18 -11
- package/skills/plan/SKILL.md +36 -29
- package/skills/rcs-setup/SKILL.md +8 -1
- package/skills/review/SKILL.md +7 -0
- package/skills/security-review/SKILL.md +120 -236
- package/skills/skill/SKILL.md +20 -13
- package/skills/skills-lock.json +47 -0
- package/skills/swarm/SKILL.md +8 -1
- package/skills/tdd/SKILL.md +7 -0
- package/skills/team/SKILL.md +17 -11
- package/skills/trace/SKILL.md +7 -0
- package/skills/ultraqa/SKILL.md +10 -3
- package/skills/ultrawork/SKILL.md +19 -12
- package/skills/{visual-ralph → visual-forge}/SKILL.md +36 -27
- package/skills/visual-verdict/SKILL.md +9 -2
- package/skills/web-clone/SKILL.md +14 -7
- package/skills/wiki/SKILL.md +10 -3
- package/skills/worker/SKILL.md +16 -7
- package/src/scripts/__tests__/codex-native-hook.test.ts +386 -319
- package/src/scripts/__tests__/run-test-files.test.ts +6 -4
- package/src/scripts/__tests__/verify-native-agents.test.ts +16 -16
- package/src/scripts/codex-native-hook.ts +34 -34
- package/src/scripts/eval/eval-cross-server-party-flow.ts +14 -0
- package/src/scripts/eval/eval-gui-onboarding-clarity.ts +20 -0
- package/src/scripts/eval/eval-liveops-reward-loop-balance.ts +14 -0
- package/src/scripts/eval/eval-profile-datastore-recovery.ts +20 -0
- package/src/scripts/eval/eval-remote-contract-hardening.ts +20 -0
- package/src/scripts/notify-fallback-watcher.ts +147 -146
- package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +24 -10
- package/src/scripts/notify-hook/{ralph-session-resume.ts → forge-session-resume.ts} +45 -43
- package/src/scripts/notify-hook/team-dispatch.ts +31 -4
- package/src/scripts/notify-hook/visual-verdict.ts +3 -3
- package/src/scripts/notify-hook.ts +10 -10
- package/src/scripts/run-test-files.ts +1 -1
- package/src/scripts/surface-taxonomy.ts +316 -0
- package/src/scripts/sync-plugin-mirror.ts +5 -4
- package/src/scripts/tmux-hook-engine.ts +31 -19
- package/templates/AGENTS.md +24 -15
- package/templates/catalog-manifest.json +5 -88
- package/templates/roblox/pre-action-plan.md +1 -0
- package/templates/roblox/robloxstudio-mcp.codex.json +18 -0
- package/templates/roblox/robloxstudio-mcp.windows.json +22 -0
- package/dist/adapt/__tests__/foundation.test.d.ts +0 -2
- package/dist/adapt/__tests__/foundation.test.d.ts.map +0 -1
- package/dist/adapt/__tests__/foundation.test.js +0 -171
- package/dist/adapt/__tests__/foundation.test.js.map +0 -1
- package/dist/adapt/__tests__/hermes.test.d.ts +0 -2
- package/dist/adapt/__tests__/hermes.test.d.ts.map +0 -1
- package/dist/adapt/__tests__/hermes.test.js +0 -137
- package/dist/adapt/__tests__/hermes.test.js.map +0 -1
- package/dist/agents/__tests__/definitions.test.d.ts +0 -2
- package/dist/agents/__tests__/definitions.test.d.ts.map +0 -1
- package/dist/agents/__tests__/definitions.test.js +0 -62
- package/dist/agents/__tests__/definitions.test.js.map +0 -1
- package/dist/agents/__tests__/native-config.test.d.ts +0 -2
- package/dist/agents/__tests__/native-config.test.d.ts.map +0 -1
- package/dist/agents/__tests__/native-config.test.js +0 -278
- package/dist/agents/__tests__/native-config.test.js.map +0 -1
- package/dist/autoresearch/__tests__/contracts.test.d.ts +0 -2
- package/dist/autoresearch/__tests__/contracts.test.d.ts.map +0 -1
- package/dist/autoresearch/__tests__/contracts.test.js +0 -127
- package/dist/autoresearch/__tests__/contracts.test.js.map +0 -1
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.d.ts +0 -2
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.d.ts.map +0 -1
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.js +0 -356
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.js.map +0 -1
- package/dist/autoresearch/__tests__/runtime.test.d.ts +0 -2
- package/dist/autoresearch/__tests__/runtime.test.d.ts.map +0 -1
- package/dist/autoresearch/__tests__/runtime.test.js +0 -218
- package/dist/autoresearch/__tests__/runtime.test.js.map +0 -1
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts +0 -2
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts.map +0 -1
- package/dist/autoresearch/__tests__/skill-validation.test.js +0 -91
- package/dist/autoresearch/__tests__/skill-validation.test.js.map +0 -1
- package/dist/catalog/__tests__/generator.test.d.ts +0 -2
- package/dist/catalog/__tests__/generator.test.d.ts.map +0 -1
- package/dist/catalog/__tests__/generator.test.js +0 -49
- package/dist/catalog/__tests__/generator.test.js.map +0 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts +0 -2
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts.map +0 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +0 -83
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +0 -1
- package/dist/catalog/__tests__/schema.test.d.ts +0 -2
- package/dist/catalog/__tests__/schema.test.d.ts.map +0 -1
- package/dist/catalog/__tests__/schema.test.js +0 -91
- package/dist/catalog/__tests__/schema.test.js.map +0 -1
- package/dist/cli/__tests__/adapt-help.test.d.ts +0 -2
- package/dist/cli/__tests__/adapt-help.test.d.ts.map +0 -1
- package/dist/cli/__tests__/adapt-help.test.js +0 -37
- package/dist/cli/__tests__/adapt-help.test.js.map +0 -1
- package/dist/cli/__tests__/adapt.test.d.ts +0 -2
- package/dist/cli/__tests__/adapt.test.d.ts.map +0 -1
- package/dist/cli/__tests__/adapt.test.js +0 -62
- package/dist/cli/__tests__/adapt.test.js.map +0 -1
- package/dist/cli/__tests__/agents-init.test.d.ts +0 -2
- package/dist/cli/__tests__/agents-init.test.d.ts.map +0 -1
- package/dist/cli/__tests__/agents-init.test.js +0 -184
- package/dist/cli/__tests__/agents-init.test.js.map +0 -1
- package/dist/cli/__tests__/agents.test.d.ts +0 -2
- package/dist/cli/__tests__/agents.test.d.ts.map +0 -1
- package/dist/cli/__tests__/agents.test.js +0 -137
- package/dist/cli/__tests__/agents.test.js.map +0 -1
- package/dist/cli/__tests__/ask.test.d.ts +0 -2
- package/dist/cli/__tests__/ask.test.d.ts.map +0 -1
- package/dist/cli/__tests__/ask.test.js +0 -265
- package/dist/cli/__tests__/ask.test.js.map +0 -1
- package/dist/cli/__tests__/autoresearch-guided.test.d.ts +0 -2
- package/dist/cli/__tests__/autoresearch-guided.test.d.ts.map +0 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js +0 -365
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +0 -1
- package/dist/cli/__tests__/autoresearch.test.d.ts +0 -2
- package/dist/cli/__tests__/autoresearch.test.d.ts.map +0 -1
- package/dist/cli/__tests__/autoresearch.test.js +0 -203
- package/dist/cli/__tests__/autoresearch.test.js.map +0 -1
- package/dist/cli/__tests__/catalog-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/catalog-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/catalog-contract.test.js +0 -18
- package/dist/cli/__tests__/catalog-contract.test.js.map +0 -1
- package/dist/cli/__tests__/cleanup.test.d.ts +0 -2
- package/dist/cli/__tests__/cleanup.test.d.ts.map +0 -1
- package/dist/cli/__tests__/cleanup.test.js +0 -419
- package/dist/cli/__tests__/cleanup.test.js.map +0 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts +0 -2
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts.map +0 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +0 -210
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +0 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +0 -2
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +0 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.js +0 -122
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +0 -1
- package/dist/cli/__tests__/doctor-invalid-config.test.d.ts +0 -2
- package/dist/cli/__tests__/doctor-invalid-config.test.d.ts.map +0 -1
- package/dist/cli/__tests__/doctor-invalid-config.test.js +0 -52
- package/dist/cli/__tests__/doctor-invalid-config.test.js.map +0 -1
- package/dist/cli/__tests__/doctor-team.test.d.ts +0 -2
- package/dist/cli/__tests__/doctor-team.test.d.ts.map +0 -1
- package/dist/cli/__tests__/doctor-team.test.js +0 -299
- package/dist/cli/__tests__/doctor-team.test.js.map +0 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts +0 -2
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts.map +0 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +0 -438
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +0 -1
- package/dist/cli/__tests__/error-handling-warnings.test.d.ts +0 -2
- package/dist/cli/__tests__/error-handling-warnings.test.d.ts.map +0 -1
- package/dist/cli/__tests__/error-handling-warnings.test.js +0 -52
- package/dist/cli/__tests__/error-handling-warnings.test.js.map +0 -1
- package/dist/cli/__tests__/exec.test.d.ts +0 -2
- package/dist/cli/__tests__/exec.test.d.ts.map +0 -1
- package/dist/cli/__tests__/exec.test.js +0 -213
- package/dist/cli/__tests__/exec.test.js.map +0 -1
- package/dist/cli/__tests__/explore-windows-diagnostics.test.d.ts +0 -2
- package/dist/cli/__tests__/explore-windows-diagnostics.test.d.ts.map +0 -1
- package/dist/cli/__tests__/explore-windows-diagnostics.test.js +0 -17
- package/dist/cli/__tests__/explore-windows-diagnostics.test.js.map +0 -1
- package/dist/cli/__tests__/explore.test.d.ts +0 -2
- package/dist/cli/__tests__/explore.test.d.ts.map +0 -1
- package/dist/cli/__tests__/explore.test.js +0 -1090
- package/dist/cli/__tests__/explore.test.js.map +0 -1
- package/dist/cli/__tests__/hooks.test.d.ts +0 -2
- package/dist/cli/__tests__/hooks.test.d.ts.map +0 -1
- package/dist/cli/__tests__/hooks.test.js +0 -55
- package/dist/cli/__tests__/hooks.test.js.map +0 -1
- package/dist/cli/__tests__/index.test.d.ts +0 -2
- package/dist/cli/__tests__/index.test.d.ts.map +0 -1
- package/dist/cli/__tests__/index.test.js +0 -2259
- package/dist/cli/__tests__/index.test.js.map +0 -1
- package/dist/cli/__tests__/launch-fallback.test.d.ts +0 -2
- package/dist/cli/__tests__/launch-fallback.test.d.ts.map +0 -1
- package/dist/cli/__tests__/launch-fallback.test.js +0 -661
- package/dist/cli/__tests__/launch-fallback.test.js.map +0 -1
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts +0 -2
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts.map +0 -1
- package/dist/cli/__tests__/lifecycle-notifications.test.js +0 -48
- package/dist/cli/__tests__/lifecycle-notifications.test.js.map +0 -1
- package/dist/cli/__tests__/list.test.d.ts +0 -2
- package/dist/cli/__tests__/list.test.d.ts.map +0 -1
- package/dist/cli/__tests__/list.test.js +0 -38
- package/dist/cli/__tests__/list.test.js.map +0 -1
- package/dist/cli/__tests__/mcp-parity.test.d.ts +0 -2
- package/dist/cli/__tests__/mcp-parity.test.d.ts.map +0 -1
- package/dist/cli/__tests__/mcp-parity.test.js +0 -228
- package/dist/cli/__tests__/mcp-parity.test.js.map +0 -1
- package/dist/cli/__tests__/mcp-serve.test.d.ts +0 -2
- package/dist/cli/__tests__/mcp-serve.test.d.ts.map +0 -1
- package/dist/cli/__tests__/mcp-serve.test.js +0 -64
- package/dist/cli/__tests__/mcp-serve.test.js.map +0 -1
- package/dist/cli/__tests__/native-assets.test.d.ts +0 -2
- package/dist/cli/__tests__/native-assets.test.d.ts.map +0 -1
- package/dist/cli/__tests__/native-assets.test.js +0 -308
- package/dist/cli/__tests__/native-assets.test.js.map +0 -1
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.js +0 -11
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.js.map +0 -1
- package/dist/cli/__tests__/nested-help-routing.test.d.ts +0 -2
- package/dist/cli/__tests__/nested-help-routing.test.d.ts.map +0 -1
- package/dist/cli/__tests__/nested-help-routing.test.js +0 -96
- package/dist/cli/__tests__/nested-help-routing.test.js.map +0 -1
- package/dist/cli/__tests__/package-bin-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/package-bin-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +0 -177
- package/dist/cli/__tests__/package-bin-contract.test.js.map +0 -1
- package/dist/cli/__tests__/packaged-explore-harness-lock.d.ts +0 -3
- package/dist/cli/__tests__/packaged-explore-harness-lock.d.ts.map +0 -1
- package/dist/cli/__tests__/packaged-explore-harness-lock.js +0 -67
- package/dist/cli/__tests__/packaged-explore-harness-lock.js.map +0 -1
- package/dist/cli/__tests__/packaged-script-resolution.test.d.ts +0 -2
- package/dist/cli/__tests__/packaged-script-resolution.test.d.ts.map +0 -1
- package/dist/cli/__tests__/packaged-script-resolution.test.js +0 -19
- package/dist/cli/__tests__/packaged-script-resolution.test.js.map +0 -1
- package/dist/cli/__tests__/prompt-skill-sanitization.test.d.ts +0 -2
- package/dist/cli/__tests__/prompt-skill-sanitization.test.d.ts.map +0 -1
- package/dist/cli/__tests__/prompt-skill-sanitization.test.js +0 -48
- package/dist/cli/__tests__/prompt-skill-sanitization.test.js.map +0 -1
- package/dist/cli/__tests__/question.test.d.ts +0 -2
- package/dist/cli/__tests__/question.test.d.ts.map +0 -1
- package/dist/cli/__tests__/question.test.js +0 -633
- package/dist/cli/__tests__/question.test.js.map +0 -1
- package/dist/cli/__tests__/ralph-deslop-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/ralph-deslop-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/ralph-deslop-contract.test.js +0 -28
- package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +0 -1
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts +0 -2
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts.map +0 -1
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +0 -24
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +0 -1
- package/dist/cli/__tests__/ralph-prd-smoke.test.d.ts +0 -2
- package/dist/cli/__tests__/ralph-prd-smoke.test.d.ts.map +0 -1
- package/dist/cli/__tests__/ralph-prd-smoke.test.js +0 -167
- package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +0 -1
- package/dist/cli/__tests__/ralph.test.d.ts +0 -2
- package/dist/cli/__tests__/ralph.test.d.ts.map +0 -1
- package/dist/cli/__tests__/ralph.test.js +0 -256
- package/dist/cli/__tests__/ralph.test.js.map +0 -1
- package/dist/cli/__tests__/resume.test.d.ts +0 -2
- package/dist/cli/__tests__/resume.test.d.ts.map +0 -1
- package/dist/cli/__tests__/resume.test.js +0 -84
- package/dist/cli/__tests__/resume.test.js.map +0 -1
- package/dist/cli/__tests__/session-scoped-runtime.test.d.ts +0 -2
- package/dist/cli/__tests__/session-scoped-runtime.test.d.ts.map +0 -1
- package/dist/cli/__tests__/session-scoped-runtime.test.js +0 -146
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +0 -1
- package/dist/cli/__tests__/session-search-help.test.d.ts +0 -2
- package/dist/cli/__tests__/session-search-help.test.d.ts.map +0 -1
- package/dist/cli/__tests__/session-search-help.test.js +0 -76
- package/dist/cli/__tests__/session-search-help.test.js.map +0 -1
- package/dist/cli/__tests__/session-search.test.d.ts +0 -2
- package/dist/cli/__tests__/session-search.test.d.ts.map +0 -1
- package/dist/cli/__tests__/session-search.test.js +0 -77
- package/dist/cli/__tests__/session-search.test.js.map +0 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-agents-overwrite.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +0 -457
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +0 -1
- package/dist/cli/__tests__/setup-gh-star.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-gh-star.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-gh-star.test.js +0 -67
- package/dist/cli/__tests__/setup-gh-star.test.js.map +0 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +0 -189
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +0 -1
- package/dist/cli/__tests__/setup-install-mode.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-install-mode.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +0 -873
- package/dist/cli/__tests__/setup-install-mode.test.js.map +0 -1
- package/dist/cli/__tests__/setup-prompts-overwrite.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-prompts-overwrite.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js +0 -191
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +0 -1
- package/dist/cli/__tests__/setup-refresh.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-refresh.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-refresh.test.js +0 -591
- package/dist/cli/__tests__/setup-refresh.test.js.map +0 -1
- package/dist/cli/__tests__/setup-scope.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-scope.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-scope.test.js +0 -340
- package/dist/cli/__tests__/setup-scope.test.js.map +0 -1
- package/dist/cli/__tests__/setup-skill-validation.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-skill-validation.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-skill-validation.test.js +0 -44
- package/dist/cli/__tests__/setup-skill-validation.test.js.map +0 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.d.ts +0 -2
- package/dist/cli/__tests__/setup-skills-overwrite.test.d.ts.map +0 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +0 -295
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +0 -1
- package/dist/cli/__tests__/sidecar.test.d.ts +0 -2
- package/dist/cli/__tests__/sidecar.test.d.ts.map +0 -1
- package/dist/cli/__tests__/sidecar.test.js +0 -24
- package/dist/cli/__tests__/sidecar.test.js.map +0 -1
- package/dist/cli/__tests__/sparkshell-cli.test.d.ts +0 -2
- package/dist/cli/__tests__/sparkshell-cli.test.d.ts.map +0 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +0 -400
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +0 -1
- package/dist/cli/__tests__/sparkshell-packaging.test.d.ts +0 -2
- package/dist/cli/__tests__/sparkshell-packaging.test.d.ts.map +0 -1
- package/dist/cli/__tests__/sparkshell-packaging.test.js +0 -74
- package/dist/cli/__tests__/sparkshell-packaging.test.js.map +0 -1
- package/dist/cli/__tests__/star-prompt.test.d.ts +0 -2
- package/dist/cli/__tests__/star-prompt.test.d.ts.map +0 -1
- package/dist/cli/__tests__/star-prompt.test.js +0 -172
- package/dist/cli/__tests__/star-prompt.test.js.map +0 -1
- package/dist/cli/__tests__/state.test.d.ts +0 -2
- package/dist/cli/__tests__/state.test.d.ts.map +0 -1
- package/dist/cli/__tests__/state.test.js +0 -46
- package/dist/cli/__tests__/state.test.js.map +0 -1
- package/dist/cli/__tests__/team-decompose.test.d.ts +0 -2
- package/dist/cli/__tests__/team-decompose.test.d.ts.map +0 -1
- package/dist/cli/__tests__/team-decompose.test.js +0 -133
- package/dist/cli/__tests__/team-decompose.test.js.map +0 -1
- package/dist/cli/__tests__/team.test.d.ts +0 -2
- package/dist/cli/__tests__/team.test.d.ts.map +0 -1
- package/dist/cli/__tests__/team.test.js +0 -1820
- package/dist/cli/__tests__/team.test.js.map +0 -1
- package/dist/cli/__tests__/uninstall.test.d.ts +0 -2
- package/dist/cli/__tests__/uninstall.test.d.ts.map +0 -1
- package/dist/cli/__tests__/uninstall.test.js +0 -766
- package/dist/cli/__tests__/uninstall.test.js.map +0 -1
- package/dist/cli/__tests__/update.test.d.ts +0 -2
- package/dist/cli/__tests__/update.test.d.ts.map +0 -1
- package/dist/cli/__tests__/update.test.js +0 -589
- package/dist/cli/__tests__/update.test.js.map +0 -1
- package/dist/cli/__tests__/version-sync-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/version-sync-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/version-sync-contract.test.js +0 -41
- package/dist/cli/__tests__/version-sync-contract.test.js.map +0 -1
- package/dist/cli/__tests__/version.test.d.ts +0 -2
- package/dist/cli/__tests__/version.test.d.ts.map +0 -1
- package/dist/cli/__tests__/version.test.js +0 -21
- package/dist/cli/__tests__/version.test.js.map +0 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts +0 -2
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts.map +0 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +0 -31
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +0 -1
- package/dist/cli/ralph.d.ts +0 -17
- package/dist/compat/__tests__/doctor-contract.test.d.ts +0 -2
- package/dist/compat/__tests__/doctor-contract.test.d.ts.map +0 -1
- package/dist/compat/__tests__/doctor-contract.test.js +0 -108
- package/dist/compat/__tests__/doctor-contract.test.js.map +0 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.d.ts +0 -2
- package/dist/compat/__tests__/rust-runtime-compat.test.d.ts.map +0 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +0 -218
- package/dist/compat/__tests__/rust-runtime-compat.test.js.map +0 -1
- package/dist/config/__tests__/codex-hooks.test.d.ts +0 -2
- package/dist/config/__tests__/codex-hooks.test.d.ts.map +0 -1
- package/dist/config/__tests__/codex-hooks.test.js +0 -77
- package/dist/config/__tests__/codex-hooks.test.js.map +0 -1
- package/dist/config/__tests__/generator-idempotent.test.d.ts +0 -2
- package/dist/config/__tests__/generator-idempotent.test.d.ts.map +0 -1
- package/dist/config/__tests__/generator-idempotent.test.js +0 -882
- package/dist/config/__tests__/generator-idempotent.test.js.map +0 -1
- package/dist/config/__tests__/generator-notify.test.d.ts +0 -2
- package/dist/config/__tests__/generator-notify.test.d.ts.map +0 -1
- package/dist/config/__tests__/generator-notify.test.js +0 -343
- package/dist/config/__tests__/generator-notify.test.js.map +0 -1
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts +0 -2
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +0 -1
- package/dist/config/__tests__/generator-status-line-presets.test.js +0 -203
- package/dist/config/__tests__/generator-status-line-presets.test.js.map +0 -1
- package/dist/config/__tests__/mcp-registry.test.d.ts +0 -2
- package/dist/config/__tests__/mcp-registry.test.d.ts.map +0 -1
- package/dist/config/__tests__/mcp-registry.test.js +0 -190
- package/dist/config/__tests__/mcp-registry.test.js.map +0 -1
- package/dist/config/__tests__/models.test.d.ts +0 -2
- package/dist/config/__tests__/models.test.d.ts.map +0 -1
- package/dist/config/__tests__/models.test.js +0 -224
- package/dist/config/__tests__/models.test.js.map +0 -1
- package/dist/config/__tests__/wiki-config-contract.test.d.ts +0 -2
- package/dist/config/__tests__/wiki-config-contract.test.d.ts.map +0 -1
- package/dist/config/__tests__/wiki-config-contract.test.js +0 -19
- package/dist/config/__tests__/wiki-config-contract.test.js.map +0 -1
- package/dist/document-refresh/__tests__/enforcer.test.d.ts +0 -2
- package/dist/document-refresh/__tests__/enforcer.test.d.ts.map +0 -1
- package/dist/document-refresh/__tests__/enforcer.test.js +0 -128
- package/dist/document-refresh/__tests__/enforcer.test.js.map +0 -1
- package/dist/hooks/__tests__/agents-overlay.test.d.ts +0 -8
- package/dist/hooks/__tests__/agents-overlay.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +0 -644
- package/dist/hooks/__tests__/agents-overlay.test.js.map +0 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.js +0 -45
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/analyze-skill-contract.test.js +0 -48
- package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.d.ts +0 -2
- package/dist/hooks/__tests__/anti-slop-workflow.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +0 -146
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +0 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +0 -37
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/clawhip-event-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/clawhip-event-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/clawhip-event-contract.test.js +0 -37
- package/dist/hooks/__tests__/clawhip-event-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +0 -56
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/codebase-map.test.d.ts +0 -8
- package/dist/hooks/__tests__/codebase-map.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/codebase-map.test.js +0 -218
- package/dist/hooks/__tests__/codebase-map.test.js.map +0 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +0 -18
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js +0 -234
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +0 -1
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +0 -20
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +0 -213
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js +0 -43
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js +0 -38
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/explore-routing.test.d.ts +0 -2
- package/dist/hooks/__tests__/explore-routing.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/explore-routing.test.js +0 -43
- package/dist/hooks/__tests__/explore-routing.test.js.map +0 -1
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js +0 -69
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/keyword-detector.test.d.ts +0 -2
- package/dist/hooks/__tests__/keyword-detector.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +0 -1716
- package/dist/hooks/__tests__/keyword-detector.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-fallback-watcher.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +0 -3898
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +0 -786
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +0 -2397
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +0 -160
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +0 -1178
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-modules.test.d.ts +0 -9
- package/dist/hooks/__tests__/notify-hook-modules.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-modules.test.js +0 -529
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.js +0 -14
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +0 -682
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts +0 -9
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +0 -255
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +0 -162
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-session-scope.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +0 -301
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +0 -1510
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +0 -2879
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +0 -228
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +0 -35
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +0 -1589
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.d.ts +0 -10
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +0 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts +0 -11
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js +0 -266
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +0 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.d.ts +0 -2
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +0 -895
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +0 -1
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js +0 -61
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts +0 -2
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +0 -40
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.js +0 -11
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-guidance-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js +0 -38
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +0 -48
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.js +0 -11
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts +0 -5
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js +0 -34
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +0 -65
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js +0 -38
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js +0 -22
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/prompt-team-routing.test.d.ts +0 -2
- package/dist/hooks/__tests__/prompt-team-routing.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/prompt-team-routing.test.js +0 -49
- package/dist/hooks/__tests__/prompt-team-routing.test.js.map +0 -1
- package/dist/hooks/__tests__/session.test.d.ts +0 -2
- package/dist/hooks/__tests__/session.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/session.test.js +0 -322
- package/dist/hooks/__tests__/session.test.js.map +0 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/skill-guidance-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +0 -29
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/task-size-detector.test.d.ts +0 -2
- package/dist/hooks/__tests__/task-size-detector.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/task-size-detector.test.js +0 -330
- package/dist/hooks/__tests__/task-size-detector.test.js.map +0 -1
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js +0 -28
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +0 -1
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.d.ts +0 -2
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.js +0 -24
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.js.map +0 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.d.ts +0 -2
- package/dist/hooks/__tests__/tmux-hook-engine.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +0 -403
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +0 -1
- package/dist/hooks/__tests__/triage-config.test.d.ts +0 -2
- package/dist/hooks/__tests__/triage-config.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/triage-config.test.js +0 -211
- package/dist/hooks/__tests__/triage-config.test.js.map +0 -1
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts +0 -2
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/triage-heuristic.test.js +0 -285
- package/dist/hooks/__tests__/triage-heuristic.test.js.map +0 -1
- package/dist/hooks/__tests__/triage-state.test.d.ts +0 -2
- package/dist/hooks/__tests__/triage-state.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/triage-state.test.js +0 -426
- package/dist/hooks/__tests__/triage-state.test.js.map +0 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts +0 -2
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.js +0 -44
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +0 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts +0 -2
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +0 -35
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +0 -1
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts +0 -2
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts.map +0 -1
- package/dist/hooks/__tests__/wiki-docs-contract.test.js +0 -34
- package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +0 -1
- package/dist/hooks/code-simplifier/__tests__/index.test.d.ts +0 -2
- package/dist/hooks/code-simplifier/__tests__/index.test.d.ts.map +0 -1
- package/dist/hooks/code-simplifier/__tests__/index.test.js +0 -187
- package/dist/hooks/code-simplifier/__tests__/index.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/dispatcher.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +0 -242
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/events.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/events.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/events.test.js +0 -125
- package/dist/hooks/extensibility/__tests__/events.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js +0 -153
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/loader.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/loader.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/loader.test.js +0 -254
- package/dist/hooks/extensibility/__tests__/loader.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/logging.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/logging.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/logging.test.js +0 -74
- package/dist/hooks/extensibility/__tests__/logging.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +0 -202
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/runtime.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/runtime.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/runtime.test.js +0 -198
- package/dist/hooks/extensibility/__tests__/runtime.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.js +0 -32
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.js.map +0 -1
- package/dist/hooks/extensibility/__tests__/sdk.test.d.ts +0 -2
- package/dist/hooks/extensibility/__tests__/sdk.test.d.ts.map +0 -1
- package/dist/hooks/extensibility/__tests__/sdk.test.js +0 -479
- package/dist/hooks/extensibility/__tests__/sdk.test.js.map +0 -1
- package/dist/hud/__tests__/authority.test.d.ts +0 -2
- package/dist/hud/__tests__/authority.test.d.ts.map +0 -1
- package/dist/hud/__tests__/authority.test.js +0 -56
- package/dist/hud/__tests__/authority.test.js.map +0 -1
- package/dist/hud/__tests__/colors.test.d.ts +0 -2
- package/dist/hud/__tests__/colors.test.d.ts.map +0 -1
- package/dist/hud/__tests__/colors.test.js +0 -92
- package/dist/hud/__tests__/colors.test.js.map +0 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.d.ts +0 -10
- package/dist/hud/__tests__/hud-tmux-injection.test.d.ts.map +0 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +0 -150
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +0 -1
- package/dist/hud/__tests__/index.test.d.ts +0 -2
- package/dist/hud/__tests__/index.test.d.ts.map +0 -1
- package/dist/hud/__tests__/index.test.js +0 -180
- package/dist/hud/__tests__/index.test.js.map +0 -1
- package/dist/hud/__tests__/reconcile.test.d.ts +0 -2
- package/dist/hud/__tests__/reconcile.test.d.ts.map +0 -1
- package/dist/hud/__tests__/reconcile.test.js +0 -125
- package/dist/hud/__tests__/reconcile.test.js.map +0 -1
- package/dist/hud/__tests__/render.test.d.ts +0 -2
- package/dist/hud/__tests__/render.test.d.ts.map +0 -1
- package/dist/hud/__tests__/render.test.js +0 -573
- package/dist/hud/__tests__/render.test.js.map +0 -1
- package/dist/hud/__tests__/state.test.d.ts +0 -2
- package/dist/hud/__tests__/state.test.d.ts.map +0 -1
- package/dist/hud/__tests__/state.test.js +0 -618
- package/dist/hud/__tests__/state.test.js.map +0 -1
- package/dist/hud/__tests__/types.test.d.ts +0 -2
- package/dist/hud/__tests__/types.test.d.ts.map +0 -1
- package/dist/hud/__tests__/types.test.js +0 -79
- package/dist/hud/__tests__/types.test.js.map +0 -1
- package/dist/hud/__tests__/watch.test.d.ts +0 -2
- package/dist/hud/__tests__/watch.test.d.ts.map +0 -1
- package/dist/hud/__tests__/watch.test.js +0 -63
- package/dist/hud/__tests__/watch.test.js.map +0 -1
- package/dist/mcp/__tests__/bootstrap.test.d.ts +0 -2
- package/dist/mcp/__tests__/bootstrap.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/bootstrap.test.js +0 -207
- package/dist/mcp/__tests__/bootstrap.test.js.map +0 -1
- package/dist/mcp/__tests__/code-intel-server.test.d.ts +0 -2
- package/dist/mcp/__tests__/code-intel-server.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +0 -70
- package/dist/mcp/__tests__/code-intel-server.test.js.map +0 -1
- package/dist/mcp/__tests__/memory-server.test.d.ts +0 -2
- package/dist/mcp/__tests__/memory-server.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/memory-server.test.js +0 -36
- package/dist/mcp/__tests__/memory-server.test.js.map +0 -1
- package/dist/mcp/__tests__/memory-validation.test.d.ts +0 -2
- package/dist/mcp/__tests__/memory-validation.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/memory-validation.test.js +0 -29
- package/dist/mcp/__tests__/memory-validation.test.js.map +0 -1
- package/dist/mcp/__tests__/path-traversal.test.d.ts +0 -2
- package/dist/mcp/__tests__/path-traversal.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/path-traversal.test.js +0 -83
- package/dist/mcp/__tests__/path-traversal.test.js.map +0 -1
- package/dist/mcp/__tests__/server-lifecycle.test.d.ts +0 -2
- package/dist/mcp/__tests__/server-lifecycle.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +0 -260
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +0 -1
- package/dist/mcp/__tests__/state-paths.test.d.ts +0 -2
- package/dist/mcp/__tests__/state-paths.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/state-paths.test.js +0 -209
- package/dist/mcp/__tests__/state-paths.test.js.map +0 -1
- package/dist/mcp/__tests__/state-server-ralph-phase.test.d.ts +0 -2
- package/dist/mcp/__tests__/state-server-ralph-phase.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/state-server-ralph-phase.test.js +0 -109
- package/dist/mcp/__tests__/state-server-ralph-phase.test.js.map +0 -1
- package/dist/mcp/__tests__/state-server-schema.test.d.ts +0 -2
- package/dist/mcp/__tests__/state-server-schema.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/state-server-schema.test.js +0 -29
- package/dist/mcp/__tests__/state-server-schema.test.js.map +0 -1
- package/dist/mcp/__tests__/state-server-team-tools.test.d.ts +0 -2
- package/dist/mcp/__tests__/state-server-team-tools.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/state-server-team-tools.test.js +0 -35
- package/dist/mcp/__tests__/state-server-team-tools.test.js.map +0 -1
- package/dist/mcp/__tests__/state-server.test.d.ts +0 -2
- package/dist/mcp/__tests__/state-server.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/state-server.test.js +0 -965
- package/dist/mcp/__tests__/state-server.test.js.map +0 -1
- package/dist/mcp/__tests__/trace-server.test.d.ts +0 -2
- package/dist/mcp/__tests__/trace-server.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/trace-server.test.js +0 -119
- package/dist/mcp/__tests__/trace-server.test.js.map +0 -1
- package/dist/mcp/__tests__/wiki-server.test.d.ts +0 -2
- package/dist/mcp/__tests__/wiki-server.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/wiki-server.test.js +0 -30
- package/dist/mcp/__tests__/wiki-server.test.js.map +0 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.d.ts +0 -2
- package/dist/modes/__tests__/base-autoresearch-contract.test.d.ts.map +0 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +0 -123
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +0 -1
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts +0 -2
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts.map +0 -1
- package/dist/modes/__tests__/base-multi-state-compat.test.js +0 -38
- package/dist/modes/__tests__/base-multi-state-compat.test.js.map +0 -1
- package/dist/modes/__tests__/base-ralph-contract.test.d.ts +0 -2
- package/dist/modes/__tests__/base-ralph-contract.test.d.ts.map +0 -1
- package/dist/modes/__tests__/base-ralph-contract.test.js +0 -64
- package/dist/modes/__tests__/base-ralph-contract.test.js.map +0 -1
- package/dist/modes/__tests__/base-session-scope.test.d.ts +0 -2
- package/dist/modes/__tests__/base-session-scope.test.d.ts.map +0 -1
- package/dist/modes/__tests__/base-session-scope.test.js +0 -98
- package/dist/modes/__tests__/base-session-scope.test.js.map +0 -1
- package/dist/modes/__tests__/base-tmux-pane.test.d.ts +0 -2
- package/dist/modes/__tests__/base-tmux-pane.test.d.ts.map +0 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +0 -39
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +0 -1
- package/dist/notifications/__tests__/config.test.d.ts +0 -2
- package/dist/notifications/__tests__/config.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/config.test.js +0 -269
- package/dist/notifications/__tests__/config.test.js.map +0 -1
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts +0 -2
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/custom-alias-enablement.test.js +0 -84
- package/dist/notifications/__tests__/custom-alias-enablement.test.js.map +0 -1
- package/dist/notifications/__tests__/dispatch-cooldown.test.d.ts +0 -5
- package/dist/notifications/__tests__/dispatch-cooldown.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/dispatch-cooldown.test.js +0 -100
- package/dist/notifications/__tests__/dispatch-cooldown.test.js.map +0 -1
- package/dist/notifications/__tests__/dispatcher.test.d.ts +0 -2
- package/dist/notifications/__tests__/dispatcher.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/dispatcher.test.js +0 -202
- package/dist/notifications/__tests__/dispatcher.test.js.map +0 -1
- package/dist/notifications/__tests__/formatter.test.d.ts +0 -2
- package/dist/notifications/__tests__/formatter.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/formatter.test.js +0 -270
- package/dist/notifications/__tests__/formatter.test.js.map +0 -1
- package/dist/notifications/__tests__/hook-config.test.d.ts +0 -5
- package/dist/notifications/__tests__/hook-config.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/hook-config.test.js +0 -139
- package/dist/notifications/__tests__/hook-config.test.js.map +0 -1
- package/dist/notifications/__tests__/idle-cooldown.test.d.ts +0 -5
- package/dist/notifications/__tests__/idle-cooldown.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/idle-cooldown.test.js +0 -209
- package/dist/notifications/__tests__/idle-cooldown.test.js.map +0 -1
- package/dist/notifications/__tests__/index.test.d.ts +0 -2
- package/dist/notifications/__tests__/index.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/index.test.js +0 -188
- package/dist/notifications/__tests__/index.test.js.map +0 -1
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts +0 -2
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js +0 -86
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +0 -1
- package/dist/notifications/__tests__/notifier.test.d.ts +0 -2
- package/dist/notifications/__tests__/notifier.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/notifier.test.js +0 -239
- package/dist/notifications/__tests__/notifier.test.js.map +0 -1
- package/dist/notifications/__tests__/profiles.test.d.ts +0 -2
- package/dist/notifications/__tests__/profiles.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/profiles.test.js +0 -404
- package/dist/notifications/__tests__/profiles.test.js.map +0 -1
- package/dist/notifications/__tests__/reply-config.test.d.ts +0 -2
- package/dist/notifications/__tests__/reply-config.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/reply-config.test.js +0 -79
- package/dist/notifications/__tests__/reply-config.test.js.map +0 -1
- package/dist/notifications/__tests__/reply-listener.test.d.ts +0 -2
- package/dist/notifications/__tests__/reply-listener.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/reply-listener.test.js +0 -723
- package/dist/notifications/__tests__/reply-listener.test.js.map +0 -1
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts +0 -2
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +0 -93
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +0 -1
- package/dist/notifications/__tests__/session-registry.test.d.ts +0 -2
- package/dist/notifications/__tests__/session-registry.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/session-registry.test.js +0 -234
- package/dist/notifications/__tests__/session-registry.test.js.map +0 -1
- package/dist/notifications/__tests__/session-status.test.d.ts +0 -2
- package/dist/notifications/__tests__/session-status.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/session-status.test.js +0 -249
- package/dist/notifications/__tests__/session-status.test.js.map +0 -1
- package/dist/notifications/__tests__/temp-mode.test.d.ts +0 -2
- package/dist/notifications/__tests__/temp-mode.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/temp-mode.test.js +0 -172
- package/dist/notifications/__tests__/temp-mode.test.js.map +0 -1
- package/dist/notifications/__tests__/template-engine.test.d.ts +0 -5
- package/dist/notifications/__tests__/template-engine.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/template-engine.test.js +0 -158
- package/dist/notifications/__tests__/template-engine.test.js.map +0 -1
- package/dist/notifications/__tests__/tmux-detector.test.d.ts +0 -2
- package/dist/notifications/__tests__/tmux-detector.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/tmux-detector.test.js +0 -208
- package/dist/notifications/__tests__/tmux-detector.test.js.map +0 -1
- package/dist/notifications/__tests__/tmux.test.d.ts +0 -2
- package/dist/notifications/__tests__/tmux.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/tmux.test.js +0 -285
- package/dist/notifications/__tests__/tmux.test.js.map +0 -1
- package/dist/notifications/__tests__/verbosity.test.d.ts +0 -2
- package/dist/notifications/__tests__/verbosity.test.d.ts.map +0 -1
- package/dist/notifications/__tests__/verbosity.test.js +0 -237
- package/dist/notifications/__tests__/verbosity.test.js.map +0 -1
- package/dist/openclaw/__tests__/config.test.d.ts +0 -6
- package/dist/openclaw/__tests__/config.test.d.ts.map +0 -1
- package/dist/openclaw/__tests__/config.test.js +0 -344
- package/dist/openclaw/__tests__/config.test.js.map +0 -1
- package/dist/openclaw/__tests__/dispatcher.test.d.ts +0 -5
- package/dist/openclaw/__tests__/dispatcher.test.d.ts.map +0 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +0 -169
- package/dist/openclaw/__tests__/dispatcher.test.js.map +0 -1
- package/dist/openclaw/__tests__/index.test.d.ts +0 -6
- package/dist/openclaw/__tests__/index.test.d.ts.map +0 -1
- package/dist/openclaw/__tests__/index.test.js +0 -382
- package/dist/openclaw/__tests__/index.test.js.map +0 -1
- package/dist/pipeline/__tests__/orchestrator.test.d.ts +0 -2
- package/dist/pipeline/__tests__/orchestrator.test.d.ts.map +0 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +0 -505
- package/dist/pipeline/__tests__/orchestrator.test.js.map +0 -1
- package/dist/pipeline/__tests__/stages.test.d.ts +0 -2
- package/dist/pipeline/__tests__/stages.test.d.ts.map +0 -1
- package/dist/pipeline/__tests__/stages.test.js +0 -754
- package/dist/pipeline/__tests__/stages.test.js.map +0 -1
- package/dist/pipeline/stages/ralph-verify.d.ts +0 -53
- package/dist/pipeline/stages/ralph-verify.d.ts.map +0 -1
- package/dist/pipeline/stages/ralph-verify.js.map +0 -1
- package/dist/pipeline/stages/ralplan.d.ts +0 -25
- package/dist/pipeline/stages/ralplan.d.ts.map +0 -1
- package/dist/pipeline/stages/ralplan.js.map +0 -1
- package/dist/planning/__tests__/artifacts.test.d.ts +0 -2
- package/dist/planning/__tests__/artifacts.test.d.ts.map +0 -1
- package/dist/planning/__tests__/artifacts.test.js +0 -544
- package/dist/planning/__tests__/artifacts.test.js.map +0 -1
- package/dist/question/__tests__/client.test.d.ts +0 -2
- package/dist/question/__tests__/client.test.d.ts.map +0 -1
- package/dist/question/__tests__/client.test.js +0 -90
- package/dist/question/__tests__/client.test.js.map +0 -1
- package/dist/question/__tests__/deep-interview.test.d.ts +0 -2
- package/dist/question/__tests__/deep-interview.test.d.ts.map +0 -1
- package/dist/question/__tests__/deep-interview.test.js +0 -209
- package/dist/question/__tests__/deep-interview.test.js.map +0 -1
- package/dist/question/__tests__/policy.test.d.ts +0 -2
- package/dist/question/__tests__/policy.test.d.ts.map +0 -1
- package/dist/question/__tests__/policy.test.js +0 -107
- package/dist/question/__tests__/policy.test.js.map +0 -1
- package/dist/question/__tests__/renderer.test.d.ts +0 -2
- package/dist/question/__tests__/renderer.test.d.ts.map +0 -1
- package/dist/question/__tests__/renderer.test.js +0 -707
- package/dist/question/__tests__/renderer.test.js.map +0 -1
- package/dist/question/__tests__/state.test.d.ts +0 -2
- package/dist/question/__tests__/state.test.d.ts.map +0 -1
- package/dist/question/__tests__/state.test.js +0 -102
- package/dist/question/__tests__/state.test.js.map +0 -1
- package/dist/question/__tests__/types.test.d.ts +0 -2
- package/dist/question/__tests__/types.test.d.ts.map +0 -1
- package/dist/question/__tests__/types.test.js +0 -65
- package/dist/question/__tests__/types.test.js.map +0 -1
- package/dist/question/__tests__/ui.test.d.ts +0 -2
- package/dist/question/__tests__/ui.test.d.ts.map +0 -1
- package/dist/question/__tests__/ui.test.js +0 -446
- package/dist/question/__tests__/ui.test.js.map +0 -1
- package/dist/ralph/__tests__/persistence.test.d.ts +0 -2
- package/dist/ralph/__tests__/persistence.test.d.ts.map +0 -1
- package/dist/ralph/__tests__/persistence.test.js +0 -116
- package/dist/ralph/__tests__/persistence.test.js.map +0 -1
- package/dist/ralph/contract.d.ts +0 -17
- package/dist/ralph/persistence.js.map +0 -1
- package/dist/ralplan/__tests__/runtime.test.d.ts +0 -2
- package/dist/ralplan/__tests__/runtime.test.d.ts.map +0 -1
- package/dist/ralplan/__tests__/runtime.test.js +0 -165
- package/dist/ralplan/__tests__/runtime.test.js.map +0 -1
- package/dist/ralplan/runtime.d.ts +0 -52
- package/dist/ralplan/runtime.d.ts.map +0 -1
- package/dist/ralplan/runtime.js.map +0 -1
- package/dist/runtime/__tests__/bridge.test.d.ts +0 -2
- package/dist/runtime/__tests__/bridge.test.d.ts.map +0 -1
- package/dist/runtime/__tests__/bridge.test.js +0 -194
- package/dist/runtime/__tests__/bridge.test.js.map +0 -1
- package/dist/runtime/__tests__/run-loop.test.d.ts +0 -2
- package/dist/runtime/__tests__/run-loop.test.d.ts.map +0 -1
- package/dist/runtime/__tests__/run-loop.test.js +0 -35
- package/dist/runtime/__tests__/run-loop.test.js.map +0 -1
- package/dist/runtime/__tests__/run-outcome.test.d.ts +0 -2
- package/dist/runtime/__tests__/run-outcome.test.d.ts.map +0 -1
- package/dist/runtime/__tests__/run-outcome.test.js +0 -102
- package/dist/runtime/__tests__/run-outcome.test.js.map +0 -1
- package/dist/runtime/__tests__/run-state.test.d.ts +0 -2
- package/dist/runtime/__tests__/run-state.test.d.ts.map +0 -1
- package/dist/runtime/__tests__/run-state.test.js +0 -37
- package/dist/runtime/__tests__/run-state.test.js.map +0 -1
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts +0 -2
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +0 -6788
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +0 -1
- package/dist/scripts/__tests__/generate-release-body.test.d.ts +0 -2
- package/dist/scripts/__tests__/generate-release-body.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/generate-release-body.test.js +0 -233
- package/dist/scripts/__tests__/generate-release-body.test.js.map +0 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts +0 -2
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +0 -195
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +0 -1
- package/dist/scripts/__tests__/postinstall.test.d.ts +0 -2
- package/dist/scripts/__tests__/postinstall.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/postinstall.test.js +0 -92
- package/dist/scripts/__tests__/postinstall.test.js.map +0 -1
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts +0 -2
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/prompt-inventory.test.js +0 -56
- package/dist/scripts/__tests__/prompt-inventory.test.js.map +0 -1
- package/dist/scripts/__tests__/run-test-files.test.d.ts +0 -2
- package/dist/scripts/__tests__/run-test-files.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/run-test-files.test.js +0 -62
- package/dist/scripts/__tests__/run-test-files.test.js.map +0 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.d.ts +0 -2
- package/dist/scripts/__tests__/smoke-packed-install.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +0 -135
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +0 -1
- package/dist/scripts/__tests__/test-reply-listener-live.test.d.ts +0 -2
- package/dist/scripts/__tests__/test-reply-listener-live.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/test-reply-listener-live.test.js +0 -82
- package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +0 -1
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts +0 -2
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +0 -166
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +0 -1
- package/dist/scripts/eval/eval-candidate-handoff.d.ts +0 -2
- package/dist/scripts/eval/eval-candidate-handoff.d.ts.map +0 -1
- package/dist/scripts/eval/eval-candidate-handoff.js +0 -11
- package/dist/scripts/eval/eval-candidate-handoff.js.map +0 -1
- package/dist/scripts/eval/eval-cli-discoverability.d.ts +0 -3
- package/dist/scripts/eval/eval-cli-discoverability.d.ts.map +0 -1
- package/dist/scripts/eval/eval-cli-discoverability.js +0 -37
- package/dist/scripts/eval/eval-cli-discoverability.js.map +0 -1
- package/dist/scripts/eval/eval-fresh-run-tagging.d.ts +0 -2
- package/dist/scripts/eval/eval-fresh-run-tagging.d.ts.map +0 -1
- package/dist/scripts/eval/eval-fresh-run-tagging.js +0 -11
- package/dist/scripts/eval/eval-fresh-run-tagging.js.map +0 -1
- package/dist/scripts/eval/eval-help-consistency.d.ts +0 -2
- package/dist/scripts/eval/eval-help-consistency.d.ts.map +0 -1
- package/dist/scripts/eval/eval-help-consistency.js +0 -12
- package/dist/scripts/eval/eval-help-consistency.js.map +0 -1
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.d.ts +0 -2
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.d.ts.map +0 -1
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.js +0 -31
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.js.map +0 -1
- package/dist/scripts/eval/eval-parity-smoke.d.ts +0 -2
- package/dist/scripts/eval/eval-parity-smoke.d.ts.map +0 -1
- package/dist/scripts/eval/eval-parity-smoke.js +0 -23
- package/dist/scripts/eval/eval-parity-smoke.js.map +0 -1
- package/dist/scripts/eval/eval-parity-sweep.d.ts +0 -2
- package/dist/scripts/eval/eval-parity-sweep.d.ts.map +0 -1
- package/dist/scripts/eval/eval-parity-sweep.js +0 -29
- package/dist/scripts/eval/eval-parity-sweep.js.map +0 -1
- package/dist/scripts/eval/eval-resume-dirty-guard.d.ts +0 -2
- package/dist/scripts/eval/eval-resume-dirty-guard.d.ts.map +0 -1
- package/dist/scripts/eval/eval-resume-dirty-guard.js +0 -11
- package/dist/scripts/eval/eval-resume-dirty-guard.js.map +0 -1
- package/dist/scripts/eval/eval-security-path-traversal.d.ts +0 -3
- package/dist/scripts/eval/eval-security-path-traversal.d.ts.map +0 -1
- package/dist/scripts/eval/eval-security-path-traversal.js +0 -35
- package/dist/scripts/eval/eval-security-path-traversal.js.map +0 -1
- package/dist/scripts/notify-hook/__tests__/operational-events.test.d.ts +0 -2
- package/dist/scripts/notify-hook/__tests__/operational-events.test.d.ts.map +0 -1
- package/dist/scripts/notify-hook/__tests__/operational-events.test.js +0 -24
- package/dist/scripts/notify-hook/__tests__/operational-events.test.js.map +0 -1
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +0 -2
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +0 -1
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +0 -153
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +0 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts +0 -22
- package/dist/session-history/__tests__/search.test.d.ts +0 -2
- package/dist/session-history/__tests__/search.test.d.ts.map +0 -1
- package/dist/session-history/__tests__/search.test.js +0 -150
- package/dist/session-history/__tests__/search.test.js.map +0 -1
- package/dist/sidecar/__tests__/boundary.test.d.ts +0 -2
- package/dist/sidecar/__tests__/boundary.test.d.ts.map +0 -1
- package/dist/sidecar/__tests__/boundary.test.js +0 -48
- package/dist/sidecar/__tests__/boundary.test.js.map +0 -1
- package/dist/sidecar/__tests__/collector.test.d.ts +0 -2
- package/dist/sidecar/__tests__/collector.test.d.ts.map +0 -1
- package/dist/sidecar/__tests__/collector.test.js +0 -162
- package/dist/sidecar/__tests__/collector.test.js.map +0 -1
- package/dist/sidecar/__tests__/render.test.d.ts +0 -2
- package/dist/sidecar/__tests__/render.test.d.ts.map +0 -1
- package/dist/sidecar/__tests__/render.test.js +0 -67
- package/dist/sidecar/__tests__/render.test.js.map +0 -1
- package/dist/sidecar/__tests__/tmux.test.d.ts +0 -2
- package/dist/sidecar/__tests__/tmux.test.d.ts.map +0 -1
- package/dist/sidecar/__tests__/tmux.test.js +0 -30
- package/dist/sidecar/__tests__/tmux.test.js.map +0 -1
- package/dist/sidecar/__tests__/watch.test.d.ts +0 -2
- package/dist/sidecar/__tests__/watch.test.d.ts.map +0 -1
- package/dist/sidecar/__tests__/watch.test.js +0 -42
- package/dist/sidecar/__tests__/watch.test.js.map +0 -1
- package/dist/state/__tests__/mode-state-context.test.d.ts +0 -2
- package/dist/state/__tests__/mode-state-context.test.d.ts.map +0 -1
- package/dist/state/__tests__/mode-state-context.test.js +0 -35
- package/dist/state/__tests__/mode-state-context.test.js.map +0 -1
- package/dist/state/__tests__/operations-ralph-phase.test.d.ts +0 -2
- package/dist/state/__tests__/operations-ralph-phase.test.d.ts.map +0 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js +0 -103
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +0 -1
- package/dist/state/__tests__/operations.test.d.ts +0 -2
- package/dist/state/__tests__/operations.test.d.ts.map +0 -1
- package/dist/state/__tests__/operations.test.js +0 -439
- package/dist/state/__tests__/operations.test.js.map +0 -1
- package/dist/state/__tests__/path-traversal.test.d.ts +0 -2
- package/dist/state/__tests__/path-traversal.test.d.ts.map +0 -1
- package/dist/state/__tests__/path-traversal.test.js +0 -49
- package/dist/state/__tests__/path-traversal.test.js.map +0 -1
- package/dist/state/__tests__/skill-active.test.d.ts +0 -2
- package/dist/state/__tests__/skill-active.test.d.ts.map +0 -1
- package/dist/state/__tests__/skill-active.test.js +0 -160
- package/dist/state/__tests__/skill-active.test.js.map +0 -1
- package/dist/state/__tests__/workflow-transition.test.d.ts +0 -2
- package/dist/state/__tests__/workflow-transition.test.d.ts.map +0 -1
- package/dist/state/__tests__/workflow-transition.test.js +0 -77
- package/dist/state/__tests__/workflow-transition.test.js.map +0 -1
- package/dist/subagents/__tests__/tracker.test.d.ts +0 -2
- package/dist/subagents/__tests__/tracker.test.d.ts.map +0 -1
- package/dist/subagents/__tests__/tracker.test.js +0 -47
- package/dist/subagents/__tests__/tracker.test.js.map +0 -1
- package/dist/team/__tests__/allocation-policy.test.d.ts +0 -2
- package/dist/team/__tests__/allocation-policy.test.d.ts.map +0 -1
- package/dist/team/__tests__/allocation-policy.test.js +0 -111
- package/dist/team/__tests__/allocation-policy.test.js.map +0 -1
- package/dist/team/__tests__/api-interop.test.d.ts +0 -2
- package/dist/team/__tests__/api-interop.test.d.ts.map +0 -1
- package/dist/team/__tests__/api-interop.test.js +0 -2262
- package/dist/team/__tests__/api-interop.test.js.map +0 -1
- package/dist/team/__tests__/commit-hygiene.test.d.ts +0 -2
- package/dist/team/__tests__/commit-hygiene.test.d.ts.map +0 -1
- package/dist/team/__tests__/commit-hygiene.test.js +0 -93
- package/dist/team/__tests__/commit-hygiene.test.js.map +0 -1
- package/dist/team/__tests__/cross-rebase-smoke.test.d.ts +0 -2
- package/dist/team/__tests__/cross-rebase-smoke.test.d.ts.map +0 -1
- package/dist/team/__tests__/cross-rebase-smoke.test.js +0 -161
- package/dist/team/__tests__/cross-rebase-smoke.test.js.map +0 -1
- package/dist/team/__tests__/current-task-baseline.test.d.ts +0 -2
- package/dist/team/__tests__/current-task-baseline.test.d.ts.map +0 -1
- package/dist/team/__tests__/current-task-baseline.test.js +0 -87
- package/dist/team/__tests__/current-task-baseline.test.js.map +0 -1
- package/dist/team/__tests__/delegation-policy.test.d.ts +0 -2
- package/dist/team/__tests__/delegation-policy.test.d.ts.map +0 -1
- package/dist/team/__tests__/delegation-policy.test.js +0 -69
- package/dist/team/__tests__/delegation-policy.test.js.map +0 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +0 -2
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +0 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +0 -679
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +0 -1
- package/dist/team/__tests__/events.test.d.ts +0 -2
- package/dist/team/__tests__/events.test.d.ts.map +0 -1
- package/dist/team/__tests__/events.test.js +0 -313
- package/dist/team/__tests__/events.test.js.map +0 -1
- package/dist/team/__tests__/followup-planner.test.d.ts +0 -2
- package/dist/team/__tests__/followup-planner.test.d.ts.map +0 -1
- package/dist/team/__tests__/followup-planner.test.js +0 -84
- package/dist/team/__tests__/followup-planner.test.js.map +0 -1
- package/dist/team/__tests__/hardening-e2e.test.d.ts +0 -2
- package/dist/team/__tests__/hardening-e2e.test.d.ts.map +0 -1
- package/dist/team/__tests__/hardening-e2e.test.js +0 -98
- package/dist/team/__tests__/hardening-e2e.test.js.map +0 -1
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +0 -2
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +0 -1
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js +0 -78
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +0 -1
- package/dist/team/__tests__/idle-nudge.test.d.ts +0 -2
- package/dist/team/__tests__/idle-nudge.test.d.ts.map +0 -1
- package/dist/team/__tests__/idle-nudge.test.js +0 -230
- package/dist/team/__tests__/idle-nudge.test.js.map +0 -1
- package/dist/team/__tests__/leader-activity.test.d.ts +0 -2
- package/dist/team/__tests__/leader-activity.test.d.ts.map +0 -1
- package/dist/team/__tests__/leader-activity.test.js +0 -261
- package/dist/team/__tests__/leader-activity.test.js.map +0 -1
- package/dist/team/__tests__/mcp-comm.test.d.ts +0 -2
- package/dist/team/__tests__/mcp-comm.test.d.ts.map +0 -1
- package/dist/team/__tests__/mcp-comm.test.js +0 -289
- package/dist/team/__tests__/mcp-comm.test.js.map +0 -1
- package/dist/team/__tests__/model-contract.test.d.ts +0 -2
- package/dist/team/__tests__/model-contract.test.d.ts.map +0 -1
- package/dist/team/__tests__/model-contract.test.js +0 -171
- package/dist/team/__tests__/model-contract.test.js.map +0 -1
- package/dist/team/__tests__/orchestrator.test.d.ts +0 -2
- package/dist/team/__tests__/orchestrator.test.d.ts.map +0 -1
- package/dist/team/__tests__/orchestrator.test.js +0 -111
- package/dist/team/__tests__/orchestrator.test.js.map +0 -1
- package/dist/team/__tests__/phase-controller.test.d.ts +0 -2
- package/dist/team/__tests__/phase-controller.test.d.ts.map +0 -1
- package/dist/team/__tests__/phase-controller.test.js +0 -50
- package/dist/team/__tests__/phase-controller.test.js.map +0 -1
- package/dist/team/__tests__/rebalance-policy.test.d.ts +0 -2
- package/dist/team/__tests__/rebalance-policy.test.d.ts.map +0 -1
- package/dist/team/__tests__/rebalance-policy.test.js +0 -168
- package/dist/team/__tests__/rebalance-policy.test.js.map +0 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +0 -2
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +0 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.js +0 -136
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +0 -1
- package/dist/team/__tests__/role-router.test.d.ts +0 -2
- package/dist/team/__tests__/role-router.test.d.ts.map +0 -1
- package/dist/team/__tests__/role-router.test.js +0 -263
- package/dist/team/__tests__/role-router.test.js.map +0 -1
- package/dist/team/__tests__/runtime-cli.test.d.ts +0 -2
- package/dist/team/__tests__/runtime-cli.test.d.ts.map +0 -1
- package/dist/team/__tests__/runtime-cli.test.js +0 -304
- package/dist/team/__tests__/runtime-cli.test.js.map +0 -1
- package/dist/team/__tests__/runtime.test.d.ts +0 -2
- package/dist/team/__tests__/runtime.test.d.ts.map +0 -1
- package/dist/team/__tests__/runtime.test.js +0 -5734
- package/dist/team/__tests__/runtime.test.js.map +0 -1
- package/dist/team/__tests__/scaling.test.d.ts +0 -2
- package/dist/team/__tests__/scaling.test.d.ts.map +0 -1
- package/dist/team/__tests__/scaling.test.js +0 -1005
- package/dist/team/__tests__/scaling.test.js.map +0 -1
- package/dist/team/__tests__/shutdown-fallback.test.d.ts +0 -2
- package/dist/team/__tests__/shutdown-fallback.test.d.ts.map +0 -1
- package/dist/team/__tests__/shutdown-fallback.test.js +0 -125
- package/dist/team/__tests__/shutdown-fallback.test.js.map +0 -1
- package/dist/team/__tests__/state-root.test.d.ts +0 -2
- package/dist/team/__tests__/state-root.test.d.ts.map +0 -1
- package/dist/team/__tests__/state-root.test.js +0 -195
- package/dist/team/__tests__/state-root.test.js.map +0 -1
- package/dist/team/__tests__/state.test.d.ts +0 -2
- package/dist/team/__tests__/state.test.d.ts.map +0 -1
- package/dist/team/__tests__/state.test.js +0 -1859
- package/dist/team/__tests__/state.test.js.map +0 -1
- package/dist/team/__tests__/team-identity.test.d.ts +0 -2
- package/dist/team/__tests__/team-identity.test.d.ts.map +0 -1
- package/dist/team/__tests__/team-identity.test.js +0 -166
- package/dist/team/__tests__/team-identity.test.js.map +0 -1
- package/dist/team/__tests__/team-ops-contract.test.d.ts +0 -2
- package/dist/team/__tests__/team-ops-contract.test.d.ts.map +0 -1
- package/dist/team/__tests__/team-ops-contract.test.js +0 -96
- package/dist/team/__tests__/team-ops-contract.test.js.map +0 -1
- package/dist/team/__tests__/tmux-claude-workers-demo.test.d.ts +0 -2
- package/dist/team/__tests__/tmux-claude-workers-demo.test.d.ts.map +0 -1
- package/dist/team/__tests__/tmux-claude-workers-demo.test.js +0 -191
- package/dist/team/__tests__/tmux-claude-workers-demo.test.js.map +0 -1
- package/dist/team/__tests__/tmux-session.test.d.ts +0 -2
- package/dist/team/__tests__/tmux-session.test.d.ts.map +0 -1
- package/dist/team/__tests__/tmux-session.test.js +0 -3785
- package/dist/team/__tests__/tmux-session.test.js.map +0 -1
- package/dist/team/__tests__/tmux-test-fixture.d.ts +0 -20
- package/dist/team/__tests__/tmux-test-fixture.d.ts.map +0 -1
- package/dist/team/__tests__/tmux-test-fixture.js +0 -152
- package/dist/team/__tests__/tmux-test-fixture.js.map +0 -1
- package/dist/team/__tests__/tmux-test-fixture.test.d.ts +0 -2
- package/dist/team/__tests__/tmux-test-fixture.test.d.ts.map +0 -1
- package/dist/team/__tests__/tmux-test-fixture.test.js +0 -113
- package/dist/team/__tests__/tmux-test-fixture.test.js.map +0 -1
- package/dist/team/__tests__/worker-bootstrap.test.d.ts +0 -2
- package/dist/team/__tests__/worker-bootstrap.test.d.ts.map +0 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +0 -685
- package/dist/team/__tests__/worker-bootstrap.test.js.map +0 -1
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts +0 -2
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts.map +0 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +0 -250
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +0 -1
- package/dist/team/__tests__/worktree.test.d.ts +0 -2
- package/dist/team/__tests__/worktree.test.d.ts.map +0 -1
- package/dist/team/__tests__/worktree.test.js +0 -317
- package/dist/team/__tests__/worktree.test.js.map +0 -1
- package/dist/utils/__tests__/agents-md.test.d.ts +0 -2
- package/dist/utils/__tests__/agents-md.test.d.ts.map +0 -1
- package/dist/utils/__tests__/agents-md.test.js +0 -52
- package/dist/utils/__tests__/agents-md.test.js.map +0 -1
- package/dist/utils/__tests__/agents-model-table.test.d.ts +0 -2
- package/dist/utils/__tests__/agents-model-table.test.d.ts.map +0 -1
- package/dist/utils/__tests__/agents-model-table.test.js +0 -104
- package/dist/utils/__tests__/agents-model-table.test.js.map +0 -1
- package/dist/utils/__tests__/dep-versions.test.d.ts +0 -2
- package/dist/utils/__tests__/dep-versions.test.d.ts.map +0 -1
- package/dist/utils/__tests__/dep-versions.test.js +0 -46
- package/dist/utils/__tests__/dep-versions.test.js.map +0 -1
- package/dist/utils/__tests__/package.test.d.ts +0 -2
- package/dist/utils/__tests__/package.test.d.ts.map +0 -1
- package/dist/utils/__tests__/package.test.js +0 -21
- package/dist/utils/__tests__/package.test.js.map +0 -1
- package/dist/utils/__tests__/paths.test.d.ts +0 -2
- package/dist/utils/__tests__/paths.test.d.ts.map +0 -1
- package/dist/utils/__tests__/paths.test.js +0 -541
- package/dist/utils/__tests__/paths.test.js.map +0 -1
- package/dist/utils/__tests__/platform-command.test.d.ts +0 -2
- package/dist/utils/__tests__/platform-command.test.d.ts.map +0 -1
- package/dist/utils/__tests__/platform-command.test.js +0 -410
- package/dist/utils/__tests__/platform-command.test.js.map +0 -1
- package/dist/utils/__tests__/repo-deps.test.d.ts +0 -2
- package/dist/utils/__tests__/repo-deps.test.d.ts.map +0 -1
- package/dist/utils/__tests__/repo-deps.test.js +0 -71
- package/dist/utils/__tests__/repo-deps.test.js.map +0 -1
- package/dist/verification/__tests__/ci-rust-gates.test.d.ts +0 -2
- package/dist/verification/__tests__/ci-rust-gates.test.d.ts.map +0 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +0 -89
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +0 -1
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts +0 -2
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts.map +0 -1
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +0 -54
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +0 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.d.ts +0 -2
- package/dist/verification/__tests__/explore-harness-release-workflow.test.d.ts.map +0 -1
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +0 -73
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +0 -1
- package/dist/verification/__tests__/native-release-manifest.test.d.ts +0 -2
- package/dist/verification/__tests__/native-release-manifest.test.d.ts.map +0 -1
- package/dist/verification/__tests__/native-release-manifest.test.js +0 -80
- package/dist/verification/__tests__/native-release-manifest.test.js.map +0 -1
- package/dist/verification/__tests__/pr-check-workflow.test.d.ts +0 -2
- package/dist/verification/__tests__/pr-check-workflow.test.d.ts.map +0 -1
- package/dist/verification/__tests__/pr-check-workflow.test.js +0 -27
- package/dist/verification/__tests__/pr-check-workflow.test.js.map +0 -1
- package/dist/verification/__tests__/ralph-persistence-gate.test.d.ts +0 -2
- package/dist/verification/__tests__/ralph-persistence-gate.test.d.ts.map +0 -1
- package/dist/verification/__tests__/ralph-persistence-gate.test.js +0 -55
- package/dist/verification/__tests__/ralph-persistence-gate.test.js.map +0 -1
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.d.ts +0 -2
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.d.ts.map +0 -1
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.js +0 -32
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.js.map +0 -1
- package/dist/verification/__tests__/verifier.test.d.ts +0 -2
- package/dist/verification/__tests__/verifier.test.d.ts.map +0 -1
- package/dist/verification/__tests__/verifier.test.js +0 -113
- package/dist/verification/__tests__/verifier.test.js.map +0 -1
- package/dist/visual/__tests__/verdict.test.d.ts +0 -2
- package/dist/visual/__tests__/verdict.test.d.ts.map +0 -1
- package/dist/visual/__tests__/verdict.test.js +0 -81
- package/dist/visual/__tests__/verdict.test.js.map +0 -1
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts +0 -12
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/cjk-tokenize.test.js +0 -139
- package/dist/wiki/__tests__/cjk-tokenize.test.js.map +0 -1
- package/dist/wiki/__tests__/crlf-parse.test.d.ts +0 -2
- package/dist/wiki/__tests__/crlf-parse.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/crlf-parse.test.js +0 -24
- package/dist/wiki/__tests__/crlf-parse.test.js.map +0 -1
- package/dist/wiki/__tests__/escape-newline.test.d.ts +0 -2
- package/dist/wiki/__tests__/escape-newline.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/escape-newline.test.js +0 -45
- package/dist/wiki/__tests__/escape-newline.test.js.map +0 -1
- package/dist/wiki/__tests__/ingest.test.d.ts +0 -5
- package/dist/wiki/__tests__/ingest.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/ingest.test.js +0 -181
- package/dist/wiki/__tests__/ingest.test.js.map +0 -1
- package/dist/wiki/__tests__/lint.test.d.ts +0 -5
- package/dist/wiki/__tests__/lint.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/lint.test.js +0 -163
- package/dist/wiki/__tests__/lint.test.js.map +0 -1
- package/dist/wiki/__tests__/query.test.d.ts +0 -5
- package/dist/wiki/__tests__/query.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/query.test.js +0 -141
- package/dist/wiki/__tests__/query.test.js.map +0 -1
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts +0 -2
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/reserved-file-guard.test.js +0 -44
- package/dist/wiki/__tests__/reserved-file-guard.test.js.map +0 -1
- package/dist/wiki/__tests__/session-hooks.test.d.ts +0 -5
- package/dist/wiki/__tests__/session-hooks.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/session-hooks.test.js +0 -36
- package/dist/wiki/__tests__/session-hooks.test.js.map +0 -1
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts +0 -2
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/slug-nonascii.test.js +0 -30
- package/dist/wiki/__tests__/slug-nonascii.test.js.map +0 -1
- package/dist/wiki/__tests__/storage.test.d.ts +0 -5
- package/dist/wiki/__tests__/storage.test.d.ts.map +0 -1
- package/dist/wiki/__tests__/storage.test.js +0 -278
- package/dist/wiki/__tests__/storage.test.js.map +0 -1
- package/dist/wiki/__tests__/test-helpers.d.ts +0 -31
- package/dist/wiki/__tests__/test-helpers.d.ts.map +0 -1
- package/dist/wiki/__tests__/test-helpers.js +0 -108
- package/dist/wiki/__tests__/test-helpers.js.map +0 -1
- package/docs/contracts/ralph-cancel-contract.md +0 -23
- package/docs/contracts/ralph-state-contract.md +0 -95
- package/docs/issues/team-ralph-followup-team.md +0 -38
- package/docs/qa/ralph-persistence-gate.md +0 -59
- package/docs/reference/ralph-parity-matrix.md +0 -25
- package/docs/reference/ralph-upstream-baseline.md +0 -34
- package/plugins/roblox-ai-os-creator-skills/skills/ralph/SKILL.md +0 -269
- package/plugins/roblox-ai-os-creator-skills/skills/ralplan/SKILL.md +0 -162
- package/prompts/api-reviewer.md +0 -113
- package/prompts/information-architect.md +0 -226
- package/prompts/performance-reviewer.md +0 -109
- package/prompts/product-analyst.md +0 -304
- package/prompts/product-manager.md +0 -245
- package/prompts/qa-tester.md +0 -124
- package/prompts/quality-reviewer.md +0 -123
- package/prompts/quality-strategist.md +0 -274
- package/prompts/style-reviewer.md +0 -102
- package/prompts/ux-researcher.md +0 -327
- package/skills/frontend-ui-ux/SKILL.md +0 -34
- package/skills/ralph/SKILL.md +0 -269
- package/skills/ralplan/SKILL.md +0 -162
- package/src/scripts/eval/eval-adaptive-sort-optimization.py +0 -24
- package/src/scripts/eval/eval-candidate-handoff.ts +0 -8
- package/src/scripts/eval/eval-cli-discoverability.ts +0 -40
- package/src/scripts/eval/eval-fresh-run-tagging.ts +0 -8
- package/src/scripts/eval/eval-help-consistency.ts +0 -11
- package/src/scripts/eval/eval-in-action-cat-shellout-demo.ts +0 -31
- package/src/scripts/eval/eval-ml-kaggle-model-optimization.py +0 -29
- package/src/scripts/eval/eval-noisy-bayesopt-highdim.py +0 -44
- package/src/scripts/eval/eval-noisy-latent-subspace-discovery.py +0 -44
- package/src/scripts/eval/eval-parity-smoke.ts +0 -20
- package/src/scripts/eval/eval-parity-sweep.ts +0 -26
- package/src/scripts/eval/eval-resume-dirty-guard.ts +0 -8
- package/src/scripts/eval/eval-security-path-traversal.ts +0 -38
- package/src/scripts/run-autoresearch-showcase.sh +0 -75
- /package/docs/{migration-mainline-post-v0.4.4.md → archive/migration-mainline-post-v0.4.4.md} +0 -0
- /package/docs/{qa-plan-0.4.2.md → archive/qa-plan-0.4.2.md} +0 -0
- /package/docs/{qa-report-0.4.2.md → archive/qa-report-0.4.2.md} +0 -0
|
@@ -1,2397 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { spawnSync } from 'node:child_process';
|
|
4
|
-
import { chmod, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
5
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
|
-
import { tmpdir } from 'node:os';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
import { buildTmuxSessionName } from '../../cli/index.js';
|
|
9
|
-
const NOTIFY_HOOK_SCRIPT = new URL('../../../dist/scripts/notify-hook.js', import.meta.url);
|
|
10
|
-
const DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS = ['yes', 'y', 'proceed', 'continue', 'ok', 'sure', 'go ahead', 'next i should'];
|
|
11
|
-
const NEXT_I_SHOULD_RESPONSE = 'Next I should update the focused tests.';
|
|
12
|
-
const DEFAULT_AUTO_NUDGE_RESPONSE = 'continue with the current task only if it is already authorized';
|
|
13
|
-
async function withTempWorkingDir(run) {
|
|
14
|
-
const cwd = await mkdtemp(join(tmpdir(), 'rcs-auto-nudge-'));
|
|
15
|
-
try {
|
|
16
|
-
await run(cwd);
|
|
17
|
-
}
|
|
18
|
-
finally {
|
|
19
|
-
await rm(cwd, { recursive: true, force: true });
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
async function writeJson(path, value) {
|
|
23
|
-
await writeFile(path, JSON.stringify(value, null, 2));
|
|
24
|
-
}
|
|
25
|
-
function readLinuxStartTicks(pid) {
|
|
26
|
-
try {
|
|
27
|
-
const stat = readFileSync(`/proc/${pid}/stat`, 'utf-8');
|
|
28
|
-
const commandEnd = stat.lastIndexOf(')');
|
|
29
|
-
if (commandEnd === -1)
|
|
30
|
-
return null;
|
|
31
|
-
const remainder = stat.slice(commandEnd + 1).trim();
|
|
32
|
-
const fields = remainder.split(/\s+/);
|
|
33
|
-
if (fields.length <= 19)
|
|
34
|
-
return null;
|
|
35
|
-
const startTicks = Number(fields[19]);
|
|
36
|
-
return Number.isFinite(startTicks) ? startTicks : null;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function readLinuxCmdline(pid) {
|
|
43
|
-
try {
|
|
44
|
-
const raw = readFileSync(`/proc/${pid}/cmdline`);
|
|
45
|
-
const text = raw.toString('utf-8').replace(/\0+/g, ' ').trim();
|
|
46
|
-
return text.length > 0 ? text : null;
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function writeManagedSessionState(stateDir, cwd) {
|
|
53
|
-
await writeJson(join(stateDir, 'session.json'), {
|
|
54
|
-
session_id: 'sess-managed',
|
|
55
|
-
started_at: new Date().toISOString(),
|
|
56
|
-
cwd,
|
|
57
|
-
pid: process.pid,
|
|
58
|
-
platform: process.platform,
|
|
59
|
-
pid_start_ticks: readLinuxStartTicks(process.pid),
|
|
60
|
-
pid_cmdline: readLinuxCmdline(process.pid),
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
async function writeWorkerIdentityFixture(stateRoot, cwd, teamName, workerName) {
|
|
64
|
-
const workerDir = join(stateRoot, 'team', teamName, 'workers', workerName);
|
|
65
|
-
await mkdir(workerDir, { recursive: true });
|
|
66
|
-
await writeJson(join(workerDir, 'identity.json'), {
|
|
67
|
-
name: workerName,
|
|
68
|
-
index: Number(workerName.replace(/^worker-/, '')) || 1,
|
|
69
|
-
role: 'executor',
|
|
70
|
-
assigned_tasks: [],
|
|
71
|
-
worktree_path: cwd,
|
|
72
|
-
team_state_root: stateRoot,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
function escapeRegex(value) {
|
|
76
|
-
return value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
77
|
-
}
|
|
78
|
-
function defaultAutoNudgePattern(targetPane) {
|
|
79
|
-
return new RegExp(`send-keys -t ${escapeRegex(targetPane)} -l ${escapeRegex(DEFAULT_AUTO_NUDGE_RESPONSE)} \\[RCS_TMUX_INJECT\\]`);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Build a fake tmux binary that logs all invocations and optionally returns
|
|
83
|
-
* capture-pane content from RCS_TEST_CAPTURE_FILE.
|
|
84
|
-
*/
|
|
85
|
-
function buildFakeTmux(tmuxLogPath, paneInMode = '0') {
|
|
86
|
-
return `#!/usr/bin/env bash
|
|
87
|
-
set -eu
|
|
88
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
89
|
-
cmd="\$1"
|
|
90
|
-
shift || true
|
|
91
|
-
if [[ "\$cmd" == "capture-pane" ]]; then
|
|
92
|
-
if [[ -n "\${RCS_TEST_CAPTURE_FILE:-}" && -f "\${RCS_TEST_CAPTURE_FILE}" ]]; then
|
|
93
|
-
cat "\${RCS_TEST_CAPTURE_FILE}"
|
|
94
|
-
fi
|
|
95
|
-
exit 0
|
|
96
|
-
fi
|
|
97
|
-
if [[ "\$cmd" == "send-keys" ]]; then
|
|
98
|
-
exit 0
|
|
99
|
-
fi
|
|
100
|
-
if [[ "\$cmd" == "display-message" ]]; then
|
|
101
|
-
target=""
|
|
102
|
-
format=""
|
|
103
|
-
while [[ "\$#" -gt 0 ]]; do
|
|
104
|
-
case "\$1" in
|
|
105
|
-
-p) shift ;;
|
|
106
|
-
-t) target="\$2"; shift 2 ;;
|
|
107
|
-
*) format="\$1"; shift ;;
|
|
108
|
-
esac
|
|
109
|
-
done
|
|
110
|
-
if [[ "\$format" == "#{pane_in_mode}" ]]; then
|
|
111
|
-
echo "${paneInMode}"
|
|
112
|
-
exit 0
|
|
113
|
-
fi
|
|
114
|
-
if [[ "\$format" == "#{pane_current_command}" && "\$target" == "%99" ]]; then
|
|
115
|
-
echo "node"
|
|
116
|
-
exit 0
|
|
117
|
-
fi
|
|
118
|
-
if [[ "\$format" == "#{pane_start_command}" && "\$target" == "%99" ]]; then
|
|
119
|
-
echo "codex --model gpt-5"
|
|
120
|
-
exit 0
|
|
121
|
-
fi
|
|
122
|
-
if [[ "\$format" == "#S" ]]; then
|
|
123
|
-
echo "${'${RCS_TEST_TMUX_SESSION_NAME:-devsess}'}"
|
|
124
|
-
exit 0
|
|
125
|
-
fi
|
|
126
|
-
exit 0
|
|
127
|
-
fi
|
|
128
|
-
if [[ "\$cmd" == "list-panes" ]]; then
|
|
129
|
-
target=""
|
|
130
|
-
while [[ "\$#" -gt 0 ]]; do
|
|
131
|
-
case "\$1" in
|
|
132
|
-
-t) target="\$2"; shift 2 ;;
|
|
133
|
-
*) shift ;;
|
|
134
|
-
esac
|
|
135
|
-
done
|
|
136
|
-
if [[ -n "\$target" && "\$target" == "${'${RCS_TEST_TMUX_SESSION_NAME:-devsess}'}" ]]; then
|
|
137
|
-
printf '%%99\t1\tnode\tcodex --model gpt-5\n'
|
|
138
|
-
exit 0
|
|
139
|
-
fi
|
|
140
|
-
echo "%1 12345"
|
|
141
|
-
exit 0
|
|
142
|
-
fi
|
|
143
|
-
exit 0
|
|
144
|
-
`;
|
|
145
|
-
}
|
|
146
|
-
function runNotifyHook(cwd, fakeBinDir, codexHome, payloadOverrides = {}, extraEnv = {}) {
|
|
147
|
-
if (extraEnv.RCS_TEST_UNMANAGED_SESSION !== '1' && !extraEnv.RCS_TEAM_WORKER) {
|
|
148
|
-
const sessionPath = join(cwd, '.rcs', 'state', 'session.json');
|
|
149
|
-
const sessionState = {
|
|
150
|
-
session_id: 'sess-managed',
|
|
151
|
-
started_at: new Date().toISOString(),
|
|
152
|
-
cwd,
|
|
153
|
-
pid: process.pid,
|
|
154
|
-
platform: process.platform,
|
|
155
|
-
pid_start_ticks: readLinuxStartTicks(process.pid),
|
|
156
|
-
pid_cmdline: readLinuxCmdline(process.pid),
|
|
157
|
-
};
|
|
158
|
-
writeFileSync(sessionPath, JSON.stringify(sessionState, null, 2));
|
|
159
|
-
}
|
|
160
|
-
const payload = {
|
|
161
|
-
cwd,
|
|
162
|
-
type: 'agent-turn-complete',
|
|
163
|
-
'thread-id': 'thread-test',
|
|
164
|
-
'turn-id': `turn-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
|
|
165
|
-
...(extraEnv.RCS_TEST_UNMANAGED_SESSION !== '1' && !extraEnv.RCS_TEAM_WORKER ? { 'session-id': 'sess-managed' } : {}),
|
|
166
|
-
'input-messages': ['test'],
|
|
167
|
-
'last-assistant-message': 'done',
|
|
168
|
-
...payloadOverrides,
|
|
169
|
-
};
|
|
170
|
-
return spawnSync(process.execPath, [NOTIFY_HOOK_SCRIPT.pathname, JSON.stringify(payload)], {
|
|
171
|
-
encoding: 'utf8',
|
|
172
|
-
timeout: 15_000,
|
|
173
|
-
env: {
|
|
174
|
-
...process.env,
|
|
175
|
-
PATH: `${fakeBinDir}:${process.env.PATH || ''}`,
|
|
176
|
-
CODEX_HOME: codexHome,
|
|
177
|
-
...(extraEnv.RCS_TEST_UNMANAGED_SESSION !== '1' && !extraEnv.RCS_TEAM_WORKER ? { RCS_SESSION_ID: 'sess-managed' } : {}),
|
|
178
|
-
...(extraEnv.RCS_TEST_UNMANAGED_SESSION !== '1' && !extraEnv.RCS_TEAM_WORKER ? { RCS_TEST_TMUX_SESSION_NAME: buildTmuxSessionName(cwd, 'sess-managed') } : {}),
|
|
179
|
-
TMUX_PANE: '%99',
|
|
180
|
-
TMUX: '1',
|
|
181
|
-
RCS_TEAM_WORKER: '',
|
|
182
|
-
RCS_TEAM_LEADER_NUDGE_MS: '9999999',
|
|
183
|
-
RCS_TEAM_LEADER_STALE_MS: '9999999',
|
|
184
|
-
...extraEnv,
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
describe('notify-hook auto-nudge', () => {
|
|
189
|
-
it('does not nudge immediately by default before a real stall window elapses', async () => {
|
|
190
|
-
await withTempWorkingDir(async (cwd) => {
|
|
191
|
-
const rcsDir = join(cwd, '.rcs');
|
|
192
|
-
const stateDir = join(rcsDir, 'state');
|
|
193
|
-
const logsDir = join(rcsDir, 'logs');
|
|
194
|
-
const codexHome = join(cwd, 'codex-home');
|
|
195
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
196
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
197
|
-
await mkdir(logsDir, { recursive: true });
|
|
198
|
-
await mkdir(stateDir, { recursive: true });
|
|
199
|
-
await mkdir(codexHome, { recursive: true });
|
|
200
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
201
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
202
|
-
autoNudge: { enabled: true, delaySec: 0 },
|
|
203
|
-
});
|
|
204
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
205
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
206
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
207
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
208
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
209
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
210
|
-
'last-assistant-message': 'I analyzed the code. Keep going and finish the focused cleanup.',
|
|
211
|
-
});
|
|
212
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
213
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
214
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
215
|
-
const nudgeState = JSON.parse(await readFile(join(sessionStateDir, 'auto-nudge-state.json'), 'utf-8'));
|
|
216
|
-
assert.equal(nudgeState.nudgeCount, 0);
|
|
217
|
-
assert.ok(nudgeState.pendingSignature);
|
|
218
|
-
assert.ok(nudgeState.pendingSince);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
it('sends nudge when stall pattern detected in last-assistant-message', async () => {
|
|
222
|
-
await withTempWorkingDir(async (cwd) => {
|
|
223
|
-
const rcsDir = join(cwd, '.rcs');
|
|
224
|
-
const stateDir = join(rcsDir, 'state');
|
|
225
|
-
const logsDir = join(rcsDir, 'logs');
|
|
226
|
-
const codexHome = join(cwd, 'codex-home');
|
|
227
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
228
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
229
|
-
await mkdir(logsDir, { recursive: true });
|
|
230
|
-
await mkdir(stateDir, { recursive: true });
|
|
231
|
-
await mkdir(codexHome, { recursive: true });
|
|
232
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
233
|
-
// Config: enabled, delaySec=0 for fast tests
|
|
234
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
235
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
236
|
-
});
|
|
237
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
238
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
239
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
240
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
241
|
-
'last-assistant-message': 'I analyzed the code. Keep going and finish the focused cleanup.',
|
|
242
|
-
});
|
|
243
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
244
|
-
assert.ok(existsSync(tmuxLogPath), 'tmux should have been called');
|
|
245
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
246
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'should send nudge response with injection marker');
|
|
247
|
-
// Codex CLI needs C-m sent twice with a delay for reliable submission
|
|
248
|
-
const cmMatches = tmuxLog.match(/send-keys -t %99 C-m/g);
|
|
249
|
-
assert.ok(cmMatches && cmMatches.length >= 2, `should send C-m twice, got ${cmMatches?.length ?? 0}`);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
it('does not auto-nudge planning-phase skill state into execution', async () => {
|
|
253
|
-
await withTempWorkingDir(async (cwd) => {
|
|
254
|
-
const rcsDir = join(cwd, '.rcs');
|
|
255
|
-
const stateDir = join(rcsDir, 'state');
|
|
256
|
-
const logsDir = join(rcsDir, 'logs');
|
|
257
|
-
const codexHome = join(cwd, 'codex-home');
|
|
258
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
259
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
260
|
-
await mkdir(logsDir, { recursive: true });
|
|
261
|
-
await mkdir(stateDir, { recursive: true });
|
|
262
|
-
await mkdir(codexHome, { recursive: true });
|
|
263
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
264
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
265
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
266
|
-
});
|
|
267
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
268
|
-
await writeJson(join(stateDir, 'skill-active-state.json'), {
|
|
269
|
-
active: true,
|
|
270
|
-
skill: 'analyze',
|
|
271
|
-
keyword: 'investigate',
|
|
272
|
-
phase: 'planning',
|
|
273
|
-
source: 'keyword-detector',
|
|
274
|
-
});
|
|
275
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
276
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
277
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
278
|
-
'last-assistant-message': 'I can continue with the plan from here.',
|
|
279
|
-
});
|
|
280
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
281
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
282
|
-
assert.doesNotMatch(tmuxLog, /send-keys -t %99 -l/, 'planning-phase prompts should not be auto-nudged');
|
|
283
|
-
const skillState = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
284
|
-
assert.equal(skillState.phase, 'planning');
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
it('respects `.rcs/tmux-hook.json` enabled:false and skips auto-nudge injection', async () => {
|
|
288
|
-
await withTempWorkingDir(async (cwd) => {
|
|
289
|
-
const rcsDir = join(cwd, '.rcs');
|
|
290
|
-
const stateDir = join(rcsDir, 'state');
|
|
291
|
-
const logsDir = join(rcsDir, 'logs');
|
|
292
|
-
const codexHome = join(cwd, 'codex-home');
|
|
293
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
294
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
295
|
-
await mkdir(logsDir, { recursive: true });
|
|
296
|
-
await mkdir(stateDir, { recursive: true });
|
|
297
|
-
await mkdir(codexHome, { recursive: true });
|
|
298
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
299
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
300
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
301
|
-
});
|
|
302
|
-
await writeJson(join(rcsDir, 'tmux-hook.json'), {
|
|
303
|
-
enabled: false,
|
|
304
|
-
target: { type: 'pane', value: '%99' },
|
|
305
|
-
});
|
|
306
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
307
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
308
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
309
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
310
|
-
'last-assistant-message': 'I analyzed the code. If you want me to make these changes, let me know.',
|
|
311
|
-
});
|
|
312
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
313
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
314
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
it('does not auto-nudge plain tmux Codex sessions that only inherit RCS session env', async () => {
|
|
318
|
-
await withTempWorkingDir(async (cwd) => {
|
|
319
|
-
const rcsDir = join(cwd, '.rcs');
|
|
320
|
-
const stateDir = join(rcsDir, 'state');
|
|
321
|
-
const logsDir = join(rcsDir, 'logs');
|
|
322
|
-
const codexHome = join(cwd, 'codex-home');
|
|
323
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
324
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
325
|
-
await mkdir(logsDir, { recursive: true });
|
|
326
|
-
await mkdir(stateDir, { recursive: true });
|
|
327
|
-
await mkdir(codexHome, { recursive: true });
|
|
328
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
329
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
330
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
331
|
-
});
|
|
332
|
-
const sleeper = spawnSync('bash', ['-lc', 'sleep 5 >/dev/null 2>&1 & echo $!'], { encoding: 'utf8' });
|
|
333
|
-
assert.equal(sleeper.status, 0, sleeper.stderr || sleeper.stdout);
|
|
334
|
-
const sleeperPid = Number((sleeper.stdout || '').trim());
|
|
335
|
-
assert.ok(Number.isFinite(sleeperPid) && sleeperPid > 1, 'expected helper pid');
|
|
336
|
-
await writeJson(join(stateDir, 'session.json'), {
|
|
337
|
-
session_id: 'sess-managed',
|
|
338
|
-
started_at: new Date().toISOString(),
|
|
339
|
-
cwd,
|
|
340
|
-
pid: sleeperPid,
|
|
341
|
-
platform: process.platform,
|
|
342
|
-
pid_start_ticks: readLinuxStartTicks(sleeperPid),
|
|
343
|
-
pid_cmdline: readLinuxCmdline(sleeperPid),
|
|
344
|
-
});
|
|
345
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
346
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
347
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
348
|
-
'session-id': 'sess-managed',
|
|
349
|
-
'last-assistant-message': 'I analyzed the code. If you want me to make these changes, let me know.',
|
|
350
|
-
}, {
|
|
351
|
-
RCS_SESSION_ID: 'sess-managed',
|
|
352
|
-
RCS_TEST_UNMANAGED_SESSION: '1',
|
|
353
|
-
});
|
|
354
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
355
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
356
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
it('does not auto-nudge plain tmux Codex sessions that are not RCS-managed', async () => {
|
|
360
|
-
await withTempWorkingDir(async (cwd) => {
|
|
361
|
-
const rcsDir = join(cwd, '.rcs');
|
|
362
|
-
const stateDir = join(rcsDir, 'state');
|
|
363
|
-
const logsDir = join(rcsDir, 'logs');
|
|
364
|
-
const codexHome = join(cwd, 'codex-home');
|
|
365
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
366
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
367
|
-
await mkdir(logsDir, { recursive: true });
|
|
368
|
-
await mkdir(stateDir, { recursive: true });
|
|
369
|
-
await mkdir(codexHome, { recursive: true });
|
|
370
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
371
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
372
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
373
|
-
});
|
|
374
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
375
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
376
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
377
|
-
'last-assistant-message': 'I analyzed the code. If you want me to make these changes, let me know.',
|
|
378
|
-
}, {
|
|
379
|
-
RCS_TEST_UNMANAGED_SESSION: '1',
|
|
380
|
-
});
|
|
381
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
382
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
383
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
it('does not auto-nudge when payload session-id disagrees with the managed tmux session identity', async () => {
|
|
387
|
-
await withTempWorkingDir(async (cwd) => {
|
|
388
|
-
const rcsDir = join(cwd, '.rcs');
|
|
389
|
-
const stateDir = join(rcsDir, 'state');
|
|
390
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
391
|
-
const logsDir = join(rcsDir, 'logs');
|
|
392
|
-
const codexHome = join(cwd, 'codex-home');
|
|
393
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
394
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
395
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
396
|
-
await mkdir(logsDir, { recursive: true });
|
|
397
|
-
await mkdir(stateDir, { recursive: true });
|
|
398
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
399
|
-
await mkdir(codexHome, { recursive: true });
|
|
400
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
401
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
402
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
403
|
-
});
|
|
404
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
405
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
406
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
407
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
408
|
-
'session-id': 'sess-other',
|
|
409
|
-
'last-assistant-message': 'I analyzed the code. If you want me to make these changes, let me know.',
|
|
410
|
-
}, {
|
|
411
|
-
RCS_SESSION_ID: 'sess-managed',
|
|
412
|
-
RCS_TEST_TMUX_SESSION_NAME: managedSessionName,
|
|
413
|
-
});
|
|
414
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
415
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
416
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
it('does not auto-nudge when tmux session naming drifts from the current RCS session id', async () => {
|
|
420
|
-
await withTempWorkingDir(async (cwd) => {
|
|
421
|
-
const rcsDir = join(cwd, '.rcs');
|
|
422
|
-
const stateDir = join(rcsDir, 'state');
|
|
423
|
-
const logsDir = join(rcsDir, 'logs');
|
|
424
|
-
const codexHome = join(cwd, 'codex-home');
|
|
425
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
426
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
427
|
-
const expectedManagedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
428
|
-
const mismatchedDetachedSessionName = buildTmuxSessionName(cwd, 'sess-legacy-detached');
|
|
429
|
-
await mkdir(logsDir, { recursive: true });
|
|
430
|
-
await mkdir(stateDir, { recursive: true });
|
|
431
|
-
await mkdir(codexHome, { recursive: true });
|
|
432
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
433
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
434
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
435
|
-
});
|
|
436
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
437
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
438
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
439
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
440
|
-
'session-id': 'sess-managed',
|
|
441
|
-
'last-assistant-message': 'I analyzed the code. If you want me to make these changes, let me know.',
|
|
442
|
-
}, {
|
|
443
|
-
RCS_SESSION_ID: 'sess-managed',
|
|
444
|
-
RCS_TEST_TMUX_SESSION_NAME: mismatchedDetachedSessionName,
|
|
445
|
-
});
|
|
446
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
447
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
448
|
-
assert.match(tmuxLog, new RegExp(`list-panes -s -t ${escapeRegex(expectedManagedSessionName)}`), 'should resolve panes against the current RCS session identity, not the drifted tmux session name');
|
|
449
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
it('sends nudge via capture-pane fallback when payload has no stall pattern', async () => {
|
|
453
|
-
await withTempWorkingDir(async (cwd) => {
|
|
454
|
-
const rcsDir = join(cwd, '.rcs');
|
|
455
|
-
const stateDir = join(rcsDir, 'state');
|
|
456
|
-
const logsDir = join(rcsDir, 'logs');
|
|
457
|
-
const codexHome = join(cwd, 'codex-home');
|
|
458
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
459
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
460
|
-
const captureFile = join(cwd, 'capture-output.txt');
|
|
461
|
-
await mkdir(logsDir, { recursive: true });
|
|
462
|
-
await mkdir(stateDir, { recursive: true });
|
|
463
|
-
await mkdir(codexHome, { recursive: true });
|
|
464
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
465
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
466
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
467
|
-
});
|
|
468
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
469
|
-
// capture-pane will return content with a stall pattern
|
|
470
|
-
await writeFile(captureFile, 'Here are the results.\nKeep going and finish the implementation.\n› ');
|
|
471
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
472
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
473
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
474
|
-
'last-assistant-message': 'clean output with no stall',
|
|
475
|
-
}, {
|
|
476
|
-
RCS_TEST_CAPTURE_FILE: captureFile,
|
|
477
|
-
});
|
|
478
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
479
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
480
|
-
assert.match(tmuxLog, /capture-pane/, 'should have tried capture-pane');
|
|
481
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'should send nudge via capture-pane fallback with marker');
|
|
482
|
-
});
|
|
483
|
-
});
|
|
484
|
-
it('does not nudge from PASS/FAIL-style test output captured from the pane', async () => {
|
|
485
|
-
await withTempWorkingDir(async (cwd) => {
|
|
486
|
-
const rcsDir = join(cwd, '.rcs');
|
|
487
|
-
const stateDir = join(rcsDir, 'state');
|
|
488
|
-
const logsDir = join(rcsDir, 'logs');
|
|
489
|
-
const codexHome = join(cwd, 'codex-home');
|
|
490
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
491
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
492
|
-
const captureFile = join(cwd, 'capture-output.txt');
|
|
493
|
-
await mkdir(logsDir, { recursive: true });
|
|
494
|
-
await mkdir(stateDir, { recursive: true });
|
|
495
|
-
await mkdir(codexHome, { recursive: true });
|
|
496
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
497
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
498
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
499
|
-
});
|
|
500
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
501
|
-
await writeFile(captureFile, [
|
|
502
|
-
'PASS should continue with the next step when approvals are present',
|
|
503
|
-
'FAIL aborts the branch cleanly when the worker exits early',
|
|
504
|
-
'Test Suites: 1 failed, 1 total',
|
|
505
|
-
].join('\n'));
|
|
506
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
507
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
508
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
509
|
-
'last-assistant-message': 'clean output with no stall',
|
|
510
|
-
}, {
|
|
511
|
-
RCS_TEST_CAPTURE_FILE: captureFile,
|
|
512
|
-
});
|
|
513
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
514
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
515
|
-
assert.match(tmuxLog, /capture-pane/, 'should still inspect capture-pane output');
|
|
516
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'PASS/FAIL-style test output must not trigger a nudge');
|
|
517
|
-
});
|
|
518
|
-
});
|
|
519
|
-
it('auto-nudges from active mode state by upgrading an anchored shell pane to the sibling codex pane', async () => {
|
|
520
|
-
await withTempWorkingDir(async (cwd) => {
|
|
521
|
-
const rcsDir = join(cwd, '.rcs');
|
|
522
|
-
const stateDir = join(rcsDir, 'state');
|
|
523
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
524
|
-
const logsDir = join(rcsDir, 'logs');
|
|
525
|
-
const codexHome = join(cwd, 'codex-home');
|
|
526
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
527
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
528
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
529
|
-
await mkdir(logsDir, { recursive: true });
|
|
530
|
-
await mkdir(stateDir, { recursive: true });
|
|
531
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
532
|
-
await mkdir(codexHome, { recursive: true });
|
|
533
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
534
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
535
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
536
|
-
});
|
|
537
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
538
|
-
await writeJson(join(sessionStateDir, 'ralph-state.json'), {
|
|
539
|
-
active: true,
|
|
540
|
-
tmux_pane_id: '%99',
|
|
541
|
-
});
|
|
542
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
543
|
-
set -eu
|
|
544
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
545
|
-
cmd="$1"
|
|
546
|
-
shift || true
|
|
547
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
548
|
-
target=""
|
|
549
|
-
format=""
|
|
550
|
-
while [[ "$#" -gt 0 ]]; do
|
|
551
|
-
case "$1" in
|
|
552
|
-
-p) shift ;;
|
|
553
|
-
-t) target="$2"; shift 2 ;;
|
|
554
|
-
*) format="$1"; shift ;;
|
|
555
|
-
esac
|
|
556
|
-
done
|
|
557
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
558
|
-
echo "sh"
|
|
559
|
-
exit 0
|
|
560
|
-
fi
|
|
561
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%100" ]]; then
|
|
562
|
-
echo "node"
|
|
563
|
-
exit 0
|
|
564
|
-
fi
|
|
565
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%100" ]]; then
|
|
566
|
-
echo "codex --model gpt-5"
|
|
567
|
-
exit 0
|
|
568
|
-
fi
|
|
569
|
-
if [[ "$format" == "#{pane_in_mode}" && "$target" == "%100" ]]; then
|
|
570
|
-
echo "0"
|
|
571
|
-
exit 0
|
|
572
|
-
fi
|
|
573
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
574
|
-
echo "${managedSessionName}"
|
|
575
|
-
exit 0
|
|
576
|
-
fi
|
|
577
|
-
exit 0
|
|
578
|
-
fi
|
|
579
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
580
|
-
target=""
|
|
581
|
-
while [[ "$#" -gt 0 ]]; do
|
|
582
|
-
case "$1" in
|
|
583
|
-
-t) target="$2"; shift 2 ;;
|
|
584
|
-
*) shift ;;
|
|
585
|
-
esac
|
|
586
|
-
done
|
|
587
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
588
|
-
printf "%%99\t0\tsh\tbash\n%%100\t1\tnode\tcodex --model gpt-5\n"
|
|
589
|
-
exit 0
|
|
590
|
-
fi
|
|
591
|
-
echo "%1 12345"
|
|
592
|
-
exit 0
|
|
593
|
-
fi
|
|
594
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
595
|
-
printf "How can I help?\n› "
|
|
596
|
-
exit 0
|
|
597
|
-
fi
|
|
598
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
599
|
-
exit 0
|
|
600
|
-
fi
|
|
601
|
-
exit 0
|
|
602
|
-
`;
|
|
603
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
604
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
605
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
606
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
607
|
-
}, {
|
|
608
|
-
TMUX_PANE: '',
|
|
609
|
-
});
|
|
610
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
611
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
612
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%100'), 'should upgrade anchored shell pane to sibling codex pane');
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
it('keeps a verified codex anchor from active mode state even when a sibling codex pane is focused', async () => {
|
|
616
|
-
await withTempWorkingDir(async (cwd) => {
|
|
617
|
-
const rcsDir = join(cwd, '.rcs');
|
|
618
|
-
const stateDir = join(rcsDir, 'state');
|
|
619
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
620
|
-
const logsDir = join(rcsDir, 'logs');
|
|
621
|
-
const codexHome = join(cwd, 'codex-home');
|
|
622
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
623
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
624
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
625
|
-
await mkdir(logsDir, { recursive: true });
|
|
626
|
-
await mkdir(stateDir, { recursive: true });
|
|
627
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
628
|
-
await mkdir(codexHome, { recursive: true });
|
|
629
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
630
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
631
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
632
|
-
});
|
|
633
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
634
|
-
await writeJson(join(sessionStateDir, 'ralph-state.json'), {
|
|
635
|
-
active: true,
|
|
636
|
-
tmux_pane_id: '%99',
|
|
637
|
-
});
|
|
638
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
639
|
-
set -eu
|
|
640
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
641
|
-
cmd="$1"
|
|
642
|
-
shift || true
|
|
643
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
644
|
-
target=""
|
|
645
|
-
format=""
|
|
646
|
-
while [[ "$#" -gt 0 ]]; do
|
|
647
|
-
case "$1" in
|
|
648
|
-
-p) shift ;;
|
|
649
|
-
-t) target="$2"; shift 2 ;;
|
|
650
|
-
*) format="$1"; shift ;;
|
|
651
|
-
esac
|
|
652
|
-
done
|
|
653
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
654
|
-
echo "codex"
|
|
655
|
-
exit 0
|
|
656
|
-
fi
|
|
657
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%99" ]]; then
|
|
658
|
-
echo "codex"
|
|
659
|
-
exit 0
|
|
660
|
-
fi
|
|
661
|
-
if [[ "$format" == "#{pane_in_mode}" && "$target" == "%99" ]]; then
|
|
662
|
-
echo "0"
|
|
663
|
-
exit 0
|
|
664
|
-
fi
|
|
665
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
666
|
-
echo "${managedSessionName}"
|
|
667
|
-
exit 0
|
|
668
|
-
fi
|
|
669
|
-
exit 0
|
|
670
|
-
fi
|
|
671
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
672
|
-
target=""
|
|
673
|
-
while [[ "$#" -gt 0 ]]; do
|
|
674
|
-
case "$1" in
|
|
675
|
-
-t) target="$2"; shift 2 ;;
|
|
676
|
-
*) shift ;;
|
|
677
|
-
esac
|
|
678
|
-
done
|
|
679
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
680
|
-
printf "%%99\t0\tcodex\tcodex\\n%%100\t1\tcodex\tcodex\\n"
|
|
681
|
-
exit 0
|
|
682
|
-
fi
|
|
683
|
-
echo "%1 12345"
|
|
684
|
-
exit 0
|
|
685
|
-
fi
|
|
686
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
687
|
-
printf "How can I help?\\n› "
|
|
688
|
-
exit 0
|
|
689
|
-
fi
|
|
690
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
691
|
-
exit 0
|
|
692
|
-
fi
|
|
693
|
-
exit 0
|
|
694
|
-
`;
|
|
695
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
696
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
697
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
698
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
699
|
-
}, {
|
|
700
|
-
TMUX_PANE: '',
|
|
701
|
-
});
|
|
702
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
703
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
704
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'should keep the verified codex anchor');
|
|
705
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%100'), 'should not jump to the focused sibling codex pane');
|
|
706
|
-
});
|
|
707
|
-
});
|
|
708
|
-
it('upgrades a node shell anchor from active mode state to the sibling codex pane', async () => {
|
|
709
|
-
await withTempWorkingDir(async (cwd) => {
|
|
710
|
-
const rcsDir = join(cwd, '.rcs');
|
|
711
|
-
const stateDir = join(rcsDir, 'state');
|
|
712
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
713
|
-
const logsDir = join(rcsDir, 'logs');
|
|
714
|
-
const codexHome = join(cwd, 'codex-home');
|
|
715
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
716
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
717
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
718
|
-
await mkdir(logsDir, { recursive: true });
|
|
719
|
-
await mkdir(stateDir, { recursive: true });
|
|
720
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
721
|
-
await mkdir(codexHome, { recursive: true });
|
|
722
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
723
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
724
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
725
|
-
});
|
|
726
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
727
|
-
await writeJson(join(sessionStateDir, 'ralph-state.json'), {
|
|
728
|
-
active: true,
|
|
729
|
-
tmux_pane_id: '%99',
|
|
730
|
-
});
|
|
731
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
732
|
-
set -eu
|
|
733
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
734
|
-
cmd="$1"
|
|
735
|
-
shift || true
|
|
736
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
737
|
-
target=""
|
|
738
|
-
format=""
|
|
739
|
-
while [[ "$#" -gt 0 ]]; do
|
|
740
|
-
case "$1" in
|
|
741
|
-
-p) shift ;;
|
|
742
|
-
-t) target="$2"; shift 2 ;;
|
|
743
|
-
*) format="$1"; shift ;;
|
|
744
|
-
esac
|
|
745
|
-
done
|
|
746
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
747
|
-
echo "node"
|
|
748
|
-
exit 0
|
|
749
|
-
fi
|
|
750
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%99" ]]; then
|
|
751
|
-
echo "bash"
|
|
752
|
-
exit 0
|
|
753
|
-
fi
|
|
754
|
-
if [[ "$format" == "#{pane_in_mode}" && "$target" == "%100" ]]; then
|
|
755
|
-
echo "0"
|
|
756
|
-
exit 0
|
|
757
|
-
fi
|
|
758
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
759
|
-
echo "${managedSessionName}"
|
|
760
|
-
exit 0
|
|
761
|
-
fi
|
|
762
|
-
exit 0
|
|
763
|
-
fi
|
|
764
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
765
|
-
target=""
|
|
766
|
-
while [[ "$#" -gt 0 ]]; do
|
|
767
|
-
case "$1" in
|
|
768
|
-
-t) target="$2"; shift 2 ;;
|
|
769
|
-
*) shift ;;
|
|
770
|
-
esac
|
|
771
|
-
done
|
|
772
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
773
|
-
printf "%%99\t0\tnode\tbash\\n%%100\t1\tnode\tcodex --model gpt-5\\n"
|
|
774
|
-
exit 0
|
|
775
|
-
fi
|
|
776
|
-
echo "%1 12345"
|
|
777
|
-
exit 0
|
|
778
|
-
fi
|
|
779
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
780
|
-
printf "How can I help?\\n› "
|
|
781
|
-
exit 0
|
|
782
|
-
fi
|
|
783
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
784
|
-
exit 0
|
|
785
|
-
fi
|
|
786
|
-
exit 0
|
|
787
|
-
`;
|
|
788
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
789
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
790
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
791
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
792
|
-
}, {
|
|
793
|
-
TMUX_PANE: '',
|
|
794
|
-
});
|
|
795
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
796
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
797
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%100'), 'should upgrade the node shell anchor to the sibling codex pane');
|
|
798
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'node shell anchor should not be retained');
|
|
799
|
-
});
|
|
800
|
-
});
|
|
801
|
-
it('upgrades a shell-degraded codex anchor from active mode state to the sibling codex pane', async () => {
|
|
802
|
-
await withTempWorkingDir(async (cwd) => {
|
|
803
|
-
const rcsDir = join(cwd, '.rcs');
|
|
804
|
-
const stateDir = join(rcsDir, 'state');
|
|
805
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
806
|
-
const logsDir = join(rcsDir, 'logs');
|
|
807
|
-
const codexHome = join(cwd, 'codex-home');
|
|
808
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
809
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
810
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
811
|
-
await mkdir(logsDir, { recursive: true });
|
|
812
|
-
await mkdir(stateDir, { recursive: true });
|
|
813
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
814
|
-
await mkdir(codexHome, { recursive: true });
|
|
815
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
816
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
817
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
818
|
-
});
|
|
819
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
820
|
-
await writeJson(join(sessionStateDir, 'ralph-state.json'), {
|
|
821
|
-
active: true,
|
|
822
|
-
tmux_pane_id: '%99',
|
|
823
|
-
});
|
|
824
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
825
|
-
set -eu
|
|
826
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
827
|
-
cmd="$1"
|
|
828
|
-
shift || true
|
|
829
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
830
|
-
target=""
|
|
831
|
-
format=""
|
|
832
|
-
while [[ "$#" -gt 0 ]]; do
|
|
833
|
-
case "$1" in
|
|
834
|
-
-p) shift ;;
|
|
835
|
-
-t) target="$2"; shift 2 ;;
|
|
836
|
-
*) format="$1"; shift ;;
|
|
837
|
-
esac
|
|
838
|
-
done
|
|
839
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
840
|
-
echo "bash"
|
|
841
|
-
exit 0
|
|
842
|
-
fi
|
|
843
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%99" ]]; then
|
|
844
|
-
echo "codex --model gpt-5"
|
|
845
|
-
exit 0
|
|
846
|
-
fi
|
|
847
|
-
if [[ "$format" == "#{pane_in_mode}" && "$target" == "%100" ]]; then
|
|
848
|
-
echo "0"
|
|
849
|
-
exit 0
|
|
850
|
-
fi
|
|
851
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
852
|
-
echo "${managedSessionName}"
|
|
853
|
-
exit 0
|
|
854
|
-
fi
|
|
855
|
-
exit 0
|
|
856
|
-
fi
|
|
857
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
858
|
-
target=""
|
|
859
|
-
while [[ "$#" -gt 0 ]]; do
|
|
860
|
-
case "$1" in
|
|
861
|
-
-t) target="$2"; shift 2 ;;
|
|
862
|
-
*) shift ;;
|
|
863
|
-
esac
|
|
864
|
-
done
|
|
865
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
866
|
-
printf "%%99\t1\tbash\tcodex --model gpt-5\\n%%100\t0\tnode\tcodex --model gpt-5\\n"
|
|
867
|
-
exit 0
|
|
868
|
-
fi
|
|
869
|
-
echo "%1 12345"
|
|
870
|
-
exit 0
|
|
871
|
-
fi
|
|
872
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
873
|
-
printf "How can I help?\\n› "
|
|
874
|
-
exit 0
|
|
875
|
-
fi
|
|
876
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
877
|
-
exit 0
|
|
878
|
-
fi
|
|
879
|
-
exit 0
|
|
880
|
-
`;
|
|
881
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
882
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
883
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
884
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
885
|
-
}, {
|
|
886
|
-
TMUX_PANE: '',
|
|
887
|
-
});
|
|
888
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
889
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
890
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%100'), 'should upgrade the shell-degraded codex anchor to the sibling codex pane');
|
|
891
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'shell-degraded codex anchor should not be retained');
|
|
892
|
-
});
|
|
893
|
-
});
|
|
894
|
-
it('fails closed when a shell-degraded codex anchor has no live sibling pane', async () => {
|
|
895
|
-
await withTempWorkingDir(async (cwd) => {
|
|
896
|
-
const rcsDir = join(cwd, '.rcs');
|
|
897
|
-
const stateDir = join(rcsDir, 'state');
|
|
898
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
899
|
-
const logsDir = join(rcsDir, 'logs');
|
|
900
|
-
const codexHome = join(cwd, 'codex-home');
|
|
901
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
902
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
903
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
904
|
-
await mkdir(logsDir, { recursive: true });
|
|
905
|
-
await mkdir(stateDir, { recursive: true });
|
|
906
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
907
|
-
await mkdir(codexHome, { recursive: true });
|
|
908
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
909
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
910
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
911
|
-
});
|
|
912
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
913
|
-
await writeJson(join(sessionStateDir, 'ralph-state.json'), {
|
|
914
|
-
active: true,
|
|
915
|
-
tmux_pane_id: '%99',
|
|
916
|
-
});
|
|
917
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
918
|
-
set -eu
|
|
919
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
920
|
-
cmd="$1"
|
|
921
|
-
shift || true
|
|
922
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
923
|
-
target=""
|
|
924
|
-
format=""
|
|
925
|
-
while [[ "$#" -gt 0 ]]; do
|
|
926
|
-
case "$1" in
|
|
927
|
-
-p) shift ;;
|
|
928
|
-
-t) target="$2"; shift 2 ;;
|
|
929
|
-
*) format="$1"; shift ;;
|
|
930
|
-
esac
|
|
931
|
-
done
|
|
932
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
933
|
-
echo "bash"
|
|
934
|
-
exit 0
|
|
935
|
-
fi
|
|
936
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%99" ]]; then
|
|
937
|
-
echo "codex --model gpt-5"
|
|
938
|
-
exit 0
|
|
939
|
-
fi
|
|
940
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
941
|
-
echo "${managedSessionName}"
|
|
942
|
-
exit 0
|
|
943
|
-
fi
|
|
944
|
-
exit 0
|
|
945
|
-
fi
|
|
946
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
947
|
-
target=""
|
|
948
|
-
while [[ "$#" -gt 0 ]]; do
|
|
949
|
-
case "$1" in
|
|
950
|
-
-t) target="$2"; shift 2 ;;
|
|
951
|
-
*) shift ;;
|
|
952
|
-
esac
|
|
953
|
-
done
|
|
954
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
955
|
-
printf "%%99\t1\tbash\tcodex --model gpt-5\\n%%100\t0\tbash\tbash\\n"
|
|
956
|
-
exit 0
|
|
957
|
-
fi
|
|
958
|
-
echo "%1 12345"
|
|
959
|
-
exit 0
|
|
960
|
-
fi
|
|
961
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
962
|
-
printf "How can I help?\\n› "
|
|
963
|
-
exit 0
|
|
964
|
-
fi
|
|
965
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
966
|
-
exit 0
|
|
967
|
-
fi
|
|
968
|
-
exit 0
|
|
969
|
-
`;
|
|
970
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
971
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
972
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
973
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
974
|
-
}, {
|
|
975
|
-
TMUX_PANE: '',
|
|
976
|
-
});
|
|
977
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
978
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
979
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'shell-degraded codex anchor should not be retained without a live sibling');
|
|
980
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%100'), 'no live sibling should keep auto-nudge from sending input');
|
|
981
|
-
});
|
|
982
|
-
});
|
|
983
|
-
it('still auto-nudges in team-worker context using the worker state root', async () => {
|
|
984
|
-
await withTempWorkingDir(async (cwd) => {
|
|
985
|
-
const workerStateRoot = join(cwd, 'leader-state-root');
|
|
986
|
-
const logsDir = join(cwd, '.rcs', 'logs');
|
|
987
|
-
const codexHome = join(cwd, 'codex-home');
|
|
988
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
989
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
990
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
991
|
-
await mkdir(logsDir, { recursive: true });
|
|
992
|
-
await mkdir(workerStateRoot, { recursive: true });
|
|
993
|
-
await mkdir(codexHome, { recursive: true });
|
|
994
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
995
|
-
await writeWorkerIdentityFixture(workerStateRoot, cwd, 'auto-nudge', 'worker-1');
|
|
996
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
997
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
998
|
-
});
|
|
999
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1000
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1001
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1002
|
-
'last-assistant-message': 'I can continue with the worker follow-up from here.',
|
|
1003
|
-
}, {
|
|
1004
|
-
RCS_TEAM_WORKER: 'auto-nudge/worker-1',
|
|
1005
|
-
RCS_TEAM_STATE_ROOT: workerStateRoot,
|
|
1006
|
-
});
|
|
1007
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1008
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1009
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'team-worker context should still send auto-nudge');
|
|
1010
|
-
const nudgeStatePath = join(workerStateRoot, 'auto-nudge-state.json');
|
|
1011
|
-
assert.ok(existsSync(nudgeStatePath), 'worker state root should receive auto-nudge state');
|
|
1012
|
-
});
|
|
1013
|
-
});
|
|
1014
|
-
it('fails closed in team-worker context when the worker state root lacks a valid identity', async () => {
|
|
1015
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1016
|
-
const localStateRoot = join(cwd, '.rcs', 'state');
|
|
1017
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1018
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1019
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1020
|
-
await mkdir(localStateRoot, { recursive: true });
|
|
1021
|
-
await mkdir(codexHome, { recursive: true });
|
|
1022
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1023
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1024
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1025
|
-
});
|
|
1026
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1027
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1028
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1029
|
-
'last-assistant-message': 'I can continue with the worker follow-up from here.',
|
|
1030
|
-
}, {
|
|
1031
|
-
RCS_TEAM_WORKER: 'auto-nudge/worker-1',
|
|
1032
|
-
RCS_TEAM_STATE_ROOT: '',
|
|
1033
|
-
});
|
|
1034
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1035
|
-
assert.equal(existsSync(join(localStateRoot, 'auto-nudge-state.json')), false, 'unvalidated worker cwd state root must not receive auto-nudge state');
|
|
1036
|
-
assert.equal(existsSync(join(localStateRoot, 'team', 'auto-nudge', 'workers', 'worker-1', 'heartbeat.json')), false, 'unvalidated worker cwd state root must not receive heartbeat state');
|
|
1037
|
-
if (existsSync(tmuxLogPath)) {
|
|
1038
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1039
|
-
assert.doesNotMatch(tmuxLog, /send-keys/, 'unvalidated worker state root must not inject auto-nudge input');
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
|
-
});
|
|
1043
|
-
it('still auto-nudges from the stored worker pane when TMUX_PANE is missing and the worker pane looks shell-degraded', async () => {
|
|
1044
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1045
|
-
const workerStateRoot = join(cwd, 'leader-state-root');
|
|
1046
|
-
const logsDir = join(cwd, '.rcs', 'logs');
|
|
1047
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1048
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1049
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1050
|
-
await mkdir(logsDir, { recursive: true });
|
|
1051
|
-
await mkdir(workerStateRoot, { recursive: true });
|
|
1052
|
-
await mkdir(codexHome, { recursive: true });
|
|
1053
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1054
|
-
await writeWorkerIdentityFixture(workerStateRoot, cwd, 'auto-nudge', 'worker-1');
|
|
1055
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1056
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1057
|
-
});
|
|
1058
|
-
await writeJson(join(workerStateRoot, 'ralph-state.json'), {
|
|
1059
|
-
active: true,
|
|
1060
|
-
tmux_pane_id: '%99',
|
|
1061
|
-
});
|
|
1062
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
1063
|
-
set -eu
|
|
1064
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
1065
|
-
cmd="$1"
|
|
1066
|
-
shift || true
|
|
1067
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
1068
|
-
target=""
|
|
1069
|
-
format=""
|
|
1070
|
-
while [[ "$#" -gt 0 ]]; do
|
|
1071
|
-
case "$1" in
|
|
1072
|
-
-p) shift ;;
|
|
1073
|
-
-t) target="$2"; shift 2 ;;
|
|
1074
|
-
*) format="$1"; shift ;;
|
|
1075
|
-
esac
|
|
1076
|
-
done
|
|
1077
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
1078
|
-
echo "bash"
|
|
1079
|
-
exit 0
|
|
1080
|
-
fi
|
|
1081
|
-
if [[ "$format" == "#{pane_start_command}" && "$target" == "%99" ]]; then
|
|
1082
|
-
echo "codex --model gpt-5"
|
|
1083
|
-
exit 0
|
|
1084
|
-
fi
|
|
1085
|
-
if [[ "$format" == "#{pane_in_mode}" && "$target" == "%99" ]]; then
|
|
1086
|
-
echo "0"
|
|
1087
|
-
exit 0
|
|
1088
|
-
fi
|
|
1089
|
-
exit 0
|
|
1090
|
-
fi
|
|
1091
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
1092
|
-
printf "How can I help?\\n› "
|
|
1093
|
-
exit 0
|
|
1094
|
-
fi
|
|
1095
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
1096
|
-
exit 0
|
|
1097
|
-
fi
|
|
1098
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
1099
|
-
echo "%1 12345"
|
|
1100
|
-
exit 0
|
|
1101
|
-
fi
|
|
1102
|
-
exit 0
|
|
1103
|
-
`;
|
|
1104
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
1105
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1106
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1107
|
-
'last-assistant-message': 'I can continue with the worker follow-up from here.',
|
|
1108
|
-
}, {
|
|
1109
|
-
RCS_TEAM_WORKER: 'auto-nudge/worker-1',
|
|
1110
|
-
RCS_TEAM_STATE_ROOT: workerStateRoot,
|
|
1111
|
-
TMUX_PANE: '',
|
|
1112
|
-
});
|
|
1113
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1114
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1115
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'worker fallback should keep using the stored pane when TMUX_PANE is absent');
|
|
1116
|
-
});
|
|
1117
|
-
});
|
|
1118
|
-
it('does not nudge when no stall pattern is present', async () => {
|
|
1119
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1120
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1121
|
-
const stateDir = join(rcsDir, 'state');
|
|
1122
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1123
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1124
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1125
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1126
|
-
await mkdir(logsDir, { recursive: true });
|
|
1127
|
-
await mkdir(stateDir, { recursive: true });
|
|
1128
|
-
await mkdir(codexHome, { recursive: true });
|
|
1129
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1130
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1131
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1132
|
-
});
|
|
1133
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1134
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1135
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1136
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1137
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1138
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1139
|
-
'last-assistant-message': 'I completed the refactoring. All tests pass.',
|
|
1140
|
-
});
|
|
1141
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1142
|
-
if (existsSync(tmuxLogPath)) {
|
|
1143
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1144
|
-
assert.doesNotMatch(tmuxLog, new RegExp(`send-keys -t %99 -l ${escapeRegex(DEFAULT_AUTO_NUDGE_RESPONSE)}`), 'should NOT send nudge');
|
|
1145
|
-
}
|
|
1146
|
-
});
|
|
1147
|
-
});
|
|
1148
|
-
it('logs agent_not_running with pane_current_command when the target pane is a shell', async () => {
|
|
1149
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1150
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1151
|
-
const stateDir = join(rcsDir, 'state');
|
|
1152
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1153
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1154
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1155
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1156
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
1157
|
-
await mkdir(logsDir, { recursive: true });
|
|
1158
|
-
await mkdir(stateDir, { recursive: true });
|
|
1159
|
-
await mkdir(codexHome, { recursive: true });
|
|
1160
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1161
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1162
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1163
|
-
});
|
|
1164
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
1165
|
-
set -eu
|
|
1166
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
1167
|
-
cmd="$1"
|
|
1168
|
-
shift || true
|
|
1169
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
1170
|
-
target=""
|
|
1171
|
-
format=""
|
|
1172
|
-
while (($#)); do
|
|
1173
|
-
case "$1" in
|
|
1174
|
-
-p) shift ;;
|
|
1175
|
-
-t) target="$2"; shift 2 ;;
|
|
1176
|
-
*) format="$1"; shift ;;
|
|
1177
|
-
esac
|
|
1178
|
-
done
|
|
1179
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
1180
|
-
echo "zsh"
|
|
1181
|
-
exit 0
|
|
1182
|
-
fi
|
|
1183
|
-
exit 0
|
|
1184
|
-
fi
|
|
1185
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
1186
|
-
printf "Would you like me to continue?\\n"
|
|
1187
|
-
exit 0
|
|
1188
|
-
fi
|
|
1189
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
1190
|
-
exit 0
|
|
1191
|
-
fi
|
|
1192
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
1193
|
-
echo "%1 12345"
|
|
1194
|
-
exit 0
|
|
1195
|
-
fi
|
|
1196
|
-
exit 0
|
|
1197
|
-
`;
|
|
1198
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
1199
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1200
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1201
|
-
'last-assistant-message': 'Would you like me to continue?',
|
|
1202
|
-
});
|
|
1203
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1204
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1205
|
-
assert.ok(tmuxLog.includes('display-message -p -t %99 #S'), 'should inspect the managed anchor pane before deciding');
|
|
1206
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'shell pane should not receive auto-nudge injection');
|
|
1207
|
-
});
|
|
1208
|
-
});
|
|
1209
|
-
it('falls back to the sibling codex pane when TMUX_PANE is a managed non-agent shell pane', async () => {
|
|
1210
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1211
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1212
|
-
const stateDir = join(rcsDir, 'state');
|
|
1213
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1214
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1215
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1216
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1217
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
1218
|
-
await mkdir(logsDir, { recursive: true });
|
|
1219
|
-
await mkdir(stateDir, { recursive: true });
|
|
1220
|
-
await mkdir(codexHome, { recursive: true });
|
|
1221
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1222
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1223
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1224
|
-
});
|
|
1225
|
-
const fakeTmux = `#!/usr/bin/env bash
|
|
1226
|
-
set -eu
|
|
1227
|
-
echo "$@" >> "${tmuxLogPath}"
|
|
1228
|
-
cmd="$1"
|
|
1229
|
-
shift || true
|
|
1230
|
-
if [[ "$cmd" == "display-message" ]]; then
|
|
1231
|
-
target=""
|
|
1232
|
-
format=""
|
|
1233
|
-
while (($#)); do
|
|
1234
|
-
case "$1" in
|
|
1235
|
-
-p) shift ;;
|
|
1236
|
-
-t) target="$2"; shift 2 ;;
|
|
1237
|
-
*) format="$1"; shift ;;
|
|
1238
|
-
esac
|
|
1239
|
-
done
|
|
1240
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%99" ]]; then
|
|
1241
|
-
echo "sh"
|
|
1242
|
-
exit 0
|
|
1243
|
-
fi
|
|
1244
|
-
if [[ "$format" == "#{pane_current_command}" && "$target" == "%100" ]]; then
|
|
1245
|
-
echo "node"
|
|
1246
|
-
exit 0
|
|
1247
|
-
fi
|
|
1248
|
-
if [[ "$format" == "#S" && "$target" == "%99" ]]; then
|
|
1249
|
-
echo "${managedSessionName}"
|
|
1250
|
-
exit 0
|
|
1251
|
-
fi
|
|
1252
|
-
if [[ "$format" == "#S" && "$target" == "%100" ]]; then
|
|
1253
|
-
echo "${managedSessionName}"
|
|
1254
|
-
exit 0
|
|
1255
|
-
fi
|
|
1256
|
-
if [[ "$format" == "#{pane_current_path}" && "$target" == "%99" ]]; then
|
|
1257
|
-
echo "${cwd}"
|
|
1258
|
-
exit 0
|
|
1259
|
-
fi
|
|
1260
|
-
if [[ "$format" == "#{pane_current_path}" && "$target" == "%100" ]]; then
|
|
1261
|
-
echo "${cwd}"
|
|
1262
|
-
exit 0
|
|
1263
|
-
fi
|
|
1264
|
-
exit 0
|
|
1265
|
-
fi
|
|
1266
|
-
if [[ "$cmd" == "capture-pane" ]]; then
|
|
1267
|
-
printf "› keep going\\n\\n• keep going\\n\\n› Implement {feature}\\n\\n gpt-5.5 high · dev · 98%% left\\n"
|
|
1268
|
-
exit 0
|
|
1269
|
-
fi
|
|
1270
|
-
if [[ "$cmd" == "send-keys" ]]; then
|
|
1271
|
-
exit 0
|
|
1272
|
-
fi
|
|
1273
|
-
if [[ "$cmd" == "list-panes" ]]; then
|
|
1274
|
-
target=""
|
|
1275
|
-
while (($#)); do
|
|
1276
|
-
case "$1" in
|
|
1277
|
-
-t) target="$2"; shift 2 ;;
|
|
1278
|
-
*) shift ;;
|
|
1279
|
-
esac
|
|
1280
|
-
done
|
|
1281
|
-
if [[ "$target" == "${managedSessionName}" ]]; then
|
|
1282
|
-
printf "%%99\t1\tsh\tbash\\n%%100\t0\tnode\tcodex --model gpt-5\\n"
|
|
1283
|
-
exit 0
|
|
1284
|
-
fi
|
|
1285
|
-
echo "%1 12345"
|
|
1286
|
-
exit 0
|
|
1287
|
-
fi
|
|
1288
|
-
exit 0
|
|
1289
|
-
`;
|
|
1290
|
-
await writeFile(join(fakeBinDir, 'tmux'), fakeTmux);
|
|
1291
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1292
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1293
|
-
'last-assistant-message': 'keep going',
|
|
1294
|
-
});
|
|
1295
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1296
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1297
|
-
assert.match(tmuxLog, /display-message -p #S/);
|
|
1298
|
-
assert.ok(tmuxLog.includes('display-message -p -t %99 #S'), 'should inspect the anchored shell pane before upgrading');
|
|
1299
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%100'));
|
|
1300
|
-
});
|
|
1301
|
-
});
|
|
1302
|
-
it('logs scroll_active and avoids send-keys when auto-nudge target pane is in copy-mode', async () => {
|
|
1303
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1304
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1305
|
-
const stateDir = join(rcsDir, 'state');
|
|
1306
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1307
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1308
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1309
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1310
|
-
const managedSessionName = buildTmuxSessionName(cwd, 'sess-managed');
|
|
1311
|
-
await mkdir(logsDir, { recursive: true });
|
|
1312
|
-
await mkdir(stateDir, { recursive: true });
|
|
1313
|
-
await mkdir(codexHome, { recursive: true });
|
|
1314
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1315
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1316
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1317
|
-
});
|
|
1318
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath, '1'));
|
|
1319
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1320
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1321
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
1322
|
-
});
|
|
1323
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1324
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1325
|
-
assert.match(tmuxLog, /display-message -p #S/);
|
|
1326
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'copy-mode pane should not receive auto-nudge injection');
|
|
1327
|
-
});
|
|
1328
|
-
});
|
|
1329
|
-
it('does not nudge when pane capture shows an active task despite stall-like assistant text', async () => {
|
|
1330
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1331
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1332
|
-
const stateDir = join(rcsDir, 'state');
|
|
1333
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1334
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1335
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1336
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1337
|
-
const captureFile = join(cwd, 'capture-output.txt');
|
|
1338
|
-
await mkdir(logsDir, { recursive: true });
|
|
1339
|
-
await mkdir(stateDir, { recursive: true });
|
|
1340
|
-
await mkdir(codexHome, { recursive: true });
|
|
1341
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1342
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1343
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1344
|
-
});
|
|
1345
|
-
await writeFile(captureFile, [
|
|
1346
|
-
'Working...',
|
|
1347
|
-
'• Running tests (3m 12s • esc to interrupt)',
|
|
1348
|
-
'',
|
|
1349
|
-
].join('\n'));
|
|
1350
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1351
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1352
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1353
|
-
'last-assistant-message': 'Would you like me to continue with the next step?',
|
|
1354
|
-
}, {
|
|
1355
|
-
RCS_TEST_CAPTURE_FILE: captureFile,
|
|
1356
|
-
});
|
|
1357
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1358
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1359
|
-
assert.match(tmuxLog, /display-message -p #S/);
|
|
1360
|
-
assert.match(tmuxLog, /capture-pane -t %99/, 'busy pane detection should inspect capture output');
|
|
1361
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), 'busy pane should not receive auto-nudge injection');
|
|
1362
|
-
});
|
|
1363
|
-
});
|
|
1364
|
-
it('respects enabled=false configuration', async () => {
|
|
1365
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1366
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1367
|
-
const stateDir = join(rcsDir, 'state');
|
|
1368
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1369
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1370
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1371
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1372
|
-
await mkdir(logsDir, { recursive: true });
|
|
1373
|
-
await mkdir(stateDir, { recursive: true });
|
|
1374
|
-
await mkdir(codexHome, { recursive: true });
|
|
1375
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1376
|
-
// Explicitly disabled
|
|
1377
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1378
|
-
autoNudge: { enabled: false, delaySec: 0 },
|
|
1379
|
-
});
|
|
1380
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1381
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1382
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1383
|
-
'last-assistant-message': 'Would you like me to proceed?',
|
|
1384
|
-
});
|
|
1385
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1386
|
-
if (existsSync(tmuxLogPath)) {
|
|
1387
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1388
|
-
assert.doesNotMatch(tmuxLog, /send-keys -t %99 -l/, 'should NOT send nudge when disabled');
|
|
1389
|
-
}
|
|
1390
|
-
});
|
|
1391
|
-
});
|
|
1392
|
-
it('deduplicates semantic proceed-style variants on the same turn', async () => {
|
|
1393
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1394
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1395
|
-
const stateDir = join(rcsDir, 'state');
|
|
1396
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1397
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1398
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1399
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1400
|
-
await mkdir(logsDir, { recursive: true });
|
|
1401
|
-
await mkdir(stateDir, { recursive: true });
|
|
1402
|
-
await mkdir(codexHome, { recursive: true });
|
|
1403
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1404
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1405
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, ttlMs: 0 },
|
|
1406
|
-
});
|
|
1407
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1408
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1409
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1410
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1411
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1412
|
-
const sharedTurnId = 'semantic-dedup-turn';
|
|
1413
|
-
const first = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1414
|
-
'turn-id': sharedTurnId,
|
|
1415
|
-
'last-assistant-message': 'Keep going and finish the cleanup from here.',
|
|
1416
|
-
});
|
|
1417
|
-
assert.equal(first.status, 0, `first hook failed: ${first.stderr || first.stdout}`);
|
|
1418
|
-
const second = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1419
|
-
'turn-id': sharedTurnId,
|
|
1420
|
-
'last-assistant-message': 'Continue with the cleanup from here.',
|
|
1421
|
-
});
|
|
1422
|
-
assert.equal(second.status, 0, `second hook failed: ${second.stderr || second.stdout}`);
|
|
1423
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1424
|
-
assert.equal((tmuxLog.match(new RegExp(defaultAutoNudgePattern('%99').source, 'g')) || []).length, 1);
|
|
1425
|
-
const nudgeState = JSON.parse(await readFile(join(sessionStateDir, 'auto-nudge-state.json'), 'utf-8'));
|
|
1426
|
-
assert.equal(nudgeState.nudgeCount, 1);
|
|
1427
|
-
assert.match(nudgeState.lastSignature, /^hud:1\|.*\|stall:proceed_intent$/);
|
|
1428
|
-
});
|
|
1429
|
-
});
|
|
1430
|
-
it('applies TTL suppression between similar nudges and allows a later retry after TTL', async () => {
|
|
1431
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1432
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1433
|
-
const stateDir = join(rcsDir, 'state');
|
|
1434
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1435
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1436
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1437
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1438
|
-
await mkdir(logsDir, { recursive: true });
|
|
1439
|
-
await mkdir(stateDir, { recursive: true });
|
|
1440
|
-
await mkdir(codexHome, { recursive: true });
|
|
1441
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1442
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1443
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, ttlMs: 5000 },
|
|
1444
|
-
});
|
|
1445
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1446
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1447
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1448
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1449
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1450
|
-
const first = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1451
|
-
'turn-id': 'cooldown-turn-1',
|
|
1452
|
-
'last-assistant-message': 'Continue with the implementation from here.',
|
|
1453
|
-
});
|
|
1454
|
-
assert.equal(first.status, 0, `first hook failed: ${first.stderr || first.stdout}`);
|
|
1455
|
-
const second = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1456
|
-
'turn-id': 'cooldown-turn-2',
|
|
1457
|
-
'last-assistant-message': 'I can also move forward with the implementation.',
|
|
1458
|
-
});
|
|
1459
|
-
assert.equal(second.status, 0, `second hook failed: ${second.stderr || second.stdout}`);
|
|
1460
|
-
let tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1461
|
-
assert.equal((tmuxLog.match(new RegExp(defaultAutoNudgePattern('%99').source, 'g')) || []).length, 1);
|
|
1462
|
-
const nudgeStatePath = join(sessionStateDir, 'auto-nudge-state.json');
|
|
1463
|
-
const nudgeStateBeforeThird = JSON.parse(await readFile(nudgeStatePath, 'utf-8'));
|
|
1464
|
-
await writeJson(nudgeStatePath, {
|
|
1465
|
-
...nudgeStateBeforeThird,
|
|
1466
|
-
lastNudgeAt: '2026-03-01T00:00:00.000Z',
|
|
1467
|
-
});
|
|
1468
|
-
const third = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1469
|
-
'turn-id': 'cooldown-turn-3',
|
|
1470
|
-
'last-assistant-message': 'Keep going and finish the focused tests.',
|
|
1471
|
-
});
|
|
1472
|
-
assert.equal(third.status, 0, `third hook failed: ${third.stderr || third.stdout}`);
|
|
1473
|
-
tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1474
|
-
assert.equal((tmuxLog.match(new RegExp(defaultAutoNudgePattern('%99').source, 'g')) || []).length, 2);
|
|
1475
|
-
const nudgeState = JSON.parse(await readFile(nudgeStatePath, 'utf-8'));
|
|
1476
|
-
assert.equal(nudgeState.nudgeCount, 2);
|
|
1477
|
-
assert.equal(nudgeState.lastSemanticSignature, 'stall:proceed_intent');
|
|
1478
|
-
});
|
|
1479
|
-
});
|
|
1480
|
-
it('does not resend the exact same stalled turn after TTL expiry', async () => {
|
|
1481
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1482
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1483
|
-
const stateDir = join(rcsDir, 'state');
|
|
1484
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1485
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1486
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1487
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1488
|
-
const lastTurnAt = '2026-03-01T00:00:00.000Z';
|
|
1489
|
-
const lastMessage = 'Keep going and finish the cleanup from here.';
|
|
1490
|
-
await mkdir(logsDir, { recursive: true });
|
|
1491
|
-
await mkdir(stateDir, { recursive: true });
|
|
1492
|
-
await mkdir(codexHome, { recursive: true });
|
|
1493
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1494
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1495
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, ttlMs: 5000 },
|
|
1496
|
-
});
|
|
1497
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1498
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1499
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1500
|
-
await writeJson(join(sessionStateDir, 'hud-state.json'), {
|
|
1501
|
-
last_turn_at: lastTurnAt,
|
|
1502
|
-
turn_count: 1,
|
|
1503
|
-
last_agent_output: lastMessage,
|
|
1504
|
-
});
|
|
1505
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1506
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1507
|
-
const first = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1508
|
-
'turn-id': 'stalled-turn-1',
|
|
1509
|
-
'last-assistant-message': lastMessage,
|
|
1510
|
-
});
|
|
1511
|
-
assert.equal(first.status, 0, `first hook failed: ${first.stderr || first.stdout}`);
|
|
1512
|
-
const nudgeStatePath = join(sessionStateDir, 'auto-nudge-state.json');
|
|
1513
|
-
const firstState = JSON.parse(await readFile(nudgeStatePath, 'utf-8'));
|
|
1514
|
-
await writeJson(nudgeStatePath, {
|
|
1515
|
-
...firstState,
|
|
1516
|
-
lastNudgeAt: '2026-03-01T00:00:10.000Z',
|
|
1517
|
-
});
|
|
1518
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1519
|
-
'turn-id': 'stalled-turn-1',
|
|
1520
|
-
'last-assistant-message': lastMessage,
|
|
1521
|
-
});
|
|
1522
|
-
assert.equal(result.status, 0, `second hook failed: ${result.stderr || result.stdout}`);
|
|
1523
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
1524
|
-
assert.equal((tmuxLog.match(new RegExp(defaultAutoNudgePattern('%99').source, 'g')) || []).length, 1);
|
|
1525
|
-
const nudgeState = JSON.parse(await readFile(nudgeStatePath, 'utf-8'));
|
|
1526
|
-
assert.equal(nudgeState.nudgeCount, 1);
|
|
1527
|
-
assert.equal(nudgeState.lastSignature, firstState.lastSignature);
|
|
1528
|
-
});
|
|
1529
|
-
});
|
|
1530
|
-
it('ignores non-turn-complete payloads so the same stalled reply cannot re-nudge without a new Codex boundary', async () => {
|
|
1531
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1532
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1533
|
-
const stateDir = join(rcsDir, 'state');
|
|
1534
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1535
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1536
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1537
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1538
|
-
const lastMessage = 'Keep going and finish the cleanup from here.';
|
|
1539
|
-
await mkdir(logsDir, { recursive: true });
|
|
1540
|
-
await mkdir(stateDir, { recursive: true });
|
|
1541
|
-
await mkdir(codexHome, { recursive: true });
|
|
1542
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1543
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1544
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, ttlMs: 0 },
|
|
1545
|
-
});
|
|
1546
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1547
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1548
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1549
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1550
|
-
const first = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1551
|
-
type: 'agent-turn-complete',
|
|
1552
|
-
'turn-id': 'turn-complete-1',
|
|
1553
|
-
'last-assistant-message': lastMessage,
|
|
1554
|
-
});
|
|
1555
|
-
assert.equal(first.status, 0, `first hook failed: ${first.stderr || first.stdout}`);
|
|
1556
|
-
const second = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1557
|
-
type: 'function_call_output',
|
|
1558
|
-
'turn-id': 'function-call-output-1',
|
|
1559
|
-
'last-assistant-message': lastMessage,
|
|
1560
|
-
});
|
|
1561
|
-
assert.equal(second.status, 0, `second hook failed: ${second.stderr || second.stdout}`);
|
|
1562
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1563
|
-
assert.equal((tmuxLog.match(new RegExp(defaultAutoNudgePattern('%99').source, 'g')) || []).length, 1);
|
|
1564
|
-
const hudState = JSON.parse(await readFile(join(sessionStateDir, 'hud-state.json'), 'utf-8'));
|
|
1565
|
-
assert.equal(hudState.turn_count, 1);
|
|
1566
|
-
const nudgeState = JSON.parse(await readFile(join(sessionStateDir, 'auto-nudge-state.json'), 'utf-8'));
|
|
1567
|
-
assert.equal(nudgeState.nudgeCount, 1);
|
|
1568
|
-
assert.match(nudgeState.lastSignature, /^hud:1\|.*\|stall:proceed_intent$/);
|
|
1569
|
-
});
|
|
1570
|
-
});
|
|
1571
|
-
it('uses custom response from config', async () => {
|
|
1572
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1573
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1574
|
-
const stateDir = join(rcsDir, 'state');
|
|
1575
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1576
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1577
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1578
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1579
|
-
await mkdir(logsDir, { recursive: true });
|
|
1580
|
-
await mkdir(stateDir, { recursive: true });
|
|
1581
|
-
await mkdir(codexHome, { recursive: true });
|
|
1582
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1583
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1584
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, response: 'continue now' },
|
|
1585
|
-
});
|
|
1586
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1587
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1588
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1589
|
-
'last-assistant-message': 'Keep going and implement this feature.',
|
|
1590
|
-
});
|
|
1591
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1592
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1593
|
-
assert.match(tmuxLog, /send-keys -t %99 -l continue now \[RCS_TMUX_INJECT\]/, 'should use custom response with marker');
|
|
1594
|
-
});
|
|
1595
|
-
});
|
|
1596
|
-
it('tracks nudge count in auto-nudge-state.json', async () => {
|
|
1597
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1598
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1599
|
-
const stateDir = join(rcsDir, 'state');
|
|
1600
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1601
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1602
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1603
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1604
|
-
await mkdir(logsDir, { recursive: true });
|
|
1605
|
-
await mkdir(stateDir, { recursive: true });
|
|
1606
|
-
await mkdir(codexHome, { recursive: true });
|
|
1607
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1608
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1609
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1610
|
-
});
|
|
1611
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1612
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1613
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1614
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1615
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1616
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1617
|
-
'last-assistant-message': 'Keep going and finish the focused cleanup.',
|
|
1618
|
-
});
|
|
1619
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1620
|
-
const nudgeStatePath = join(sessionStateDir, 'auto-nudge-state.json');
|
|
1621
|
-
assert.ok(existsSync(nudgeStatePath), 'auto-nudge-state.json should be created');
|
|
1622
|
-
const nudgeState = JSON.parse(await readFile(nudgeStatePath, 'utf-8'));
|
|
1623
|
-
assert.equal(nudgeState.nudgeCount, 1, 'nudge count should be 1');
|
|
1624
|
-
assert.ok(nudgeState.lastNudgeAt, 'should have lastNudgeAt timestamp');
|
|
1625
|
-
});
|
|
1626
|
-
});
|
|
1627
|
-
it('writes skill-active-state.json when keyword activation is detected', async () => {
|
|
1628
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1629
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1630
|
-
const stateDir = join(rcsDir, 'state');
|
|
1631
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1632
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1633
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1634
|
-
await mkdir(logsDir, { recursive: true });
|
|
1635
|
-
await mkdir(stateDir, { recursive: true });
|
|
1636
|
-
await mkdir(codexHome, { recursive: true });
|
|
1637
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1638
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1639
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1640
|
-
});
|
|
1641
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
1642
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1643
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1644
|
-
'input-messages': ['please use $autopilot for this task'],
|
|
1645
|
-
'last-assistant-message': 'Here is the plan I will follow.',
|
|
1646
|
-
});
|
|
1647
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1648
|
-
const skillStatePath = join(stateDir, 'skill-active-state.json');
|
|
1649
|
-
assert.ok(existsSync(skillStatePath), 'skill-active-state.json should be created');
|
|
1650
|
-
const skillState = JSON.parse(await readFile(skillStatePath, 'utf-8'));
|
|
1651
|
-
assert.equal(skillState.skill, 'autopilot');
|
|
1652
|
-
assert.equal(skillState.phase, 'ralplan');
|
|
1653
|
-
assert.equal(skillState.active, true);
|
|
1654
|
-
});
|
|
1655
|
-
});
|
|
1656
|
-
it('disables auto-nudge entirely when deep-interview mode state is active', async () => {
|
|
1657
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1658
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1659
|
-
const stateDir = join(rcsDir, 'state');
|
|
1660
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1661
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1662
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1663
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1664
|
-
await mkdir(logsDir, { recursive: true });
|
|
1665
|
-
await mkdir(stateDir, { recursive: true });
|
|
1666
|
-
await mkdir(codexHome, { recursive: true });
|
|
1667
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1668
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1669
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1670
|
-
});
|
|
1671
|
-
await writeJson(join(stateDir, 'deep-interview-state.json'), {
|
|
1672
|
-
active: true,
|
|
1673
|
-
mode: 'deep-interview',
|
|
1674
|
-
current_phase: 'deep-interview',
|
|
1675
|
-
});
|
|
1676
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1677
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1678
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1679
|
-
'last-assistant-message': 'Would you like me to continue?',
|
|
1680
|
-
});
|
|
1681
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1682
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
1683
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
1684
|
-
});
|
|
1685
|
-
});
|
|
1686
|
-
it('disables auto-nudge when only skill-active-state carries the deep-interview input lock', async () => {
|
|
1687
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1688
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1689
|
-
const stateDir = join(rcsDir, 'state');
|
|
1690
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1691
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1692
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1693
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1694
|
-
await mkdir(logsDir, { recursive: true });
|
|
1695
|
-
await mkdir(stateDir, { recursive: true });
|
|
1696
|
-
await mkdir(codexHome, { recursive: true });
|
|
1697
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1698
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1699
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1700
|
-
});
|
|
1701
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1702
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1703
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1704
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
1705
|
-
version: 1,
|
|
1706
|
-
active: true,
|
|
1707
|
-
skill: 'deep-interview',
|
|
1708
|
-
keyword: 'deep interview',
|
|
1709
|
-
phase: 'executing',
|
|
1710
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
1711
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
1712
|
-
source: 'keyword-detector',
|
|
1713
|
-
input_lock: {
|
|
1714
|
-
active: true,
|
|
1715
|
-
scope: 'deep-interview-auto-approval',
|
|
1716
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
1717
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
1718
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
1719
|
-
},
|
|
1720
|
-
});
|
|
1721
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1722
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1723
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1724
|
-
'last-assistant-message': 'Would you like me to continue?',
|
|
1725
|
-
});
|
|
1726
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1727
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
1728
|
-
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'));
|
|
1729
|
-
});
|
|
1730
|
-
});
|
|
1731
|
-
it('acquires the deep-interview input lock when deep-interview activates', async () => {
|
|
1732
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1733
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1734
|
-
const stateDir = join(rcsDir, 'state');
|
|
1735
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1736
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1737
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1738
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1739
|
-
await mkdir(logsDir, { recursive: true });
|
|
1740
|
-
await mkdir(stateDir, { recursive: true });
|
|
1741
|
-
await mkdir(codexHome, { recursive: true });
|
|
1742
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1743
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1744
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1745
|
-
});
|
|
1746
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
1747
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1748
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1749
|
-
'input-messages': ['please run a deep interview first'],
|
|
1750
|
-
'last-assistant-message': 'Round 1 | Target: Goal Clarity',
|
|
1751
|
-
});
|
|
1752
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1753
|
-
const skillState = JSON.parse(await readFile(join(stateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1754
|
-
assert.equal(skillState.skill, 'deep-interview');
|
|
1755
|
-
assert.equal(skillState.input_lock?.active, true);
|
|
1756
|
-
assert.deepEqual(skillState.input_lock?.blocked_inputs, DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS);
|
|
1757
|
-
assert.match(skillState.input_lock?.message || '', /Deep interview is active/i);
|
|
1758
|
-
const modeState = JSON.parse(await readFile(join(sessionStateDir, 'deep-interview-state.json'), 'utf-8'));
|
|
1759
|
-
assert.equal(modeState.active, true);
|
|
1760
|
-
assert.equal(modeState.mode, 'deep-interview');
|
|
1761
|
-
assert.equal(modeState.current_phase, 'intent-first');
|
|
1762
|
-
assert.equal(modeState.input_lock?.active, true);
|
|
1763
|
-
});
|
|
1764
|
-
});
|
|
1765
|
-
it('releases deep-interview mode state on normal completion without waiting for later keyword input', async () => {
|
|
1766
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1767
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1768
|
-
const stateDir = join(rcsDir, 'state');
|
|
1769
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1770
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1771
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1772
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1773
|
-
await mkdir(logsDir, { recursive: true });
|
|
1774
|
-
await mkdir(stateDir, { recursive: true });
|
|
1775
|
-
await mkdir(codexHome, { recursive: true });
|
|
1776
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1777
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1778
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
1779
|
-
});
|
|
1780
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
1781
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1782
|
-
const activated = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1783
|
-
'input-messages': ['please run a deep interview first'],
|
|
1784
|
-
'last-assistant-message': 'Round 1 | Target: Goal Clarity',
|
|
1785
|
-
});
|
|
1786
|
-
assert.equal(activated.status, 0, `activation hook failed: ${activated.stderr || activated.stdout}`);
|
|
1787
|
-
const completed = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1788
|
-
'input-messages': ['continue'],
|
|
1789
|
-
'last-assistant-message': 'Interview completed. Final summary ready.',
|
|
1790
|
-
});
|
|
1791
|
-
assert.equal(completed.status, 0, `completion hook failed: ${completed.stderr || completed.stdout}`);
|
|
1792
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
1793
|
-
assert.equal(skillState.active, false);
|
|
1794
|
-
assert.equal(skillState.phase, 'completing');
|
|
1795
|
-
assert.equal(skillState.input_lock?.active, false);
|
|
1796
|
-
assert.equal(skillState.input_lock?.exit_reason, 'success');
|
|
1797
|
-
assert.ok(skillState.input_lock?.released_at);
|
|
1798
|
-
const modeState = JSON.parse(await readFile(join(sessionStateDir, 'deep-interview-state.json'), 'utf-8'));
|
|
1799
|
-
assert.equal(modeState.active, false);
|
|
1800
|
-
assert.equal(modeState.current_phase, 'completing');
|
|
1801
|
-
assert.ok(modeState.completed_at);
|
|
1802
|
-
assert.equal(modeState.input_lock?.active, false);
|
|
1803
|
-
assert.equal(modeState.input_lock?.exit_reason, 'success');
|
|
1804
|
-
assert.ok(modeState.input_lock?.released_at);
|
|
1805
|
-
});
|
|
1806
|
-
});
|
|
1807
|
-
for (const blockedResponse of ['yes', 'y', 'proceed', 'continue', 'ok', 'sure', 'go ahead']) {
|
|
1808
|
-
it(`blocks deep-interview auto-approval injection for "${blockedResponse}"`, async () => {
|
|
1809
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1810
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1811
|
-
const stateDir = join(rcsDir, 'state');
|
|
1812
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1813
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1814
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1815
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1816
|
-
await mkdir(logsDir, { recursive: true });
|
|
1817
|
-
await mkdir(stateDir, { recursive: true });
|
|
1818
|
-
await mkdir(codexHome, { recursive: true });
|
|
1819
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1820
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1821
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, response: blockedResponse },
|
|
1822
|
-
});
|
|
1823
|
-
await writeJson(join(stateDir, 'skill-active-state.json'), {
|
|
1824
|
-
version: 1,
|
|
1825
|
-
active: true,
|
|
1826
|
-
skill: 'deep-interview',
|
|
1827
|
-
keyword: 'deep interview',
|
|
1828
|
-
phase: 'planning',
|
|
1829
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
1830
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
1831
|
-
source: 'keyword-detector',
|
|
1832
|
-
input_lock: {
|
|
1833
|
-
active: true,
|
|
1834
|
-
scope: 'deep-interview-auto-approval',
|
|
1835
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
1836
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
1837
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
1838
|
-
},
|
|
1839
|
-
});
|
|
1840
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1841
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1842
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1843
|
-
'last-assistant-message': 'Keep going and finish the cleanup.',
|
|
1844
|
-
});
|
|
1845
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1846
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1847
|
-
assert.doesNotMatch(tmuxLog, /Deep interview is active; auto-approval shortcuts are blocked until the interview finishes\. \[RCS_TMUX_INJECT\]/);
|
|
1848
|
-
assert.equal(tmuxLog.includes(`send-keys -t %99 -l ${blockedResponse} [RCS_TMUX_INJECT]`), false);
|
|
1849
|
-
});
|
|
1850
|
-
});
|
|
1851
|
-
}
|
|
1852
|
-
it('suppresses deep-interview auto-approval without injecting tmux input', async () => {
|
|
1853
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1854
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1855
|
-
const stateDir = join(rcsDir, 'state');
|
|
1856
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1857
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1858
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1859
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1860
|
-
await mkdir(logsDir, { recursive: true });
|
|
1861
|
-
await mkdir(stateDir, { recursive: true });
|
|
1862
|
-
await mkdir(codexHome, { recursive: true });
|
|
1863
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1864
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1865
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, response: 'yes' },
|
|
1866
|
-
});
|
|
1867
|
-
await writeJson(join(stateDir, 'skill-active-state.json'), {
|
|
1868
|
-
version: 1,
|
|
1869
|
-
active: true,
|
|
1870
|
-
skill: 'deep-interview',
|
|
1871
|
-
keyword: 'deep interview',
|
|
1872
|
-
phase: 'planning',
|
|
1873
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
1874
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
1875
|
-
source: 'keyword-detector',
|
|
1876
|
-
input_lock: {
|
|
1877
|
-
active: true,
|
|
1878
|
-
scope: 'deep-interview-auto-approval',
|
|
1879
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
1880
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
1881
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
1882
|
-
},
|
|
1883
|
-
});
|
|
1884
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1885
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1886
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1887
|
-
'last-assistant-message': 'Keep going and finish the cleanup.',
|
|
1888
|
-
});
|
|
1889
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1890
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1891
|
-
assert.doesNotMatch(tmuxLog, /send-keys -t %99 -l Deep interview is active; auto-approval shortcuts are blocked until the interview finishes\. \[RCS_TMUX_INJECT\]/);
|
|
1892
|
-
});
|
|
1893
|
-
});
|
|
1894
|
-
it('blocks deep-interview auto-approval injection for actionable "Next I should ..." replies', async () => {
|
|
1895
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1896
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1897
|
-
const stateDir = join(rcsDir, 'state');
|
|
1898
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1899
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1900
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1901
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1902
|
-
await mkdir(logsDir, { recursive: true });
|
|
1903
|
-
await mkdir(stateDir, { recursive: true });
|
|
1904
|
-
await mkdir(codexHome, { recursive: true });
|
|
1905
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1906
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1907
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, response: NEXT_I_SHOULD_RESPONSE },
|
|
1908
|
-
});
|
|
1909
|
-
await writeJson(join(stateDir, 'skill-active-state.json'), {
|
|
1910
|
-
version: 1,
|
|
1911
|
-
active: true,
|
|
1912
|
-
skill: 'deep-interview',
|
|
1913
|
-
keyword: 'deep interview',
|
|
1914
|
-
phase: 'planning',
|
|
1915
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
1916
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
1917
|
-
source: 'keyword-detector',
|
|
1918
|
-
input_lock: {
|
|
1919
|
-
active: true,
|
|
1920
|
-
scope: 'deep-interview-auto-approval',
|
|
1921
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
1922
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
1923
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
1924
|
-
},
|
|
1925
|
-
});
|
|
1926
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1927
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1928
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1929
|
-
'last-assistant-message': 'Would you like me to continue?',
|
|
1930
|
-
});
|
|
1931
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1932
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1933
|
-
assert.doesNotMatch(tmuxLog, /Deep interview is active; auto-approval shortcuts are blocked until the interview finishes\. \[RCS_TMUX_INJECT\]/);
|
|
1934
|
-
assert.equal(tmuxLog.includes(`send-keys -t %99 -l ${NEXT_I_SHOULD_RESPONSE} [RCS_TMUX_INJECT]`), false);
|
|
1935
|
-
});
|
|
1936
|
-
});
|
|
1937
|
-
it('allows non-blocked custom deep-interview auto-nudge responses to continue', async () => {
|
|
1938
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1939
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1940
|
-
const stateDir = join(rcsDir, 'state');
|
|
1941
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1942
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1943
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1944
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1945
|
-
const capturePath = join(cwd, 'capture.txt');
|
|
1946
|
-
const customResponse = 'advance with the next interview question';
|
|
1947
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
1948
|
-
await mkdir(logsDir, { recursive: true });
|
|
1949
|
-
await mkdir(stateDir, { recursive: true });
|
|
1950
|
-
await mkdir(codexHome, { recursive: true });
|
|
1951
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1952
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
1953
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0, response: customResponse },
|
|
1954
|
-
});
|
|
1955
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
1956
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
1957
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
1958
|
-
version: 1,
|
|
1959
|
-
active: true,
|
|
1960
|
-
skill: 'deep-interview',
|
|
1961
|
-
keyword: 'deep interview',
|
|
1962
|
-
phase: 'executing',
|
|
1963
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
1964
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
1965
|
-
source: 'keyword-detector',
|
|
1966
|
-
input_lock: {
|
|
1967
|
-
active: true,
|
|
1968
|
-
scope: 'deep-interview-auto-approval',
|
|
1969
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
1970
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
1971
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
1972
|
-
},
|
|
1973
|
-
});
|
|
1974
|
-
await writeFile(capturePath, 'OpenAI Codex\n› ');
|
|
1975
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1976
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1977
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1978
|
-
'last-assistant-message': 'Keep going and finish the cleanup.',
|
|
1979
|
-
}, {
|
|
1980
|
-
RCS_TEST_CAPTURE_FILE: capturePath,
|
|
1981
|
-
});
|
|
1982
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1983
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1984
|
-
assert.match(tmuxLog, new RegExp(`send-keys -t %99 -l ${customResponse} \\[RCS_TMUX_INJECT\\]`), 'should allow a non-blocked continuation response during deep interview');
|
|
1985
|
-
});
|
|
1986
|
-
});
|
|
1987
|
-
it('keeps autoresearch active when assistant claims completion without validator evidence', async () => {
|
|
1988
|
-
await withTempWorkingDir(async (cwd) => {
|
|
1989
|
-
const rcsDir = join(cwd, '.rcs');
|
|
1990
|
-
const stateDir = join(rcsDir, 'state');
|
|
1991
|
-
const logsDir = join(rcsDir, 'logs');
|
|
1992
|
-
const codexHome = join(cwd, 'codex-home');
|
|
1993
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1994
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1995
|
-
await mkdir(logsDir, { recursive: true });
|
|
1996
|
-
await mkdir(stateDir, { recursive: true });
|
|
1997
|
-
await mkdir(codexHome, { recursive: true });
|
|
1998
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
1999
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2000
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2001
|
-
});
|
|
2002
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2003
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2004
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2005
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2006
|
-
active: true,
|
|
2007
|
-
skill: 'autoresearch',
|
|
2008
|
-
keyword: '$autoresearch',
|
|
2009
|
-
phase: 'executing',
|
|
2010
|
-
source: 'keyword-detector',
|
|
2011
|
-
session_id: 'sess-managed',
|
|
2012
|
-
});
|
|
2013
|
-
await writeJson(join(sessionStateDir, 'autoresearch-state.json'), {
|
|
2014
|
-
active: true,
|
|
2015
|
-
mode: 'autoresearch',
|
|
2016
|
-
current_phase: 'executing',
|
|
2017
|
-
session_id: 'sess-managed',
|
|
2018
|
-
validation_mode: 'mission-validator-script',
|
|
2019
|
-
mission_validator_command: 'node scripts/validate.js',
|
|
2020
|
-
completion_artifact_path: '.rcs/specs/autoresearch-demo/completion.json',
|
|
2021
|
-
});
|
|
2022
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
2023
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2024
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2025
|
-
'last-assistant-message': 'All tests pass. Completed with summary.',
|
|
2026
|
-
});
|
|
2027
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2028
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2029
|
-
assert.equal(skillState.active, true);
|
|
2030
|
-
assert.equal(skillState.phase, 'executing');
|
|
2031
|
-
assert.equal(skillState.autoresearch_completion_reason, 'missing_or_invalid_completion_artifact');
|
|
2032
|
-
});
|
|
2033
|
-
});
|
|
2034
|
-
it('completes autoresearch when validator artifact passes', async () => {
|
|
2035
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2036
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2037
|
-
const stateDir = join(rcsDir, 'state');
|
|
2038
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2039
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2040
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2041
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
2042
|
-
const specDir = join(cwd, '.rcs', 'specs', 'autoresearch-demo');
|
|
2043
|
-
await mkdir(logsDir, { recursive: true });
|
|
2044
|
-
await mkdir(stateDir, { recursive: true });
|
|
2045
|
-
await mkdir(codexHome, { recursive: true });
|
|
2046
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2047
|
-
await mkdir(specDir, { recursive: true });
|
|
2048
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2049
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2050
|
-
});
|
|
2051
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2052
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2053
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2054
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2055
|
-
active: true,
|
|
2056
|
-
skill: 'autoresearch',
|
|
2057
|
-
keyword: '$autoresearch',
|
|
2058
|
-
phase: 'reviewing',
|
|
2059
|
-
source: 'keyword-detector',
|
|
2060
|
-
session_id: 'sess-managed',
|
|
2061
|
-
});
|
|
2062
|
-
await writeJson(join(sessionStateDir, 'autoresearch-state.json'), {
|
|
2063
|
-
active: true,
|
|
2064
|
-
mode: 'autoresearch',
|
|
2065
|
-
current_phase: 'reviewing',
|
|
2066
|
-
session_id: 'sess-managed',
|
|
2067
|
-
validation_mode: 'mission-validator-script',
|
|
2068
|
-
mission_validator_command: 'node scripts/validate.js',
|
|
2069
|
-
completion_artifact_path: '.rcs/specs/autoresearch-demo/completion.json',
|
|
2070
|
-
});
|
|
2071
|
-
await writeJson(join(specDir, 'completion.json'), {
|
|
2072
|
-
status: 'passed',
|
|
2073
|
-
passed: true,
|
|
2074
|
-
});
|
|
2075
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
2076
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2077
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2078
|
-
'last-assistant-message': 'Completed with final summary after validator pass.',
|
|
2079
|
-
});
|
|
2080
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2081
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2082
|
-
assert.equal(skillState.active, false);
|
|
2083
|
-
assert.equal(skillState.phase, 'completing');
|
|
2084
|
-
assert.equal(skillState.autoresearch_completion_reason, 'validator_passed');
|
|
2085
|
-
});
|
|
2086
|
-
});
|
|
2087
|
-
it('releases the deep-interview input lock on success', async () => {
|
|
2088
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2089
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2090
|
-
const stateDir = join(rcsDir, 'state');
|
|
2091
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2092
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2093
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2094
|
-
await mkdir(logsDir, { recursive: true });
|
|
2095
|
-
await mkdir(stateDir, { recursive: true });
|
|
2096
|
-
await mkdir(codexHome, { recursive: true });
|
|
2097
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2098
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2099
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2100
|
-
});
|
|
2101
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2102
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2103
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2104
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2105
|
-
version: 1,
|
|
2106
|
-
active: true,
|
|
2107
|
-
skill: 'deep-interview',
|
|
2108
|
-
keyword: 'deep interview',
|
|
2109
|
-
phase: 'planning',
|
|
2110
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
2111
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
2112
|
-
source: 'keyword-detector',
|
|
2113
|
-
input_lock: {
|
|
2114
|
-
active: true,
|
|
2115
|
-
scope: 'deep-interview-auto-approval',
|
|
2116
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
2117
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
2118
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
2119
|
-
},
|
|
2120
|
-
});
|
|
2121
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
2122
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2123
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2124
|
-
'last-assistant-message': 'Interview completed. Final summary ready.',
|
|
2125
|
-
});
|
|
2126
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2127
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2128
|
-
assert.equal(skillState.active, false);
|
|
2129
|
-
assert.equal(skillState.phase, 'completing');
|
|
2130
|
-
assert.equal(skillState.input_lock?.active, false);
|
|
2131
|
-
assert.ok(skillState.input_lock?.released_at);
|
|
2132
|
-
assert.equal(skillState.input_lock?.exit_reason, 'success');
|
|
2133
|
-
});
|
|
2134
|
-
});
|
|
2135
|
-
it('does not release deep-interview state from generic progress prose', async () => {
|
|
2136
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2137
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2138
|
-
const stateDir = join(rcsDir, 'state');
|
|
2139
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2140
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2141
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2142
|
-
await mkdir(logsDir, { recursive: true });
|
|
2143
|
-
await mkdir(stateDir, { recursive: true });
|
|
2144
|
-
await mkdir(codexHome, { recursive: true });
|
|
2145
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2146
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2147
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2148
|
-
});
|
|
2149
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2150
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2151
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2152
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2153
|
-
version: 1,
|
|
2154
|
-
active: true,
|
|
2155
|
-
skill: 'deep-interview',
|
|
2156
|
-
keyword: 'deep interview',
|
|
2157
|
-
phase: 'executing',
|
|
2158
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
2159
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
2160
|
-
source: 'keyword-detector',
|
|
2161
|
-
input_lock: {
|
|
2162
|
-
active: true,
|
|
2163
|
-
scope: 'deep-interview-auto-approval',
|
|
2164
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
2165
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
2166
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
2167
|
-
},
|
|
2168
|
-
});
|
|
2169
|
-
await writeJson(join(sessionStateDir, 'deep-interview-state.json'), {
|
|
2170
|
-
active: true,
|
|
2171
|
-
mode: 'deep-interview',
|
|
2172
|
-
current_phase: 'intent-first',
|
|
2173
|
-
started_at: '2026-02-25T00:00:00.000Z',
|
|
2174
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
2175
|
-
});
|
|
2176
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
2177
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2178
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2179
|
-
'last-assistant-message': 'Summary so far: done with the first round of questions.',
|
|
2180
|
-
});
|
|
2181
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2182
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2183
|
-
assert.equal(skillState.active, true);
|
|
2184
|
-
assert.notEqual(skillState.phase, 'completing');
|
|
2185
|
-
assert.equal(skillState.input_lock?.active, true);
|
|
2186
|
-
assert.equal(skillState.input_lock?.released_at || '', '');
|
|
2187
|
-
assert.equal(skillState.input_lock?.exit_reason || '', '');
|
|
2188
|
-
const modeState = JSON.parse(await readFile(join(sessionStateDir, 'deep-interview-state.json'), 'utf-8'));
|
|
2189
|
-
assert.equal(modeState.active, true);
|
|
2190
|
-
assert.equal(modeState.current_phase, 'intent-first');
|
|
2191
|
-
assert.equal(modeState.completed_at || '', '');
|
|
2192
|
-
});
|
|
2193
|
-
});
|
|
2194
|
-
it('releases the deep-interview input lock on error', async () => {
|
|
2195
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2196
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2197
|
-
const stateDir = join(rcsDir, 'state');
|
|
2198
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2199
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2200
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2201
|
-
await mkdir(logsDir, { recursive: true });
|
|
2202
|
-
await mkdir(stateDir, { recursive: true });
|
|
2203
|
-
await mkdir(codexHome, { recursive: true });
|
|
2204
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2205
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2206
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2207
|
-
});
|
|
2208
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2209
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2210
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2211
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2212
|
-
version: 1,
|
|
2213
|
-
active: true,
|
|
2214
|
-
skill: 'deep-interview',
|
|
2215
|
-
keyword: 'deep interview',
|
|
2216
|
-
phase: 'planning',
|
|
2217
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
2218
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
2219
|
-
source: 'keyword-detector',
|
|
2220
|
-
input_lock: {
|
|
2221
|
-
active: true,
|
|
2222
|
-
scope: 'deep-interview-auto-approval',
|
|
2223
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
2224
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
2225
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
2226
|
-
},
|
|
2227
|
-
});
|
|
2228
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
2229
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2230
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2231
|
-
'last-assistant-message': 'Deep interview failed with error: unable to continue.',
|
|
2232
|
-
});
|
|
2233
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2234
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2235
|
-
assert.equal(skillState.active, false);
|
|
2236
|
-
assert.equal(skillState.phase, 'completing');
|
|
2237
|
-
assert.equal(skillState.input_lock?.active, false);
|
|
2238
|
-
assert.ok(skillState.input_lock?.released_at);
|
|
2239
|
-
assert.equal(skillState.input_lock?.exit_reason, 'error');
|
|
2240
|
-
});
|
|
2241
|
-
});
|
|
2242
|
-
it('releases the deep-interview input lock on abort', async () => {
|
|
2243
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2244
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2245
|
-
const stateDir = join(rcsDir, 'state');
|
|
2246
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2247
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2248
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2249
|
-
await mkdir(logsDir, { recursive: true });
|
|
2250
|
-
await mkdir(stateDir, { recursive: true });
|
|
2251
|
-
await mkdir(codexHome, { recursive: true });
|
|
2252
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2253
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2254
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2255
|
-
});
|
|
2256
|
-
await writeManagedSessionState(stateDir, cwd);
|
|
2257
|
-
const sessionStateDir = join(stateDir, 'sessions', 'sess-managed');
|
|
2258
|
-
await mkdir(sessionStateDir, { recursive: true });
|
|
2259
|
-
await writeJson(join(sessionStateDir, 'skill-active-state.json'), {
|
|
2260
|
-
version: 1,
|
|
2261
|
-
active: true,
|
|
2262
|
-
skill: 'deep-interview',
|
|
2263
|
-
keyword: 'deep interview',
|
|
2264
|
-
phase: 'planning',
|
|
2265
|
-
activated_at: '2026-02-25T00:00:00.000Z',
|
|
2266
|
-
updated_at: '2026-02-25T00:00:00.000Z',
|
|
2267
|
-
source: 'keyword-detector',
|
|
2268
|
-
input_lock: {
|
|
2269
|
-
active: true,
|
|
2270
|
-
scope: 'deep-interview-auto-approval',
|
|
2271
|
-
acquired_at: '2026-02-25T00:00:00.000Z',
|
|
2272
|
-
blocked_inputs: DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS,
|
|
2273
|
-
message: 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.',
|
|
2274
|
-
},
|
|
2275
|
-
});
|
|
2276
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
2277
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2278
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2279
|
-
'input-messages': ['abort'],
|
|
2280
|
-
'last-assistant-message': 'Stopping interview now.',
|
|
2281
|
-
});
|
|
2282
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2283
|
-
const skillState = JSON.parse(await readFile(join(sessionStateDir, 'skill-active-state.json'), 'utf-8'));
|
|
2284
|
-
assert.equal(skillState.skill, 'deep-interview');
|
|
2285
|
-
assert.equal(skillState.active, false);
|
|
2286
|
-
assert.equal(skillState.phase, 'completing');
|
|
2287
|
-
assert.equal(skillState.input_lock?.active, false);
|
|
2288
|
-
assert.ok(skillState.input_lock?.released_at);
|
|
2289
|
-
});
|
|
2290
|
-
});
|
|
2291
|
-
it('uses custom patterns from config', async () => {
|
|
2292
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2293
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2294
|
-
const stateDir = join(rcsDir, 'state');
|
|
2295
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2296
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2297
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2298
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
2299
|
-
await mkdir(logsDir, { recursive: true });
|
|
2300
|
-
await mkdir(stateDir, { recursive: true });
|
|
2301
|
-
await mkdir(codexHome, { recursive: true });
|
|
2302
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2303
|
-
// Custom patterns that replace defaults
|
|
2304
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2305
|
-
autoNudge: {
|
|
2306
|
-
enabled: true,
|
|
2307
|
-
delaySec: 0,
|
|
2308
|
-
stallMs: 0,
|
|
2309
|
-
patterns: ['awaiting approval'],
|
|
2310
|
-
},
|
|
2311
|
-
});
|
|
2312
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
2313
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2314
|
-
// Default pattern should NOT trigger with custom config
|
|
2315
|
-
const result1 = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2316
|
-
'last-assistant-message': 'Keep going and finish the focused cleanup.',
|
|
2317
|
-
});
|
|
2318
|
-
assert.equal(result1.status, 0);
|
|
2319
|
-
if (existsSync(tmuxLogPath)) {
|
|
2320
|
-
const log1 = await readFile(tmuxLogPath, 'utf-8');
|
|
2321
|
-
assert.doesNotMatch(log1, /send-keys -t %99 -l/, 'default pattern should not match with custom config');
|
|
2322
|
-
}
|
|
2323
|
-
// Clean tmux log for second run
|
|
2324
|
-
if (existsSync(tmuxLogPath)) {
|
|
2325
|
-
await writeFile(tmuxLogPath, '');
|
|
2326
|
-
}
|
|
2327
|
-
// Custom pattern should trigger
|
|
2328
|
-
const result2 = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2329
|
-
'last-assistant-message': 'Changes ready. Awaiting approval before applying.',
|
|
2330
|
-
});
|
|
2331
|
-
assert.equal(result2.status, 0);
|
|
2332
|
-
const log2 = await readFile(tmuxLogPath, 'utf-8');
|
|
2333
|
-
assert.match(log2, defaultAutoNudgePattern('%99'), 'custom pattern should trigger nudge with marker');
|
|
2334
|
-
});
|
|
2335
|
-
});
|
|
2336
|
-
it('defaults to enabled when no config file exists', async () => {
|
|
2337
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2338
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2339
|
-
const stateDir = join(rcsDir, 'state');
|
|
2340
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2341
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2342
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2343
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
2344
|
-
await mkdir(logsDir, { recursive: true });
|
|
2345
|
-
await mkdir(stateDir, { recursive: true });
|
|
2346
|
-
await mkdir(codexHome, { recursive: true });
|
|
2347
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2348
|
-
// No .rcs-config.json at all — should use defaults (enabled=true, stallMs=5000)
|
|
2349
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2350
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2351
|
-
});
|
|
2352
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
2353
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2354
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2355
|
-
'last-assistant-message': 'Keep going and fix the remaining issues.',
|
|
2356
|
-
});
|
|
2357
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2358
|
-
assert.ok(existsSync(tmuxLogPath), 'tmux should be called with defaults');
|
|
2359
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
2360
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'should nudge with default config and marker');
|
|
2361
|
-
});
|
|
2362
|
-
});
|
|
2363
|
-
it('can still resolve the managed session pane when TMUX_PANE is not set', async () => {
|
|
2364
|
-
await withTempWorkingDir(async (cwd) => {
|
|
2365
|
-
const rcsDir = join(cwd, '.rcs');
|
|
2366
|
-
const stateDir = join(rcsDir, 'state');
|
|
2367
|
-
const logsDir = join(rcsDir, 'logs');
|
|
2368
|
-
const codexHome = join(cwd, 'codex-home');
|
|
2369
|
-
const fakeBinDir = join(cwd, 'fake-bin');
|
|
2370
|
-
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
2371
|
-
const captureFile = join(cwd, 'capture-output.txt');
|
|
2372
|
-
await mkdir(logsDir, { recursive: true });
|
|
2373
|
-
await mkdir(stateDir, { recursive: true });
|
|
2374
|
-
await mkdir(codexHome, { recursive: true });
|
|
2375
|
-
await mkdir(fakeBinDir, { recursive: true });
|
|
2376
|
-
await writeJson(join(codexHome, '.rcs-config.json'), {
|
|
2377
|
-
autoNudge: { enabled: true, delaySec: 0, stallMs: 0 },
|
|
2378
|
-
});
|
|
2379
|
-
await writeFile(captureFile, 'Here are the results.\nKeep going and finish the implementation.\n› ');
|
|
2380
|
-
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
2381
|
-
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2382
|
-
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2383
|
-
'last-assistant-message': 'clean output with no stall',
|
|
2384
|
-
}, {
|
|
2385
|
-
TMUX_PANE: '', // No pane available
|
|
2386
|
-
TMUX: '',
|
|
2387
|
-
RCS_TEST_CAPTURE_FILE: captureFile,
|
|
2388
|
-
});
|
|
2389
|
-
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
2390
|
-
if (existsSync(tmuxLogPath)) {
|
|
2391
|
-
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
2392
|
-
assert.match(tmuxLog, defaultAutoNudgePattern('%99'), 'should fall back to the managed session pane when TMUX_PANE is absent');
|
|
2393
|
-
}
|
|
2394
|
-
});
|
|
2395
|
-
});
|
|
2396
|
-
});
|
|
2397
|
-
//# sourceMappingURL=notify-hook-auto-nudge.test.js.map
|