oh-my-codex 0.18.2 → 0.18.3
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/Cargo.toml +1 -1
- package/dist/agents/__tests__/definitions.test.js +9 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +1 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +10 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/auth/__tests__/config-sessions.test.d.ts +2 -0
- package/dist/auth/__tests__/config-sessions.test.d.ts.map +1 -0
- package/dist/auth/__tests__/config-sessions.test.js +48 -0
- package/dist/auth/__tests__/config-sessions.test.js.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts +2 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.js +33 -0
- package/dist/auth/__tests__/quota-rotation.test.js.map +1 -0
- package/dist/auth/__tests__/redact.test.d.ts +2 -0
- package/dist/auth/__tests__/redact.test.d.ts.map +1 -0
- package/dist/auth/__tests__/redact.test.js +20 -0
- package/dist/auth/__tests__/redact.test.js.map +1 -0
- package/dist/auth/__tests__/storage.test.d.ts +2 -0
- package/dist/auth/__tests__/storage.test.d.ts.map +1 -0
- package/dist/auth/__tests__/storage.test.js +108 -0
- package/dist/auth/__tests__/storage.test.js.map +1 -0
- package/dist/auth/config.d.ts +9 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +77 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/hotswap.d.ts +36 -0
- package/dist/auth/hotswap.d.ts.map +1 -0
- package/dist/auth/hotswap.js +159 -0
- package/dist/auth/hotswap.js.map +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/paths.d.ts +12 -0
- package/dist/auth/paths.d.ts.map +1 -0
- package/dist/auth/paths.js +78 -0
- package/dist/auth/paths.js.map +1 -0
- package/dist/auth/quota-detector.d.ts +10 -0
- package/dist/auth/quota-detector.d.ts.map +1 -0
- package/dist/auth/quota-detector.js +40 -0
- package/dist/auth/quota-detector.js.map +1 -0
- package/dist/auth/redact.d.ts +2 -0
- package/dist/auth/redact.d.ts.map +1 -0
- package/dist/auth/redact.js +26 -0
- package/dist/auth/redact.js.map +1 -0
- package/dist/auth/rotation.d.ts +9 -0
- package/dist/auth/rotation.d.ts.map +1 -0
- package/dist/auth/rotation.js +26 -0
- package/dist/auth/rotation.js.map +1 -0
- package/dist/auth/sessions.d.ts +15 -0
- package/dist/auth/sessions.d.ts.map +1 -0
- package/dist/auth/sessions.js +62 -0
- package/dist/auth/sessions.js.map +1 -0
- package/dist/auth/storage.d.ts +27 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +111 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/cli/__tests__/auth.test.d.ts +2 -0
- package/dist/cli/__tests__/auth.test.d.ts.map +1 -0
- package/dist/cli/__tests__/auth.test.js +168 -0
- package/dist/cli/__tests__/auth.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +51 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +20 -0
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +10 -0
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +30 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +47 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/auth.d.ts +4 -0
- package/dist/cli/auth.d.ts.map +1 -0
- package/dist/cli/auth.js +89 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +19 -7
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +12 -0
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +20 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +104 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +11 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/config/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/config/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/config/__tests__/deep-interview.test.js +239 -0
- package/dist/config/__tests__/deep-interview.test.js.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.js +123 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/deep-interview.d.ts +22 -0
- package/dist/config/deep-interview.d.ts.map +1 -0
- package/dist/config/deep-interview.js +151 -0
- package/dist/config/deep-interview.js.map +1 -0
- package/dist/config/generator.d.ts +5 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +106 -36
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +2 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/explore-routing.test.js +1 -0
- package/dist/hooks/__tests__/explore-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +301 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/deep-interview-config-instruction.d.ts +3 -0
- package/dist/hooks/deep-interview-config-instruction.d.ts.map +1 -0
- package/dist/hooks/deep-interview-config-instruction.js +47 -0
- package/dist/hooks/deep-interview-config-instruction.js.map +1 -0
- package/dist/hooks/explore-routing.d.ts.map +1 -1
- package/dist/hooks/explore-routing.js +1 -0
- package/dist/hooks/explore-routing.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +5 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +52 -8
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +4 -4
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +94 -9
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +103 -1
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +1 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +8 -0
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/tmux.d.ts +7 -0
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +46 -9
- package/dist/hud/tmux.js.map +1 -1
- package/dist/question/deep-interview.d.ts +2 -0
- package/dist/question/deep-interview.d.ts.map +1 -1
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +387 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +24 -2
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/state/__tests__/planning-gate.test.d.ts +2 -0
- package/dist/state/__tests__/planning-gate.test.d.ts.map +1 -0
- package/dist/state/__tests__/planning-gate.test.js +219 -0
- package/dist/state/__tests__/planning-gate.test.js.map +1 -0
- package/dist/state/workflow-transition.d.ts +23 -0
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +63 -0
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +86 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +7 -0
- package/dist/team/tmux-session.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +10 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +6 -2
- package/prompts/scholastic.md +11 -0
- package/skills/deep-interview/SKILL.md +10 -0
- package/skills/ralplan/SKILL.md +6 -2
- package/src/scripts/__tests__/codex-native-hook.test.ts +485 -0
- package/src/scripts/codex-native-hook.ts +23 -1
- package/templates/catalog-manifest.json +5 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { evaluatePreToolUseGate, isImplementationToolCall, isPlanningGateBypassActive, containsBypassPlanningGatePhrase, computeBypassExpiry, buildPlanningGateLogEvent, PLANNING_GATE_BYPASS_TTL_MS, } from '../workflow-transition.js';
|
|
4
|
+
import { DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS, DEEP_INTERVIEW_INPUT_LOCK_MESSAGE, } from '../../hooks/keyword-detector.js';
|
|
5
|
+
import { evaluateWorkflowTransition } from '../workflow-transition.js';
|
|
6
|
+
describe('planning gate: tool classification', () => {
|
|
7
|
+
it('classifies Edit, Write, NotebookEdit as implementation tools', () => {
|
|
8
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Edit' }), true);
|
|
9
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Write' }), true);
|
|
10
|
+
assert.equal(isImplementationToolCall({ tool_name: 'NotebookEdit' }), true);
|
|
11
|
+
});
|
|
12
|
+
it('classifies Bash with git push / gh pr create / gh pr merge as implementation tools', () => {
|
|
13
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'git push origin main' }), true);
|
|
14
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'gh pr create --title "fix"' }), true);
|
|
15
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'gh pr merge 42' }), true);
|
|
16
|
+
});
|
|
17
|
+
it('does not classify Read, Glob, Grep, or safe Bash as implementation tools', () => {
|
|
18
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Read' }), false);
|
|
19
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Glob' }), false);
|
|
20
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Grep' }), false);
|
|
21
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'git status' }), false);
|
|
22
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'npm test' }), false);
|
|
23
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash', tool_input: 'ls -la' }), false);
|
|
24
|
+
});
|
|
25
|
+
it('does not classify Bash without tool_input as implementation tool', () => {
|
|
26
|
+
assert.equal(isImplementationToolCall({ tool_name: 'Bash' }), false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('planning gate: downstream_authority=plan_then_execute + no ralplan consensus artifact', () => {
|
|
30
|
+
const gateState = {
|
|
31
|
+
downstream_authority: 'plan_then_execute',
|
|
32
|
+
};
|
|
33
|
+
it('denies Edit when no ralplan consensus artifact exists', () => {
|
|
34
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Edit' }, gateState, false);
|
|
35
|
+
assert.equal(decision.allowed, false);
|
|
36
|
+
assert.equal(decision.gate_fired, true);
|
|
37
|
+
assert.match(decision.reason, /plan_then_execute/);
|
|
38
|
+
assert.match(decision.reason, /Edit denied/);
|
|
39
|
+
});
|
|
40
|
+
it('denies Write when no ralplan consensus artifact exists', () => {
|
|
41
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Write' }, gateState, false);
|
|
42
|
+
assert.equal(decision.allowed, false);
|
|
43
|
+
assert.equal(decision.gate_fired, true);
|
|
44
|
+
assert.match(decision.reason, /Write denied/);
|
|
45
|
+
});
|
|
46
|
+
it('denies Bash(git push) when no ralplan consensus artifact exists', () => {
|
|
47
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Bash', tool_input: 'git push origin fix/branch' }, gateState, false);
|
|
48
|
+
assert.equal(decision.allowed, false);
|
|
49
|
+
assert.equal(decision.gate_fired, true);
|
|
50
|
+
assert.match(decision.reason, /Bash denied/);
|
|
51
|
+
});
|
|
52
|
+
it('denies Bash(gh pr create) when no ralplan consensus artifact exists', () => {
|
|
53
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Bash', tool_input: 'gh pr create --title "feature"' }, gateState, false);
|
|
54
|
+
assert.equal(decision.allowed, false);
|
|
55
|
+
assert.equal(decision.gate_fired, true);
|
|
56
|
+
});
|
|
57
|
+
it('allows Read when no ralplan consensus artifact exists', () => {
|
|
58
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Read' }, gateState, false);
|
|
59
|
+
assert.equal(decision.allowed, true);
|
|
60
|
+
assert.equal(decision.gate_fired, undefined);
|
|
61
|
+
});
|
|
62
|
+
it('allows Glob when no ralplan consensus artifact exists', () => {
|
|
63
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Glob' }, gateState, false);
|
|
64
|
+
assert.equal(decision.allowed, true);
|
|
65
|
+
});
|
|
66
|
+
it('allows Grep when no ralplan consensus artifact exists', () => {
|
|
67
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Grep' }, gateState, false);
|
|
68
|
+
assert.equal(decision.allowed, true);
|
|
69
|
+
});
|
|
70
|
+
it('allows safe Bash commands when no ralplan consensus artifact exists', () => {
|
|
71
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Bash', tool_input: 'npm test -- src/state/' }, gateState, false);
|
|
72
|
+
assert.equal(decision.allowed, true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('planning gate: downstream_authority=plan_then_execute + fresh ralplan consensus artifact', () => {
|
|
76
|
+
const gateState = {
|
|
77
|
+
downstream_authority: 'plan_then_execute',
|
|
78
|
+
};
|
|
79
|
+
it('allows Edit when ralplan consensus artifact is present', () => {
|
|
80
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Edit' }, gateState, true);
|
|
81
|
+
assert.equal(decision.allowed, true);
|
|
82
|
+
});
|
|
83
|
+
it('allows Write when ralplan consensus artifact is present', () => {
|
|
84
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Write' }, gateState, true);
|
|
85
|
+
assert.equal(decision.allowed, true);
|
|
86
|
+
});
|
|
87
|
+
it('allows Bash(git push) when ralplan consensus artifact is present', () => {
|
|
88
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Bash', tool_input: 'git push origin main' }, gateState, true);
|
|
89
|
+
assert.equal(decision.allowed, true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('planning gate: bypass planning gate phrase + TTL', () => {
|
|
93
|
+
it('detects bypass planning gate phrase case-insensitively', () => {
|
|
94
|
+
assert.equal(containsBypassPlanningGatePhrase('please bypass planning gate for now'), true);
|
|
95
|
+
assert.equal(containsBypassPlanningGatePhrase('BYPASS PLANNING GATE'), true);
|
|
96
|
+
assert.equal(containsBypassPlanningGatePhrase('Bypass Planning Gate please'), true);
|
|
97
|
+
assert.equal(containsBypassPlanningGatePhrase('just do it'), false);
|
|
98
|
+
});
|
|
99
|
+
it('allows implementation tools within TTL after bypass', () => {
|
|
100
|
+
const now = new Date('2026-05-24T10:00:00.000Z');
|
|
101
|
+
const gateState = {
|
|
102
|
+
downstream_authority: 'plan_then_execute',
|
|
103
|
+
bypass_planning_gate_until: new Date('2026-05-24T10:05:00.000Z').toISOString(),
|
|
104
|
+
};
|
|
105
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Edit' }, gateState, false, now);
|
|
106
|
+
assert.equal(decision.allowed, true);
|
|
107
|
+
assert.match(decision.reason, /bypass_planning_gate active/);
|
|
108
|
+
});
|
|
109
|
+
it('denies implementation tools after TTL expires', () => {
|
|
110
|
+
const now = new Date('2026-05-24T10:15:00.000Z');
|
|
111
|
+
const gateState = {
|
|
112
|
+
downstream_authority: 'plan_then_execute',
|
|
113
|
+
bypass_planning_gate_until: new Date('2026-05-24T10:05:00.000Z').toISOString(),
|
|
114
|
+
};
|
|
115
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Edit' }, gateState, false, now);
|
|
116
|
+
assert.equal(decision.allowed, false);
|
|
117
|
+
assert.equal(decision.gate_fired, true);
|
|
118
|
+
});
|
|
119
|
+
it('computeBypassExpiry produces a TTL of 10 minutes', () => {
|
|
120
|
+
const now = new Date('2026-05-24T10:00:00.000Z');
|
|
121
|
+
const expiry = computeBypassExpiry(now);
|
|
122
|
+
const expiryMs = Date.parse(expiry);
|
|
123
|
+
assert.equal(expiryMs - now.getTime(), PLANNING_GATE_BYPASS_TTL_MS);
|
|
124
|
+
assert.equal(PLANNING_GATE_BYPASS_TTL_MS, 10 * 60 * 1000);
|
|
125
|
+
});
|
|
126
|
+
it('isPlanningGateBypassActive returns false for empty or invalid bypass timestamps', () => {
|
|
127
|
+
assert.equal(isPlanningGateBypassActive({ downstream_authority: 'plan_then_execute' }), false);
|
|
128
|
+
assert.equal(isPlanningGateBypassActive({ downstream_authority: 'plan_then_execute', bypass_planning_gate_until: '' }), false);
|
|
129
|
+
assert.equal(isPlanningGateBypassActive({ downstream_authority: 'plan_then_execute', bypass_planning_gate_until: 'not-a-date' }), false);
|
|
130
|
+
});
|
|
131
|
+
it('denies again after mode transition clears bypass (simulated by removing bypass field)', () => {
|
|
132
|
+
const gateStateWithoutBypass = {
|
|
133
|
+
downstream_authority: 'plan_then_execute',
|
|
134
|
+
};
|
|
135
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Edit' }, gateStateWithoutBypass, false);
|
|
136
|
+
assert.equal(decision.allowed, false);
|
|
137
|
+
assert.equal(decision.gate_fired, true);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('planning gate: execute_now downstream authority', () => {
|
|
141
|
+
it('allows all tools when downstream_authority is execute_now', () => {
|
|
142
|
+
const gateState = {
|
|
143
|
+
downstream_authority: 'execute_now',
|
|
144
|
+
};
|
|
145
|
+
assert.equal(evaluatePreToolUseGate({ tool_name: 'Edit' }, gateState, false).allowed, true);
|
|
146
|
+
assert.equal(evaluatePreToolUseGate({ tool_name: 'Write' }, gateState, false).allowed, true);
|
|
147
|
+
assert.equal(evaluatePreToolUseGate({ tool_name: 'Bash', tool_input: 'git push' }, gateState, false).allowed, true);
|
|
148
|
+
});
|
|
149
|
+
it('allows all tools when no gate state exists', () => {
|
|
150
|
+
assert.equal(evaluatePreToolUseGate({ tool_name: 'Edit' }, null, false).allowed, true);
|
|
151
|
+
assert.equal(evaluatePreToolUseGate({ tool_name: 'Write' }, undefined, false).allowed, true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('planning gate: telemetry log event', () => {
|
|
155
|
+
it('builds a structured log event when gate fires', () => {
|
|
156
|
+
const gateState = {
|
|
157
|
+
downstream_authority: 'plan_then_execute',
|
|
158
|
+
};
|
|
159
|
+
const toolInput = { tool_name: 'Edit' };
|
|
160
|
+
const decision = evaluatePreToolUseGate(toolInput, gateState, false);
|
|
161
|
+
const logEvent = buildPlanningGateLogEvent(decision, toolInput, gateState);
|
|
162
|
+
assert.equal(logEvent.event, 'planning-gate-fired');
|
|
163
|
+
assert.equal(logEvent.tool_name, 'Edit');
|
|
164
|
+
assert.equal(logEvent.allowed, false);
|
|
165
|
+
assert.equal(logEvent.downstream_authority, 'plan_then_execute');
|
|
166
|
+
assert.equal(logEvent.bypass_active, false);
|
|
167
|
+
assert.ok(logEvent.timestamp);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('regression: explicit $ralplan top-level entry path is unaffected', () => {
|
|
171
|
+
it('allows ralplan activation from empty state', () => {
|
|
172
|
+
const decision = evaluateWorkflowTransition([], 'ralplan');
|
|
173
|
+
assert.equal(decision.allowed, true);
|
|
174
|
+
assert.equal(decision.kind, 'allow');
|
|
175
|
+
assert.deepEqual(decision.resultingModes, ['ralplan']);
|
|
176
|
+
});
|
|
177
|
+
it('allows deep-interview -> ralplan auto-complete transition', () => {
|
|
178
|
+
const decision = evaluateWorkflowTransition(['deep-interview'], 'ralplan');
|
|
179
|
+
assert.equal(decision.allowed, true);
|
|
180
|
+
assert.equal(decision.kind, 'auto-complete');
|
|
181
|
+
assert.deepEqual(decision.autoCompleteModes, ['deep-interview']);
|
|
182
|
+
assert.deepEqual(decision.resultingModes, ['ralplan']);
|
|
183
|
+
});
|
|
184
|
+
it('planning gate does not interfere with workflow transitions', () => {
|
|
185
|
+
const gateState = {
|
|
186
|
+
downstream_authority: 'plan_then_execute',
|
|
187
|
+
};
|
|
188
|
+
const readDecision = evaluatePreToolUseGate({ tool_name: 'Read' }, gateState, false);
|
|
189
|
+
assert.equal(readDecision.allowed, true);
|
|
190
|
+
const transitionDecision = evaluateWorkflowTransition([], 'ralplan');
|
|
191
|
+
assert.equal(transitionDecision.allowed, true);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('regression: existing DEEP_INTERVIEW_INPUT_LOCK_MESSAGE behavior unchanged', () => {
|
|
195
|
+
it('DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS contains the expected blocked inputs', () => {
|
|
196
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('yes'));
|
|
197
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('y'));
|
|
198
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('proceed'));
|
|
199
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('continue'));
|
|
200
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('ok'));
|
|
201
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('sure'));
|
|
202
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('go ahead'));
|
|
203
|
+
assert.ok(DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS.includes('next i should'));
|
|
204
|
+
});
|
|
205
|
+
it('DEEP_INTERVIEW_INPUT_LOCK_MESSAGE is the expected string', () => {
|
|
206
|
+
assert.equal(DEEP_INTERVIEW_INPUT_LOCK_MESSAGE, 'Deep interview is active; auto-approval shortcuts are blocked until the interview finishes.');
|
|
207
|
+
});
|
|
208
|
+
it('planning gate is orthogonal to input lock — gate evaluates tool calls, not user inputs', () => {
|
|
209
|
+
const gateState = {
|
|
210
|
+
downstream_authority: 'plan_then_execute',
|
|
211
|
+
};
|
|
212
|
+
for (const blockedInput of DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS) {
|
|
213
|
+
assert.equal(typeof blockedInput, 'string');
|
|
214
|
+
}
|
|
215
|
+
const decision = evaluatePreToolUseGate({ tool_name: 'Read' }, gateState, false);
|
|
216
|
+
assert.equal(decision.allowed, true);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
//# sourceMappingURL=planning-gate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planning-gate.test.js","sourceRoot":"","sources":["../../../src/state/__tests__/planning-gate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
export type DownstreamAuthority = 'plan_then_execute' | 'execute_now';
|
|
2
|
+
export interface PlanningGateState {
|
|
3
|
+
downstream_authority: DownstreamAuthority;
|
|
4
|
+
bypass_planning_gate_until?: string;
|
|
5
|
+
objective_id?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PreToolUseGateInput {
|
|
8
|
+
tool_name: string;
|
|
9
|
+
tool_input?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PreToolUseGateDecision {
|
|
12
|
+
allowed: boolean;
|
|
13
|
+
reason?: string;
|
|
14
|
+
gate_fired?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const PLANNING_GATE_BYPASS_TTL_MS: number;
|
|
17
|
+
export declare const BYPASS_PLANNING_GATE_PHRASE = "bypass planning gate";
|
|
18
|
+
export declare function isImplementationToolCall(input: PreToolUseGateInput): boolean;
|
|
19
|
+
export declare function isPlanningGateBypassActive(state: PlanningGateState, now?: Date): boolean;
|
|
20
|
+
export declare function evaluatePreToolUseGate(toolInput: PreToolUseGateInput, gateState: PlanningGateState | null | undefined, planningComplete: boolean, now?: Date): PreToolUseGateDecision;
|
|
21
|
+
export declare function computeBypassExpiry(now?: Date, ttlMs?: number): string;
|
|
22
|
+
export declare function containsBypassPlanningGatePhrase(text: string): boolean;
|
|
23
|
+
export declare function buildPlanningGateLogEvent(decision: PreToolUseGateDecision, toolInput: PreToolUseGateInput, gateState: PlanningGateState | null | undefined): Record<string, unknown>;
|
|
1
24
|
export declare const TRACKED_WORKFLOW_MODES: readonly ["autopilot", "autoresearch", "team", "ultragoal", "ralph", "ultrawork", "ultraqa", "ralplan", "deep-interview"];
|
|
2
25
|
export type TrackedWorkflowMode = (typeof TRACKED_WORKFLOW_MODES)[number];
|
|
3
26
|
export type WorkflowTransitionAction = 'activate' | 'start' | 'write';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-transition.d.ts","sourceRoot":"","sources":["../../src/state/workflow-transition.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,2HAUzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1E,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AACtE,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,MAAM,CAAC;AA2EpF,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,mBAAmB,EAC/B,aAAa,EAAE,mBAAmB,GACjC,MAAM,CAER;AASD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,EAAE,mBAAmB,CAAC;IACnC,cAAc,EAAE,mBAAmB,EAAE,CAAC;IACtC,iBAAiB,EAAE,mBAAmB,EAAE,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,mBAAmB,CAE/E;AAED,wBAAgB,0BAA0B,CACxC,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,EACpC,aAAa,EAAE,mBAAmB,GACjC,0BAA0B,CA4D5B;AAED,wBAAgB,4BAA4B,CAC1C,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,EACpC,aAAa,EAAE,mBAAmB,EAClC,MAAM,GAAE,wBAAqC,GAC5C,MAAM,CAkBR;AAED,wBAAgB,+BAA+B,CAC7C,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,EACpC,aAAa,EAAE,mBAAmB,EAClC,MAAM,GAAE,wBAAqC,GAC5C,IAAI,CAIN;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAsBhC;AAED,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,OAAO,EACvB,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,YAAY,EAAE,MAAM,GACnB,MAAM,CAMR"}
|
|
1
|
+
{"version":3,"file":"workflow-transition.d.ts","sourceRoot":"","sources":["../../src/state/workflow-transition.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
import { existsSync } from 'fs';
|
|
2
2
|
import { readFile } from 'fs/promises';
|
|
3
3
|
import { getAuthoritativeActiveStatePaths } from '../mcp/state-paths.js';
|
|
4
|
+
const IMPLEMENTATION_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit']);
|
|
5
|
+
const DENIED_BASH_PATTERNS = [
|
|
6
|
+
/\bgit\s+push\b/,
|
|
7
|
+
/\bgh\s+pr\s+create\b/,
|
|
8
|
+
/\bgh\s+pr\s+merge\b/,
|
|
9
|
+
];
|
|
10
|
+
export const PLANNING_GATE_BYPASS_TTL_MS = 10 * 60 * 1000;
|
|
11
|
+
export const BYPASS_PLANNING_GATE_PHRASE = 'bypass planning gate';
|
|
12
|
+
export function isImplementationToolCall(input) {
|
|
13
|
+
if (IMPLEMENTATION_TOOLS.has(input.tool_name))
|
|
14
|
+
return true;
|
|
15
|
+
if (input.tool_name === 'Bash' && typeof input.tool_input === 'string') {
|
|
16
|
+
return DENIED_BASH_PATTERNS.some((pattern) => pattern.test(input.tool_input));
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
export function isPlanningGateBypassActive(state, now = new Date()) {
|
|
21
|
+
const raw = typeof state.bypass_planning_gate_until === 'string'
|
|
22
|
+
? state.bypass_planning_gate_until.trim()
|
|
23
|
+
: '';
|
|
24
|
+
if (!raw)
|
|
25
|
+
return false;
|
|
26
|
+
const bypassMs = Date.parse(raw);
|
|
27
|
+
if (!Number.isFinite(bypassMs))
|
|
28
|
+
return false;
|
|
29
|
+
return now.getTime() < bypassMs;
|
|
30
|
+
}
|
|
31
|
+
export function evaluatePreToolUseGate(toolInput, gateState, planningComplete, now = new Date()) {
|
|
32
|
+
if (!gateState || gateState.downstream_authority !== 'plan_then_execute') {
|
|
33
|
+
return { allowed: true };
|
|
34
|
+
}
|
|
35
|
+
if (planningComplete) {
|
|
36
|
+
return { allowed: true };
|
|
37
|
+
}
|
|
38
|
+
if (!isImplementationToolCall(toolInput)) {
|
|
39
|
+
return { allowed: true };
|
|
40
|
+
}
|
|
41
|
+
if (isPlanningGateBypassActive(gateState, now)) {
|
|
42
|
+
return { allowed: true, reason: 'bypass_planning_gate active' };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
allowed: false,
|
|
46
|
+
gate_fired: true,
|
|
47
|
+
reason: `deep-interview downstream_authority is plan_then_execute but no ralplan consensus artifact exists; ${toolInput.tool_name} denied`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function computeBypassExpiry(now = new Date(), ttlMs = PLANNING_GATE_BYPASS_TTL_MS) {
|
|
51
|
+
return new Date(now.getTime() + ttlMs).toISOString();
|
|
52
|
+
}
|
|
53
|
+
export function containsBypassPlanningGatePhrase(text) {
|
|
54
|
+
return text.toLowerCase().includes(BYPASS_PLANNING_GATE_PHRASE);
|
|
55
|
+
}
|
|
56
|
+
export function buildPlanningGateLogEvent(decision, toolInput, gateState) {
|
|
57
|
+
return {
|
|
58
|
+
event: 'planning-gate-fired',
|
|
59
|
+
tool_name: toolInput.tool_name,
|
|
60
|
+
allowed: decision.allowed,
|
|
61
|
+
reason: decision.reason,
|
|
62
|
+
downstream_authority: gateState?.downstream_authority,
|
|
63
|
+
bypass_active: gateState ? isPlanningGateBypassActive(gateState) : false,
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
4
67
|
export const TRACKED_WORKFLOW_MODES = [
|
|
5
68
|
'autopilot',
|
|
6
69
|
'autoresearch',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-transition.js","sourceRoot":"","sources":["../../src/state/workflow-transition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-transition.js","sourceRoot":"","sources":["../../src/state/workflow-transition.ts"],"names":[],"mappings":"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"}
|
|
@@ -2869,6 +2869,92 @@ esac
|
|
|
2869
2869
|
});
|
|
2870
2870
|
});
|
|
2871
2871
|
describe('createTeamSession tmux instance tagging', () => {
|
|
2872
|
+
it('redraws the leader pane after team layout changes so wrapped diff hunks repaint with gutters', async () => {
|
|
2873
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-team-redraw-leader-'));
|
|
2874
|
+
const prevTmux = process.env.TMUX;
|
|
2875
|
+
const prevTmuxPane = process.env.TMUX_PANE;
|
|
2876
|
+
const prevWorkerCli = process.env.OMX_TEAM_WORKER_CLI;
|
|
2877
|
+
try {
|
|
2878
|
+
await withMockTmuxFixture('omx-tmux-redraw-leader-', (logPath) => `#!/bin/sh
|
|
2879
|
+
set -eu
|
|
2880
|
+
printf '%s\n' "$*" >> "${logPath}"
|
|
2881
|
+
case "\${1:-}" in
|
|
2882
|
+
-V)
|
|
2883
|
+
echo "tmux 3.4"
|
|
2884
|
+
exit 0
|
|
2885
|
+
;;
|
|
2886
|
+
display-message)
|
|
2887
|
+
case "$*" in
|
|
2888
|
+
*"#{window_width}"*)
|
|
2889
|
+
echo "120"
|
|
2890
|
+
;;
|
|
2891
|
+
*)
|
|
2892
|
+
echo "leader:0 %1"
|
|
2893
|
+
;;
|
|
2894
|
+
esac
|
|
2895
|
+
exit 0
|
|
2896
|
+
;;
|
|
2897
|
+
list-panes)
|
|
2898
|
+
case "$*" in
|
|
2899
|
+
*"pane_current_command"*)
|
|
2900
|
+
printf "%%1\\tnode\\t'codex'\\n"
|
|
2901
|
+
;;
|
|
2902
|
+
*)
|
|
2903
|
+
printf "%%1\\n"
|
|
2904
|
+
;;
|
|
2905
|
+
esac
|
|
2906
|
+
exit 0
|
|
2907
|
+
;;
|
|
2908
|
+
split-window)
|
|
2909
|
+
case "$*" in
|
|
2910
|
+
*" -h "*)
|
|
2911
|
+
echo "%2"
|
|
2912
|
+
;;
|
|
2913
|
+
*)
|
|
2914
|
+
echo "%3"
|
|
2915
|
+
;;
|
|
2916
|
+
esac
|
|
2917
|
+
exit 0
|
|
2918
|
+
;;
|
|
2919
|
+
set-option|resize-pane|select-layout|set-window-option|select-pane|set-hook|run-shell|send-keys)
|
|
2920
|
+
exit 0
|
|
2921
|
+
;;
|
|
2922
|
+
*)
|
|
2923
|
+
exit 0
|
|
2924
|
+
;;
|
|
2925
|
+
esac
|
|
2926
|
+
`, async ({ logPath }) => {
|
|
2927
|
+
const fakeBinDir = join(logPath, '..');
|
|
2928
|
+
const geminiPath = join(fakeBinDir, 'gemini');
|
|
2929
|
+
await writeFile(geminiPath, '#!/bin/sh\nexit 0\n');
|
|
2930
|
+
await chmod(geminiPath, 0o755);
|
|
2931
|
+
process.env.TMUX = 'leader-session,stub,0';
|
|
2932
|
+
process.env.TMUX_PANE = '%1';
|
|
2933
|
+
process.env.OMX_TEAM_WORKER_CLI = 'gemini';
|
|
2934
|
+
createTeamSession('Diff Gutter Redraw', 1, cwd);
|
|
2935
|
+
const tmuxLog = await readFile(logPath, 'utf-8');
|
|
2936
|
+
assert.match(tmuxLog, /select-layout -t leader:0 main-vertical/);
|
|
2937
|
+
assert.match(tmuxLog, /set-window-option -t leader:0 main-pane-width 60/);
|
|
2938
|
+
assert.match(tmuxLog, /split-window -v -f -l 3 -t leader:0 -d -P -F #\{pane_id\}/);
|
|
2939
|
+
assert.match(tmuxLog, /send-keys -t %1 C-l/, 'leader Codex pane must repaint after team splits/resizes so tmux does not auto-wrap diff continuation rows without the line-number gutter');
|
|
2940
|
+
});
|
|
2941
|
+
}
|
|
2942
|
+
finally {
|
|
2943
|
+
if (typeof prevTmux === 'string')
|
|
2944
|
+
process.env.TMUX = prevTmux;
|
|
2945
|
+
else
|
|
2946
|
+
delete process.env.TMUX;
|
|
2947
|
+
if (typeof prevTmuxPane === 'string')
|
|
2948
|
+
process.env.TMUX_PANE = prevTmuxPane;
|
|
2949
|
+
else
|
|
2950
|
+
delete process.env.TMUX_PANE;
|
|
2951
|
+
if (typeof prevWorkerCli === 'string')
|
|
2952
|
+
process.env.OMX_TEAM_WORKER_CLI = prevWorkerCli;
|
|
2953
|
+
else
|
|
2954
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
2955
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2956
|
+
}
|
|
2957
|
+
});
|
|
2872
2958
|
it('tags leader, worker, and HUD panes with pane-scoped instance ownership', async () => {
|
|
2873
2959
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-team-pane-tags-'));
|
|
2874
2960
|
const prevTmux = process.env.TMUX;
|