ultracode-for-codex 0.3.1 → 0.3.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/README.md CHANGED
@@ -1,23 +1,58 @@
1
1
  # Ultracode for Codex
2
2
 
3
- Ultracode for Codex ships two Codex skill commands plus a local npm CLI runtime.
4
- `$ultracode-for-codex` is the default high-visibility mode: the Codex main
5
- context plans adaptive phases, spawns focused parallel subagents, synthesizes
6
- their results, and reports progress directly in the chat.
7
- `$ultracode-for-codex-cli` is the explicit runtime path for package validation,
8
- background jobs, attached CLI runs, release checks, and reproducible local
9
- workflow artifacts.
3
+ Dynamic workflows redesigned for Codex, with parallel subagents, visible
4
+ progress, and an optional local CLI runtime.
10
5
 
11
- ## Quick Start
6
+ The default experience is Codex-native: you ask for `$ultracode-for-codex`, and
7
+ the main Codex chat becomes the orchestrator. It plans the next useful phase,
8
+ runs independent subagents in parallel when that helps, summarizes their
9
+ findings, and shows compact progress snapshots directly in the conversation.
12
10
 
13
- Install from npm:
11
+ A local CLI runtime is included for users who want background jobs, reproducible
12
+ workflow runs, package checks, or attached terminal execution.
13
+
14
+ ## Why Use It
15
+
16
+ - Get multi-angle reviews instead of a single linear pass.
17
+ - Run implementation and verification work phase by phase.
18
+ - See what agents are doing, what finished, and what still needs attention.
19
+ - Keep long CLI workflows running in the OS background when desired.
20
+ - Package the same workflow behavior for repeatable local use.
21
+
22
+ ## Install
23
+
24
+ For one project:
14
25
 
15
26
  ```bash
16
27
  npm install --save-dev ultracode-for-codex
28
+ ```
29
+
30
+ For global use:
31
+
32
+ ```bash
33
+ npm install -g ultracode-for-codex
34
+ ```
35
+
36
+ If you installed it globally, check the CLI directly:
37
+
38
+ ```bash
39
+ ultracode-for-codex --version
40
+ ultracode-for-codex --llm-guide
41
+ ```
42
+
43
+ If you installed it as a project dependency, check it with `npm exec --`:
44
+
45
+ ```bash
46
+ npm exec -- ultracode-for-codex --version
17
47
  npm exec -- ultracode-for-codex --llm-guide
18
48
  ```
19
49
 
20
- Install the Codex skill commands from the package:
50
+ ## Install The Codex Skills
51
+
52
+ After installing the npm package, copy the included skill commands into your
53
+ Codex skills folder.
54
+
55
+ From a project install:
21
56
 
22
57
  ```bash
23
58
  mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills"
@@ -27,235 +62,171 @@ cp -R ./node_modules/ultracode-for-codex/skills/ultracode-for-codex-cli \
27
62
  "${CODEX_HOME:-$HOME/.codex}/skills/"
28
63
  ```
29
64
 
30
- Build and verify a local installable tarball from a source checkout:
65
+ From a global install:
31
66
 
32
67
  ```bash
33
- npm install
34
- npm run pack:ultracode-for-codex
68
+ mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills"
69
+ GLOBAL_NODE_MODULES="$(npm root -g)"
70
+ cp -R "$GLOBAL_NODE_MODULES/ultracode-for-codex/skills/ultracode-for-codex" \
71
+ "${CODEX_HOME:-$HOME/.codex}/skills/"
72
+ cp -R "$GLOBAL_NODE_MODULES/ultracode-for-codex/skills/ultracode-for-codex-cli" \
73
+ "${CODEX_HOME:-$HOME/.codex}/skills/"
35
74
  ```
36
75
 
37
- Install the tarball from a target project:
76
+ Restart Codex or start a new Codex session if the skills do not appear
77
+ immediately.
38
78
 
39
- ```bash
40
- npm install --save-dev /path/to/ultracode-for-codex-<version>.tgz
79
+ ## Use In Codex
80
+
81
+ Use the default skill for normal work:
82
+
83
+ ```text
84
+ $ultracode-for-codex Review this change for correctness and security risks.
41
85
  ```
42
86
 
43
- Run through the CLI runtime when that path is explicitly wanted:
87
+ Good tasks for the default skill:
44
88
 
45
- ```bash
46
- npm exec -- ultracode-for-codex run \
47
- --accept-llm-guide=v1 \
48
- --cwd /path/to/target-repo \
49
- --script-file .codex/workflows/review.js \
50
- --args '{"prompt":"review the current change"}'
89
+ - code review;
90
+ - implementation planning;
91
+ - multi-step verification;
92
+ - architecture or design critique;
93
+ - release readiness checks;
94
+ - work that benefits from parallel perspectives.
95
+
96
+ The default skill shows a phase plan before work starts and keeps a cumulative
97
+ progress snapshot as agents finish.
98
+
99
+ Example:
100
+
101
+ ```text
102
+ Phase Review
103
+
104
+ + Runtime correctness done no material issue
105
+ > Security boundary running checking local state handling
106
+ - Package contract queued verify installed files
107
+
108
+ Agents 1 completed | 1 running | 1 queued
109
+ Next: synthesize material findings
51
110
  ```
52
111
 
53
- By default this prints a background launch record to stdout. The record contains
54
- `jobId`, `pid`, `resultPath`, `progressPath`, `metadataPath`, and `pidPath`.
55
- Use the job id to inspect or control the background run:
112
+ ## Use The CLI Runtime
113
+
114
+ Use `$ultracode-for-codex-cli` or the `ultracode-for-codex` binary when you
115
+ explicitly want a local command-owned workflow run.
116
+
117
+ Run a built-in task workflow:
56
118
 
57
119
  ```bash
58
- npm exec -- ultracode-for-codex status <jobId> --cwd /path/to/target-repo
59
- npm exec -- ultracode-for-codex wait <jobId> --cwd /path/to/target-repo
60
- npm exec -- ultracode-for-codex logs <jobId> --cwd /path/to/target-repo --tail 40
61
- npm exec -- ultracode-for-codex result <jobId> --cwd /path/to/target-repo
62
- npm exec -- ultracode-for-codex cancel <jobId> --cwd /path/to/target-repo
63
- npm exec -- ultracode-for-codex jobs --cwd /path/to/target-repo
64
- npm exec -- ultracode-for-codex archive <jobId> --cwd /path/to/target-repo
120
+ npm exec -- ultracode-for-codex run \
121
+ --accept-llm-guide=v1 \
122
+ --cwd /path/to/project \
123
+ --name task \
124
+ --args '{"prompt":"review correctness risks and propose fixes"}'
65
125
  ```
66
126
 
67
- Run attached to the current terminal:
127
+ Run a code review:
68
128
 
69
129
  ```bash
70
130
  npm exec -- ultracode-for-codex run \
71
131
  --accept-llm-guide=v1 \
72
- --execution attached \
73
- --cwd /path/to/target-repo \
74
- --script-file .codex/workflows/review.js \
132
+ --cwd /path/to/project \
133
+ --name code-review \
75
134
  --args '{"prompt":"review the current change"}'
76
135
  ```
77
136
 
78
- Named workflows are resolved from `.codex/workflows`, user workflow folders,
79
- plugin workflow folders, and built-ins:
137
+ The built-in `code-review` workflow collects bounded repository evidence,
138
+ chooses review lenses, runs finder agents in parallel, verifies each candidate,
139
+ and returns JSON with `findings`, `provenance`, `synthesis`, and `stats`.
140
+ Use `{"level":"high"}` to skip the final sweep, or omit it for the default
141
+ `xhigh` review.
142
+
143
+ CLI runs use OS background execution by default. The command prints a launch
144
+ record with a `jobId`, then you can inspect or control the job:
145
+
146
+ ```bash
147
+ npm exec -- ultracode-for-codex status <jobId> --cwd /path/to/project
148
+ npm exec -- ultracode-for-codex logs <jobId> --cwd /path/to/project --tail 40
149
+ npm exec -- ultracode-for-codex result <jobId> --cwd /path/to/project
150
+ npm exec -- ultracode-for-codex cancel <jobId> --cwd /path/to/project
151
+ ```
152
+
153
+ Use attached execution only when the terminal should stay connected until the
154
+ workflow finishes:
80
155
 
81
156
  ```bash
82
157
  npm exec -- ultracode-for-codex run \
83
158
  --accept-llm-guide=v1 \
84
- --cwd /path/to/target-repo \
159
+ --execution attached \
160
+ --cwd /path/to/project \
85
161
  --name task \
86
- --args '{"prompt":"review correctness risks and propose fixes"}'
162
+ --args '{"prompt":"check the release plan"}'
87
163
  ```
88
164
 
89
- The CLI built-in `task` and `code-review` workflows use an LLM planner first,
90
- then run work phase by phase. Within each phase, multiple focused Codex
91
- subagents run in parallel by default, followed by phase and final synthesis. The
92
- planner may choose a single-agent path only when parallel execution would add
93
- risk or waste. Planner guidance includes dynamic workflow patterns such as
94
- classify-and-act, fan-out-and-synthesize, adversarial verification,
95
- generate-and-filter, tournament, and loop-until-done, so different work types
96
- can use different phase shapes.
97
-
98
- ## Settings
99
-
100
- Package defaults live in `settings.json`:
101
-
102
- ```json
103
- {
104
- "workflow": {
105
- "executionMode": "background",
106
- "progress": "jsonl",
107
- "permission": "ask",
108
- "retryLimit": 0,
109
- "timeoutMs": 0,
110
- "background": {
111
- "runDir": ".ultracode-for-codex/background/{jobId}",
112
- "resultFile": "result.json",
113
- "progressFile": "progress.jsonl",
114
- "metadataFile": "metadata.json",
115
- "pidFile": "pid"
116
- }
117
- }
118
- }
119
- ```
165
+ ## What Gets Installed
120
166
 
121
- Use `--execution attached`, `--progress`, `--permission`, `--retry-limit`, and
122
- `--timeout-ms` to override settings for one run.
123
- The package default workflow timeout is `0`, meaning the workflow waits until it
124
- completes, is cancelled, or the Codex app-server exits. Set `--timeout-ms` to a
125
- positive value to opt into a deadline for one run.
126
- Use the default background execution for long Codex-launched work so Codex can
127
- continue other tasks and inspect the job later with `status`, `logs`, or
128
- `result`. Use
129
- `--execution attached` only when the caller must block until the final result.
130
-
131
- ## CLI Controls
132
-
133
- - Use `--version` or `-v` to print the installed package version.
134
- - Use `status`, `wait`, `logs`, `result`, and `cancel` with a background
135
- `jobId` or `metadata.json` path to inspect, wait for, read, or cancel OS
136
- background runs.
137
- - Use `jobs` or `list` to enumerate local background runs.
138
- - Use `archive` or `export` to write a sensitive local JSON bundle for one run
139
- without deleting runtime state.
140
- - Use `wait --result`, `cancel --wait`, `logs --event <event>`, and `--plain`
141
- for shorter foreground checks.
142
- - Progress is printed to stderr as JSONL by default.
143
- - The final workflow result is printed as JSON to stdout.
144
- - JSONL records include `kind`, `version`, `event`, `status`, and `summary`;
145
- agent records also include stable agent identity and label fields.
146
- - Built-in `task` and `code-review` emit `workflow.plan.ready` as a planning
147
- snapshot, not a promise that every later phase is already known.
148
- - `workflow.phase.planned` is emitted immediately before each phase starts and
149
- carries that phase's current planned agent role labels. Each
150
- `workflow.phase.started` record repeats the same role labels when the phase
151
- begins.
152
- - Each `workflow.agent.completed` record includes phase progress, total known
153
- agent progress, and elapsed time.
154
- - After a completed run, `workflow.summary.ready` reports each phase with its
155
- planned agent count and angle/focus list, then `workflow.review.recommended`
156
- asks the current session LLM to critically re-check the final result before
157
- acting on it.
158
- - Press `Ctrl-C` once to cancel the active workflow.
159
- - Use `--retry-limit <n>` to retry failed workflows inside the same process.
160
- - `--timeout-ms 0` waits for completion, cancellation, or app-server exit.
161
- Positive values opt into a workflow deadline and per-agent silence budget;
162
- that budget is not divided by the retry budget.
163
- - Use `--permission ask|allow|deny` for project/user/plugin/scriptPath workflow
164
- permission reviews.
165
- - Use `--progress plain` for human-readable log lines.
166
- - Use `--execution background` for OS background runs and `--execution attached`
167
- only when the caller should stay connected until completion.
168
-
169
- ## Codex Skill Commands
170
-
171
- The npm package includes two Codex skill command folders:
172
-
173
- - `skills/ultracode-for-codex`: default Codex-native orchestration. The main
174
- context plans adaptive phases, spawns parallel subagents, synthesizes each
175
- phase, reports completion progress, and recommends a final critical re-check.
176
- Live progress uses test-runner-style visual snapshots; completion reporting
177
- uses a diffstat-style impact summary plus a plan-style result summary.
178
- - `skills/ultracode-for-codex-cli`: explicit CLI runtime operations, including
179
- background jobs, attached runs, packaging, release checks, runtime-boundary
180
- validation, and installed E2E tests.
181
-
182
- ## Runtime Boundaries
183
-
184
- - The only production backend is Codex app-server over stdio.
185
- - Direct provider credentials are stripped from the Codex child process
186
- environment.
187
- - Codex subagents run against the requested workflow cwd and receive bounded
188
- read-only workspace tools for text file reads and directory listings.
189
- - CLI built-in `task` and `code-review` inject deterministic workspace context into
190
- planner-selected phase-wise parallel subagents, then synthesize each phase and
191
- the final result.
192
- - Workflow execution is local and command-owned; settings default to OS
193
- background execution so long runs can keep waiting while Codex does other
194
- work.
195
- - `.ultracode-for-codex` workflow state is sensitive local data.
196
- - `journalPath`, `journal.jsonl`, and journal contents stay out of CLI output.
197
- Local runtime state may still contain runtime-owned
198
- `transcriptDir`, `scriptPath`, and result files.
199
- - `resumeFromRunId` remains runtime-internal and same-session; users retry the
200
- active run or rerun the workflow command.
201
- - `agent(..., { isolation: "worktree" })` runs the agent in a detached git
202
- worktree and preserves the worktree for review, including clean worktrees.
203
-
204
- ## Development
167
+ The package includes:
205
168
 
206
- ```bash
207
- npm install
208
- npm test
209
- npm run pack:ultracode-for-codex
210
- npm run test:e2e:ultracode-for-codex
211
- npm run test:all
212
- ```
169
+ - `ultracode-for-codex`: the local CLI binary;
170
+ - `skills/ultracode-for-codex`: the recommended Codex-native skill;
171
+ - `skills/ultracode-for-codex-cli`: the explicit CLI/runtime skill;
172
+ - `settings.json`: default CLI runtime settings;
173
+ - `ULTRACODE_INSTALL.md`: detailed install and operating guide for agents.
213
174
 
214
- ## Publishing
175
+ ## Local State
215
176
 
216
- The npm package name is `ultracode-for-codex`. Public publish metadata lives in
217
- `package.json`, and `prepublishOnly` runs the full verification suite before
218
- `npm publish`.
177
+ CLI background runs write local workflow state under `.ultracode-for-codex/` in
178
+ the target project. Treat that folder as local runtime data. It may contain
179
+ progress, metadata, transcripts, and results for the run.
219
180
 
220
- Check the package before publishing:
181
+ Add it to `.gitignore` if your project does not already ignore it:
182
+
183
+ ```gitignore
184
+ .ultracode-for-codex/
185
+ ```
186
+
187
+ ## Troubleshooting
188
+
189
+ If Codex does not recognize `$ultracode-for-codex`, confirm that the skill
190
+ folder exists:
221
191
 
222
192
  ```bash
223
- npm run publish:dry-run
193
+ ls "${CODEX_HOME:-$HOME/.codex}/skills/ultracode-for-codex"
224
194
  ```
225
195
 
226
- Publish after `npm login`:
196
+ If `npm exec -- ultracode-for-codex` fails, confirm the package is installed:
227
197
 
228
198
  ```bash
229
- npm run publish:npm
199
+ npm ls ultracode-for-codex
230
200
  ```
231
201
 
232
- For supported CI/CD environments, provenance is available as an explicit opt-in:
202
+ If a CLI workflow is still running, list local jobs:
233
203
 
234
204
  ```bash
235
- npm run publish:npm:provenance
205
+ npm exec -- ultracode-for-codex jobs --cwd /path/to/project
236
206
  ```
237
207
 
238
- Optional live smoke against the local Codex CLI:
208
+ ## For Maintainers
209
+
210
+ Common source checkout commands:
239
211
 
240
212
  ```bash
241
- ULTRACODE_LIVE_SMOKE=1 npm run smoke:live
213
+ npm install
214
+ npm test
215
+ npm run test:e2e:ultracode-for-codex
216
+ npm run test:all
217
+ npm run pack:ultracode-for-codex
242
218
  ```
243
219
 
244
- Useful local run:
220
+ Check the publish payload:
245
221
 
246
222
  ```bash
247
- npm run build
248
- node dist/cli.js run --accept-llm-guide=v1 --script-file ./workflow.js
223
+ npm run publish:dry-run
249
224
  ```
250
225
 
251
- ## Docs
252
-
253
- - `skills/ultracode-for-codex/SKILL.md`: default Codex-native orchestrator
254
- skill command.
255
- - `skills/ultracode-for-codex/references/progress-visuals.md`: golden visual
256
- progress and completion summary examples for native orchestration.
257
- - `skills/ultracode-for-codex-cli/SKILL.md`: explicit CLI runtime skill command.
258
- - `ULTRACODE_INSTALL.md`: install and operating guide for LLM agents.
259
- - `docs/ultracode-p3a-journal-design.md`: journal contract.
260
- - `docs/ultracode-p3b-resume-cache.md`: runtime-internal resume/cache contract.
261
- - `docs/ultracode-p3c-worktree-isolation.md`: worktree isolation contract.
226
+ ## More Documentation
227
+
228
+ - `ULTRACODE_INSTALL.md`: detailed install and operating guide.
229
+ - `skills/ultracode-for-codex/SKILL.md`: Codex-native orchestration behavior.
230
+ - `skills/ultracode-for-codex/references/progress-visuals.md`: progress display
231
+ examples.
232
+ - `skills/ultracode-for-codex-cli/SKILL.md`: CLI runtime behavior.
@@ -99,13 +99,19 @@ npm exec -- ultracode-for-codex archive <jobId> --cwd /path/to/project
99
99
  ```
100
100
 
101
101
  Use CLI built-in `task` for general work and `code-review` for review-specific
102
- work. Both start with an LLM planner, execute phase by phase, run multiple
103
- focused Codex subagents in parallel within each phase by default, and synthesize
104
- phase and final results. The planner chooses a single-agent path only when
105
- parallel execution would add risk or waste.
106
- Planner guidance includes classify-and-act, fan-out-and-synthesize,
107
- adversarial verification, generate-and-filter, tournament, and loop-until-done
108
- patterns so different work types can use different phase shapes.
102
+ work. `task` starts with an LLM planner, executes phase by phase, runs multiple
103
+ focused Codex subagents in parallel within each phase by default, and chooses a
104
+ single-agent path only when parallel execution would add risk or waste. Planner
105
+ guidance includes classify-and-act, fan-out-and-synthesize, adversarial
106
+ verification, generate-and-filter, tournament, and loop-until-done patterns so
107
+ different work types can use different phase shapes.
108
+
109
+ `code-review` uses a specialized review harness. It collects bounded repository
110
+ evidence, selects active review lenses, runs one finder per lens in parallel,
111
+ verifies every emitted candidate with a candidate-scoped subagent, optionally
112
+ runs an `xhigh` sweep, then synthesizes final findings by verified candidate
113
+ index. The final JSON includes `findings`, `provenance`, `synthesis`, and
114
+ `stats`.
109
115
 
110
116
  Settings defaults:
111
117
 
@@ -145,7 +151,9 @@ Useful controls:
145
151
  - JSONL records include `kind`, `version`, `event`, `status`, and `summary`;
146
152
  agent records also include stable agent identity and label fields.
147
153
  - Built-in `task` and `code-review` emit `workflow.plan.ready` as a planning
148
- snapshot, not a promise that every later phase is already known.
154
+ snapshot, not a promise that every later phase is already known. In
155
+ `code-review`, later verifier agents are discovered after finder agents emit
156
+ candidates.
149
157
  - `workflow.phase.planned` is emitted immediately before each phase starts and
150
158
  carries that phase's current planned agent role labels. Each
151
159
  `workflow.phase.started` record repeats the same role labels when the phase
@@ -180,9 +188,10 @@ Useful controls:
180
188
  - Strip direct provider credentials from child CLI environments.
181
189
  - Run Codex subagents against the requested workflow cwd and provide bounded
182
190
  read-only workspace tools for text file reads and directory listings.
183
- - Built-in `task` and `code-review` add deterministic workspace context to
184
- planner-selected phase-wise parallel subagents, then synthesize each phase and
185
- the final result.
191
+ - Built-in `task` adds deterministic workspace context to planner-selected
192
+ phase-wise parallel subagents. Built-in `code-review` uses deterministic
193
+ review evidence, allowed evidence refs, dynamic lenses, candidate verification,
194
+ and bounded final synthesis.
186
195
  - Install consumers from a packaged artifact.
187
196
  - Keep `journalPath`, `journal.jsonl`, and journal contents out of CLI output.
188
197
  Local runtime state may still contain runtime-owned
package/dist/cli.js CHANGED
@@ -1116,31 +1116,27 @@ function workflowPhaseExecutionSummary(events) {
1116
1116
  for (const event of events) {
1117
1117
  if (event.type !== 'workflow.agent.started' || !event.phase)
1118
1118
  continue;
1119
+ const startedAgent = {
1120
+ title: event.label,
1121
+ label: event.label,
1122
+ angle: event.promptPreview,
1123
+ };
1119
1124
  const existing = phases.get(event.phase);
1120
1125
  if (!existing) {
1121
1126
  phases.set(event.phase, {
1122
1127
  title: event.phase,
1123
1128
  agentCount: 1,
1124
- agents: [{
1125
- title: event.label,
1126
- label: event.label,
1127
- angle: event.promptPreview,
1128
- }],
1129
+ agents: [startedAgent],
1129
1130
  });
1130
1131
  continue;
1131
1132
  }
1132
- if (phaseTitlesWithPlannedAgents.has(event.phase))
1133
+ if (phaseTitlesWithPlannedAgents.has(event.phase)
1134
+ && existing.agents.length > 0
1135
+ && !phaseSummaryAllowsDynamicStartedAgents(existing))
1133
1136
  continue;
1134
1137
  if (existing.agents.some((agent) => agent.label === event.label || agent.title === event.label))
1135
1138
  continue;
1136
- const agents = [
1137
- ...existing.agents,
1138
- {
1139
- title: event.label,
1140
- label: event.label,
1141
- angle: event.promptPreview,
1142
- },
1143
- ];
1139
+ const agents = [...existing.agents, startedAgent];
1144
1140
  phases.set(event.phase, {
1145
1141
  ...existing,
1146
1142
  agentCount: agents.length,
@@ -1149,6 +1145,14 @@ function workflowPhaseExecutionSummary(events) {
1149
1145
  }
1150
1146
  return [...phases.values()];
1151
1147
  }
1148
+ function phaseSummaryAllowsDynamicStartedAgents(phase) {
1149
+ return phase.agents.some((agent) => {
1150
+ const label = agent.label ?? '';
1151
+ const title = agent.title ?? '';
1152
+ const angle = agent.angle ?? '';
1153
+ return /\bdynamic\b/i.test(`${label} ${title} ${angle}`);
1154
+ });
1155
+ }
1152
1156
  function criticalReviewRecommendation() {
1153
1157
  return 'Session LLM should critically re-check the final result before acting: verify whether the conclusion is justified, internally consistent, supported by the observed workflow evidence, and missing material counterarguments.';
1154
1158
  }
@@ -12,6 +12,7 @@ export interface WorkflowAgentSemanticOpts {
12
12
  readonly effort?: string;
13
13
  readonly isolation?: string;
14
14
  readonly agentType?: string;
15
+ readonly logicalKey?: string;
15
16
  }
16
17
  export type WorkflowJournalEntry = WorkflowRunStartedEntry | WorkflowAgentStartedEntry | WorkflowAgentCompletedEntry | WorkflowAgentFailedEntry | WorkflowRunCompletedEntry | WorkflowRunFailedEntry;
17
18
  interface WorkflowJournalEntryEnvelope {
@@ -219,6 +219,9 @@ export function computeWorkflowAgentCallKey(input) {
219
219
  if (!HASH_RE.test(input.previousAgentCallKey)) {
220
220
  throw new WorkflowJournalValidationError('previousAgentCallKey must be a 64-character sha256 hex digest.');
221
221
  }
222
+ if (input.semanticOpts.logicalKey) {
223
+ return sha256(`logical\0${input.semanticOpts.logicalKey}\0${input.prompt}\0${stableJson(input.semanticOpts)}`);
224
+ }
222
225
  return sha256(`${input.previousAgentCallKey}\0${input.prompt}\0${stableJson(input.semanticOpts)}`);
223
226
  }
224
227
  export function workflowJournalHash(entryWithoutEntryHash) {
@@ -473,10 +476,10 @@ function assertWorkflowAgentSemanticOpts(value) {
473
476
  const opts = asRecord(value);
474
477
  if (!opts)
475
478
  throw new WorkflowJournalValidationError('semanticOpts must be an object.');
476
- rejectUnknownKeys(opts, ['schema', 'model', 'effort', 'isolation', 'agentType'], 'semanticOpts');
479
+ rejectUnknownKeys(opts, ['schema', 'model', 'effort', 'isolation', 'agentType', 'logicalKey'], 'semanticOpts');
477
480
  if (typeof opts.model !== 'string' || !opts.model)
478
481
  throw new WorkflowJournalValidationError('semanticOpts.model must be a string.');
479
- for (const key of ['effort', 'isolation', 'agentType']) {
482
+ for (const key of ['effort', 'isolation', 'agentType', 'logicalKey']) {
480
483
  if (opts[key] !== undefined && typeof opts[key] !== 'string') {
481
484
  throw new WorkflowJournalValidationError(`semanticOpts.${key} must be a string.`);
482
485
  }