@orion-agents/orion-code 0.3.21 → 0.3.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -22,13 +22,27 @@ which is **not** a pass.
22
22
 
23
23
  ## [Unreleased]
24
24
 
25
- ## [0.3.21] — UNRELEASED
25
+ ## [0.3.22] — UNRELEASED
26
26
 
27
- > **Status: candidate.** Open. Adds user-authorized local project-root discovery to
28
- > `LOCAL WORKSPACE` (bounded scan, explicit inspect → confirm → activate reuse, no
29
- > Home/network-volume scanning, no silent registration) and corrects the v0.3.20
30
- > release-facts documentation (`docs/plan/evidence/v0.3.20-e2e/release-receipt-v0.3.20.md`).
31
- > Not merged, tagged or published.
27
+ > **Status: candidate.** Open. Agent Reliability & Efficiency — hardens ToolGateway
28
+ > in-flight request identity (T22-01), adds the durability fault-injection matrix (T22-02),
29
+ > the four-state release verification gate (T22-03), and a real coding-task evaluation
30
+ > harness (T22-04). Plan: `docs/plan/v0.3.22-plan.md`. Not merged, tagged or published.
31
+
32
+ ### Fixed (product)
33
+
34
+ - ToolGateway in-flight dedupe now compares the full request digest: the same invocationId
35
+ with different arguments, tool, snapshot, or parent conflicts
36
+ (`ORION_TOOL_INVOCATION_CONFLICT`) instead of reusing the running execution's promise.
37
+
38
+ ## [0.3.21] — 2026-10-09
39
+
40
+ > **Status: published.** Released as `@orion-agents/orion-code@0.3.21` from
41
+ > `refs/tags/v0.3.21`, and merged to `main` as `0d22c9a` (#264). Adds user-authorized
42
+ > local project-root discovery to `LOCAL WORKSPACE` (bounded scan, explicit
43
+ > inspect → confirm → activate reuse, no Home/network-volume scanning, no silent
44
+ > registration) and corrects the v0.3.20 release-facts documentation
45
+ > (`docs/plan/evidence/v0.3.20-e2e/release-receipt-v0.3.20.md`).
32
46
 
33
47
  ### Added (planned)
34
48
 
package/README.md CHANGED
@@ -2,10 +2,9 @@
2
2
 
3
3
  Local-first, goal-driven coding agent for the terminal and browser.
4
4
 
5
- > v0.3.21 candidate — open. Adds user-authorized local project-root discovery to
6
- > `LOCAL WORKSPACE` (bounded scan, explicit inspect → confirm → activate reuse). The previous
7
- > release 0.3.20 is on npm (registry `latest`) and tagged `v0.3.20` (`e658932`, #261) —
8
- > release facts: `docs/plan/evidence/v0.3.20-e2e/release-receipt-v0.3.20.md`.
5
+ > v0.3.22 candidate — open. Hardens agent reliability (ToolGateway in-flight request
6
+ > identity) and builds a real coding-task evaluation harness. The previous release 0.3.21
7
+ > is on npm (registry `latest`) and tagged `v0.3.21` (`0d22c9a`, #264).
9
8
 
10
9
  [中文说明](README.zh-CN.md) ·
11
10
  [v0.3.7 plan](docs/plan/v0.3.7-left-rail-improvement-plan.md) ·
@@ -170,7 +169,7 @@ current development environments. Node 20 is upstream EOL and is no longer a v0.
170
169
  After the immutable `0.3.5` npm receipt exists:
171
170
 
172
171
  ```bash
173
- npm install -g @orion-agents/orion-code@0.3.21
172
+ npm install -g @orion-agents/orion-code@0.3.22
174
173
  orion --version
175
174
  orion doctor
176
175
  ```
package/README.zh-CN.md CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  面向终端与浏览器、本地优先的目标驱动 Coding Agent。
4
4
 
5
- > v0.3.21 候选版本:进行中。为 `LOCAL WORKSPACE` 增加用户显式授权的项目根目录发现(有界
6
- > 扫描、复用 inspect → confirm → activate)。上一版 0.3.20 已发布 npm(registry `latest`)
7
- > 并打 tag `v0.3.20`(`e658932`,#261)——发布事实:`docs/plan/evidence/v0.3.20-e2e/release-receipt-v0.3.20.md`。
5
+ > v0.3.22 候选版本:进行中。强化 Agent 可靠性(ToolGateway 执行中请求身份)并建设真实编码
6
+ > 任务评测体系。上一版 0.3.21 已发布 npm(registry `latest`)并打 tag `v0.3.21`(`0d22c9a`,#264)。
8
7
 
9
8
  [English](README.md) ·
10
9
  [v0.3.7 方案](docs/plan/v0.3.7-left-rail-improvement-plan.md) ·
@@ -101,7 +100,7 @@ Current。Node 20 已结束上游维护,不再属于 v0.3 Runtime 合同。
101
100
  当 npm 已存在不可变的 `0.3.4` 发布凭据后:
102
101
 
103
102
  ```bash
104
- npm install -g @orion-agents/orion-code@0.3.21
103
+ npm install -g @orion-agents/orion-code@0.3.22
105
104
  orion --version
106
105
  orion doctor
107
106
  ```
@@ -140,6 +140,12 @@ export declare class ToolGatewayError extends Error {
140
140
  /** Capability → Policy → Approval → Sandbox → Execute → durable terminal receipt. */
141
141
  export declare class ToolGateway {
142
142
  private readonly services;
143
+ /**
144
+ * v0.3.22 T22-01 — in-flight entries carry the full request digest so the
145
+ * same invocationId with different arguments, tool, snapshot, or parent
146
+ * conflicts instead of silently reusing the first execution's promise
147
+ * (matching the durable journal's guard strength).
148
+ */
143
149
  private readonly inflight;
144
150
  private readonly clock;
145
151
  constructor(services: ToolGatewayServicesV1);
@@ -19,16 +19,38 @@ exports.ToolGatewayError = ToolGatewayError;
19
19
  class ToolGateway {
20
20
  constructor(services) {
21
21
  this.services = services;
22
+ /**
23
+ * v0.3.22 T22-01 — in-flight entries carry the full request digest so the
24
+ * same invocationId with different arguments, tool, snapshot, or parent
25
+ * conflicts instead of silently reusing the first execution's promise
26
+ * (matching the durable journal's guard strength).
27
+ */
22
28
  this.inflight = new Map();
23
29
  this.clock = services.clock ?? Date.now;
24
30
  }
25
31
  invoke(invocation) {
32
+ const requestDigest = computeRequestDigest(invocation);
26
33
  const existing = this.inflight.get(invocation.invocationId);
27
- if (existing)
28
- return existing;
29
- const run = this.invokeOnce(invocation).finally(() => this.inflight.delete(invocation.invocationId));
30
- this.inflight.set(invocation.invocationId, run);
31
- return run;
34
+ if (existing) {
35
+ if (existing.requestDigest !== requestDigest) {
36
+ // Reject (rather than throw synchronously) so callers awaiting the
37
+ // invocation observe the conflict through the same promise channel as
38
+ // the durable-journal conflict.
39
+ return Promise.reject(new ToolGatewayError('ORION_TOOL_INVOCATION_CONFLICT', 'Invocation ID is already executing with different arguments or snapshot', invocation.invocationId));
40
+ }
41
+ return existing.promise;
42
+ }
43
+ const promise = this.invokeOnce(invocation).finally(() => {
44
+ // Remove only our own entry: the guard keeps a defensive barrier against
45
+ // deleting an entry created by a later invocation after this run
46
+ // finished.
47
+ const current = this.inflight.get(invocation.invocationId);
48
+ if (current && current.requestDigest === requestDigest) {
49
+ this.inflight.delete(invocation.invocationId);
50
+ }
51
+ });
52
+ this.inflight.set(invocation.invocationId, { requestDigest, promise });
53
+ return promise;
32
54
  }
33
55
  async invokeOnce(invocation) {
34
56
  validateInvocation(invocation);
@@ -237,8 +259,13 @@ function createStaticApprovalDecisionV1(input) {
237
259
  function createSandboxPreparationV1(input) {
238
260
  return deepFreeze({ ...input, digest: (0, canonical_1.digestRuntimeValue)(input) });
239
261
  }
240
- function createIntent(invocation, startedAt) {
241
- const requestDigest = (0, canonical_1.digestRuntimeValue)({
262
+ /**
263
+ * v0.3.22 T22-01 — the authoritative request identity, shared by the durable
264
+ * intent and the in-flight dedupe map. Excludes startedAt so identity stays
265
+ * stable across retries within one execution.
266
+ */
267
+ function computeRequestDigest(invocation) {
268
+ return (0, canonical_1.digestRuntimeValue)({
242
269
  invocationId: invocation.invocationId,
243
270
  parentInvocationId: invocation.parentInvocationId,
244
271
  threadId: invocation.snapshot.threadId,
@@ -248,6 +275,9 @@ function createIntent(invocation, startedAt) {
248
275
  snapshotDigest: invocation.snapshot.digest,
249
276
  argsDigest: (0, canonical_1.digestRuntimeValue)(invocation.args),
250
277
  });
278
+ }
279
+ function createIntent(invocation, startedAt) {
280
+ const requestDigest = computeRequestDigest(invocation);
251
281
  const content = {
252
282
  version: 1,
253
283
  invocationId: invocation.invocationId,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@orion-agents/orion-code",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@orion-agents/orion-code",
9
- "version": "0.3.21",
9
+ "version": "0.3.22",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@clack/prompts": "^0.7.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-agents/orion-code",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "description": "Orion Code - local-first goal-driven coding agent for terminal and Web.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",