aiterm-mcp 0.61.13 → 0.61.15
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 +15 -1
- package/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/execution-parent-worker.js +16 -1
- package/dist/execution-service.js +54 -23
- package/docs/DESIGN.md +7 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.61.15] - 2026-10-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Completion checks observe the original request boundary outside the shared metadata mutex, then revalidate the unchanged original record and all uncertainty/slot gates before committing. Slow transcript/native completion observation no longer blocks unrelated admission; unknown sends are never reconciled or replayed.
|
|
15
|
+
|
|
16
|
+
## [0.61.14] - 2026-10-24
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Native execution participants retain their verified current-process identity instead of spawning another OS identity probe at every scope check. Foreign process, multiplexer, source/target generation and participant checks remain fresh. This reduces admission overhead; it does not reconcile unknown sends or establish recovery from a production mutex timeout.
|
|
21
|
+
|
|
10
22
|
## [0.61.13] - 2026-10-24
|
|
11
23
|
|
|
12
24
|
### Validation scope
|
|
@@ -2836,7 +2848,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
2836
2848
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
2837
2849
|
provenance.
|
|
2838
2850
|
|
|
2839
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.
|
|
2851
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.15...HEAD
|
|
2852
|
+
[0.61.15]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.14...v0.61.15
|
|
2853
|
+
[0.61.14]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.13...v0.61.14
|
|
2840
2854
|
[0.61.13]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.12...v0.61.13
|
|
2841
2855
|
[0.61.12]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.11...v0.61.12
|
|
2842
2856
|
[0.61.11]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.10...v0.61.11
|
package/README.ja.md
CHANGED
|
@@ -209,7 +209,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
209
209
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
210
210
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
211
211
|
|
|
212
|
-
**状態:** 開発継続中 · 現行公開版 **v0.61.
|
|
212
|
+
**状態:** 開発継続中 · 現行公開版 **v0.61.15** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
213
213
|
|
|
214
214
|
### 更新と巻き戻し
|
|
215
215
|
|
package/README.md
CHANGED
|
@@ -227,7 +227,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
227
227
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
228
228
|
Release re-registers the Official MCP Registry entry.
|
|
229
229
|
|
|
230
|
-
**Status:** actively maintained · current public release **v0.61.
|
|
230
|
+
**Status:** actively maintained · current public release **v0.61.15** · runs on Linux · WSL2 · macOS · native Windows (tmux on POSIX, the tmux-CLI-compatible [psmux](https://github.com/psmux/psmux) on native Windows — no WSL required) · MIT · see the [CHANGELOG](CHANGELOG.md).
|
|
231
231
|
|
|
232
232
|
### Update and rollback
|
|
233
233
|
|
|
@@ -15,9 +15,24 @@ import { createSteerExecutionAdmission } from "./execution-steer.js";
|
|
|
15
15
|
import { ExecutionError } from "./execution-wire.js";
|
|
16
16
|
import { parentHookReference } from "./execution-parent-alias.js";
|
|
17
17
|
import { requireExecutionEffectScope } from "./execution-effect.js";
|
|
18
|
+
let localActor;
|
|
19
|
+
function currentLocalActor() {
|
|
20
|
+
// This code is executing in the observed process. Its PID/start identity
|
|
21
|
+
// cannot change during its lifetime; another process has its own module.
|
|
22
|
+
// Keep only a verified self identity, never a server/parent/target sample.
|
|
23
|
+
// Missing/failed first reads remain failures and may be observed again.
|
|
24
|
+
if (!localActor || localActor.pid !== process.pid) {
|
|
25
|
+
const observed = readProcessIdentities([process.pid])[0];
|
|
26
|
+
if (!observed || observed.pid !== process.pid || !observed.started_identity
|
|
27
|
+
|| !Number.isFinite(Date.parse(observed.started_identity)))
|
|
28
|
+
return null;
|
|
29
|
+
localActor = Object.freeze({ pid: observed.pid, started_identity: observed.started_identity });
|
|
30
|
+
}
|
|
31
|
+
return { ...localActor };
|
|
32
|
+
}
|
|
18
33
|
export const localParentWorkerRuntime = {
|
|
19
34
|
scope: () => ({ state_root: stateRoot(), multiplexer: isWin ? { kind: "namespace", key: WIN_NS } : { kind: "socket", key: SOCK } }),
|
|
20
|
-
actor:
|
|
35
|
+
actor: currentLocalActor,
|
|
21
36
|
observeActors: readProcessIdentities,
|
|
22
37
|
observeParentProcess: observeExecutionParentProcess, observeSessionGeneration: observeExecutionSessionGeneration,
|
|
23
38
|
};
|
|
@@ -1113,6 +1113,8 @@ export class ExecutionService {
|
|
|
1113
1113
|
});
|
|
1114
1114
|
}
|
|
1115
1115
|
async finish(args) {
|
|
1116
|
+
if (args.evidence.kind === "completion")
|
|
1117
|
+
return this.finishCompletion(args.request, args.evidence.target);
|
|
1116
1118
|
return this.store.transaction(async (state) => {
|
|
1117
1119
|
const record = find(state, args.request);
|
|
1118
1120
|
if (record.operations.launch === "issued" || record.operations.send === "issued"
|
|
@@ -1134,34 +1136,63 @@ export class ExecutionService {
|
|
|
1134
1136
|
const target = record.relation.target;
|
|
1135
1137
|
if (!target)
|
|
1136
1138
|
throw new ExecutionError("EXECUTION_CONFLICT");
|
|
1137
|
-
if (args.evidence.
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
record.relation.target_fence = pendingParentReturn(state, args.request) ? "unknown"
|
|
1147
|
-
: observed.state === "completed" ? "closed" : observed.fence;
|
|
1148
|
-
}
|
|
1149
|
-
else {
|
|
1150
|
-
if (!same(target.launch, args.evidence.target))
|
|
1151
|
-
throw new ExecutionError("EXECUTION_CONFLICT", "possible");
|
|
1152
|
-
if (record.relation.completion === "interrupted" && record.relation.target_fence === "closed")
|
|
1153
|
-
return view(state, record);
|
|
1154
|
-
const observed = await this.runtime.observe(target.launch.session_id);
|
|
1155
|
-
if (observed.state !== "absent" || state.slots.some(slot => slot.session_id === target.launch.session_id))
|
|
1156
|
-
throw new ExecutionError("EXECUTION_UNCONFIRMED", "possible");
|
|
1157
|
-
record.relation.completion = "interrupted";
|
|
1158
|
-
record.relation.target_fence = "closed";
|
|
1159
|
-
}
|
|
1139
|
+
if (!same(target.launch, args.evidence.target))
|
|
1140
|
+
throw new ExecutionError("EXECUTION_CONFLICT", "possible");
|
|
1141
|
+
if (record.relation.completion === "interrupted" && record.relation.target_fence === "closed")
|
|
1142
|
+
return view(state, record);
|
|
1143
|
+
const observed = await this.runtime.observe(target.launch.session_id);
|
|
1144
|
+
if (observed.state !== "absent" || state.slots.some(slot => slot.session_id === target.launch.session_id))
|
|
1145
|
+
throw new ExecutionError("EXECUTION_UNCONFIRMED", "possible");
|
|
1146
|
+
record.relation.completion = "interrupted";
|
|
1147
|
+
record.relation.target_fence = "closed";
|
|
1160
1148
|
}
|
|
1161
1149
|
retireSettledBranches(state);
|
|
1162
1150
|
return view(state, record);
|
|
1163
1151
|
});
|
|
1164
1152
|
}
|
|
1153
|
+
/** Completion evidence is for one fixed historical request/Point. Native
|
|
1154
|
+
* transcript/generation observation must not hold the global writer mutex.
|
|
1155
|
+
* Commit only if the original record and all uncertainty gates still match;
|
|
1156
|
+
* an unrelated writer is allowed to progress while evidence is observed.
|
|
1157
|
+
*/
|
|
1158
|
+
async finishCompletion(request, target) {
|
|
1159
|
+
const eligible = (state) => {
|
|
1160
|
+
const record = find(state, request);
|
|
1161
|
+
if ([record.operations.launch, record.operations.send].some(stage => stage === "issued" || stage === "unknown")
|
|
1162
|
+
|| state.slots.some(slot => slot.request && same(slot.request, request))
|
|
1163
|
+
|| openParentEffect(state, request))
|
|
1164
|
+
throw new ExecutionError("EXECUTION_UNCONFIRMED", "possible");
|
|
1165
|
+
if (!record.relation.target)
|
|
1166
|
+
throw new ExecutionError("EXECUTION_CONFLICT");
|
|
1167
|
+
if (!record.relation.target.boundary || !same(record.relation.target, target))
|
|
1168
|
+
throw new ExecutionError("EXECUTION_CONFLICT", "possible");
|
|
1169
|
+
return record;
|
|
1170
|
+
};
|
|
1171
|
+
const settled = (record) => record.relation.completion === "completed" && record.relation.target_fence === "closed";
|
|
1172
|
+
const initial = await this.store.transaction(state => {
|
|
1173
|
+
const record = eligible(state);
|
|
1174
|
+
return { record, result: view(state, record) };
|
|
1175
|
+
}, { readOnly: true });
|
|
1176
|
+
if (settled(initial.record))
|
|
1177
|
+
return initial.result;
|
|
1178
|
+
const observed = { ...await this.runtime.completion(executionPointSchema.parse(target)) };
|
|
1179
|
+
if (observed.state === "unknown")
|
|
1180
|
+
throw new ExecutionError("EXECUTION_UNCONFIRMED", "possible");
|
|
1181
|
+
return this.store.transaction(state => {
|
|
1182
|
+
const record = eligible(state);
|
|
1183
|
+
if (settled(record))
|
|
1184
|
+
return view(state, record);
|
|
1185
|
+
// Do not overwrite a concurrent cancellation, target rebinding, phase
|
|
1186
|
+
// change or interruption with an earlier read's completion evidence.
|
|
1187
|
+
if (!same(record, initial.record))
|
|
1188
|
+
throw new ExecutionError("EXECUTION_UNCONFIRMED", "possible");
|
|
1189
|
+
record.relation.completion = observed.state;
|
|
1190
|
+
record.relation.target_fence = pendingParentReturn(state, request) ? "unknown"
|
|
1191
|
+
: observed.state === "completed" ? "closed" : observed.fence;
|
|
1192
|
+
retireSettledBranches(state);
|
|
1193
|
+
return view(state, record);
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1165
1196
|
/** Adapter for existing restart/configuration/close paths. It shares the
|
|
1166
1197
|
* same per-seat issuance slots as dispatch and stop, without creating a job ID.
|
|
1167
1198
|
* Callers must not wrap a multi-step restart in one unobserved callback:
|
package/docs/DESIGN.md
CHANGED
|
@@ -53,11 +53,18 @@ private participant factoryはproducer/service/dispatcher/同process用worker pr
|
|
|
53
53
|
source環境の既存8名は一度だけ読み、必要な値だけを固定してproducerとdispatcherへ渡す。
|
|
54
54
|
呼出側のprovider/profile/runtime methodの差替えは構築済みparticipantへ混入させず、現在のscope/actorの変化は作用前に拒否する。
|
|
55
55
|
親managerの保存先とownerも同じscope/actorへ照合する。別processのhookはactorを流用せず、自分のworker factoryで接続する。
|
|
56
|
+
native runtimeの自己actorは、現在実行中のprocessのPIDと開始identityを一度だけOSで確定して保持する。
|
|
57
|
+
同processの生存中に開始identityは変わらないため、scope確認ごとの自己PID照会を行わない。
|
|
58
|
+
初回の欠測・失敗は確定値として保持せず、返すobjectも複製する。注入runtimeのactor、他process・server・
|
|
59
|
+
source/target世代の観測は保持せず、従来どおり各受付で再照合する。
|
|
56
60
|
注入runtimeへ欠けたparent依存を既定OS処理で補わず、完全なfake依存を要求する。このfactoryも通常mainには未注入。
|
|
57
61
|
同producer serviceの停止closeは、既存のissued close slotを持つ間だけ同期の期待世代primitiveへ渡す。
|
|
58
62
|
実killの直前にもruntimeの同期世代読取を通し、scope/actor/期待launchの交代を拒否する。
|
|
59
63
|
注入runtimeのclose欠測をcore既定処理で補わず、作用後の応答欠測は消失観測があってもunknown slotを保持する。
|
|
60
64
|
完了の照会点は固定し、終了fenceの非同期応答後にも現在世代を確認する。実受取番/終了fenceの証拠adapterは未了。
|
|
65
|
+
通常のcompletion終了確認は元request/Pointを共有lock内で固定し、native/transcript観測をlock外で行う。
|
|
66
|
+
反映時に同じrecord全体・issued/unknown・元slot・親作用を再照合し、途中変更があれば反映しない。
|
|
67
|
+
親返却のpending判定は反映時のstateで行い、元unknownの解除や送信の再実行には使わない。
|
|
61
68
|
private producer/worker factoryを構築したprocessではnative effect scopeを必須にする。
|
|
62
69
|
coreの公開変更入口も、打鍵や設定・認証・lock/metadata準備に入る前に対象のrequest contextを要求する。
|
|
63
70
|
この入口確認はissuedへの昇格ではない。実作用時には既存の同期受付を別に通す。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.61.
|
|
3
|
+
"version": "0.61.15",
|
|
4
4
|
"mcpName": "io.github.kitepon/aiterm-mcp",
|
|
5
5
|
"description": "Persistent terminal MCP with one harness-based launcher for Claude Code, Codex CLI, Grok CLI, and Cursor Agent CLI, plus durable PTYs for SSH, containers, and REPLs.",
|
|
6
6
|
"keywords": [
|