kiokuko-dsh 0.2.21 → 0.2.23
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.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/deep-thinker/current-model.d.ts.map +1 -1
- package/dist/deep-thinker/current-model.js +4 -0
- package/dist/deep-thinker/current-model.js.map +1 -1
- package/dist/dsh/answer-review/contracts.d.ts +1 -0
- package/dist/dsh/answer-review/contracts.d.ts.map +1 -1
- package/dist/dsh/answer-review/coordinator.js +3 -3
- package/dist/dsh/answer-review/coordinator.js.map +1 -1
- package/dist/dsh/clarification-context.d.ts +24 -0
- package/dist/dsh/clarification-context.d.ts.map +1 -0
- package/dist/dsh/clarification-context.js +31 -0
- package/dist/dsh/clarification-context.js.map +1 -0
- package/dist/dsh/coding-question.d.ts +26 -0
- package/dist/dsh/coding-question.d.ts.map +1 -0
- package/dist/dsh/coding-question.js +48 -0
- package/dist/dsh/coding-question.js.map +1 -0
- package/dist/dsh/coding-workflow/contracts.d.ts +2 -2
- package/dist/dsh/coding-workflow/host.d.ts +2 -4
- package/dist/dsh/coding-workflow/host.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/host.js +13 -29
- package/dist/dsh/coding-workflow/host.js.map +1 -1
- package/dist/dsh/coding-workflow/intent.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/intent.js +2 -1
- package/dist/dsh/coding-workflow/intent.js.map +1 -1
- package/dist/dsh/coding-workflow/service.d.ts +6 -6
- package/dist/dsh/coding-workflow/service.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/service.js +5 -3
- package/dist/dsh/coding-workflow/service.js.map +1 -1
- package/dist/dsh/guardrail/contracts.d.ts +33 -1
- package/dist/dsh/guardrail/contracts.d.ts.map +1 -1
- package/dist/dsh/guardrail/contracts.js +1 -1
- package/dist/dsh/guardrail/contracts.js.map +1 -1
- package/dist/dsh/guardrail/engine.d.ts +2 -0
- package/dist/dsh/guardrail/engine.d.ts.map +1 -1
- package/dist/dsh/guardrail/engine.js +18 -7
- package/dist/dsh/guardrail/engine.js.map +1 -1
- package/dist/dsh/guardrail/evidence.d.ts.map +1 -1
- package/dist/dsh/guardrail/evidence.js +29 -1
- package/dist/dsh/guardrail/evidence.js.map +1 -1
- package/dist/dsh/guardrail/service.d.ts +2 -0
- package/dist/dsh/guardrail/service.d.ts.map +1 -1
- package/dist/dsh/guardrail/service.js +44 -2
- package/dist/dsh/guardrail/service.js.map +1 -1
- package/dist/dsh/lisp/ci.d.ts +7 -0
- package/dist/dsh/lisp/ci.d.ts.map +1 -1
- package/dist/dsh/lisp/ci.js +27 -10
- package/dist/dsh/lisp/ci.js.map +1 -1
- package/dist/dsh/lisp/coding-choice.d.ts +2 -0
- package/dist/dsh/lisp/coding-choice.d.ts.map +1 -1
- package/dist/dsh/lisp/coding-choice.js +5 -1
- package/dist/dsh/lisp/coding-choice.js.map +1 -1
- package/dist/dsh/lisp/coding-preparation.d.ts +4 -5
- package/dist/dsh/lisp/coding-preparation.d.ts.map +1 -1
- package/dist/dsh/lisp/coding-preparation.js +57 -18
- package/dist/dsh/lisp/coding-preparation.js.map +1 -1
- package/dist/dsh/lisp/compiled-cache.d.ts.map +1 -1
- package/dist/dsh/lisp/compiled-cache.js +4 -3
- package/dist/dsh/lisp/compiled-cache.js.map +1 -1
- package/dist/dsh/lisp/host-tool-dispatch.d.ts +19 -0
- package/dist/dsh/lisp/host-tool-dispatch.d.ts.map +1 -0
- package/dist/dsh/lisp/host-tool-dispatch.js +23 -0
- package/dist/dsh/lisp/host-tool-dispatch.js.map +1 -0
- package/dist/dsh/lisp/manager.d.ts +3 -0
- package/dist/dsh/lisp/manager.d.ts.map +1 -1
- package/dist/dsh/lisp/manager.js +114 -13
- package/dist/dsh/lisp/manager.js.map +1 -1
- package/dist/dsh/lisp/sandbox.d.ts.map +1 -1
- package/dist/dsh/lisp/sandbox.js +4 -2
- package/dist/dsh/lisp/sandbox.js.map +1 -1
- package/dist/dsh/lisp/surface.d.ts.map +1 -1
- package/dist/dsh/lisp/surface.js +62 -25
- package/dist/dsh/lisp/surface.js.map +1 -1
- package/dist/dsh/lisp/worker.d.ts +10 -2
- package/dist/dsh/lisp/worker.d.ts.map +1 -1
- package/dist/dsh/lisp/worker.js +21 -11
- package/dist/dsh/lisp/worker.js.map +1 -1
- package/dist/dsh/managed-operation-journal.d.ts +115 -0
- package/dist/dsh/managed-operation-journal.d.ts.map +1 -0
- package/dist/dsh/managed-operation-journal.js +336 -0
- package/dist/dsh/managed-operation-journal.js.map +1 -0
- package/dist/dsh/managed-operation-runner.d.ts +33 -0
- package/dist/dsh/managed-operation-runner.d.ts.map +1 -0
- package/dist/dsh/managed-operation-runner.js +104 -0
- package/dist/dsh/managed-operation-runner.js.map +1 -0
- package/dist/dsh/model-routing.d.ts +8 -4
- package/dist/dsh/model-routing.d.ts.map +1 -1
- package/dist/dsh/model-routing.js +81 -22
- package/dist/dsh/model-routing.js.map +1 -1
- package/dist/dsh/models/surface.d.ts.map +1 -1
- package/dist/dsh/models/surface.js +7 -1
- package/dist/dsh/models/surface.js.map +1 -1
- package/dist/dsh/models/vendor/opencode-adapter.d.ts.map +1 -1
- package/dist/dsh/models/vendor/opencode-adapter.js +2 -0
- package/dist/dsh/models/vendor/opencode-adapter.js.map +1 -1
- package/dist/dsh/on-demand-intake.d.ts +12 -0
- package/dist/dsh/on-demand-intake.d.ts.map +1 -1
- package/dist/dsh/on-demand-intake.js +61 -9
- package/dist/dsh/on-demand-intake.js.map +1 -1
- package/dist/dsh/owned-execution.d.ts +2 -0
- package/dist/dsh/owned-execution.d.ts.map +1 -1
- package/dist/dsh/owned-execution.js +242 -110
- package/dist/dsh/owned-execution.js.map +1 -1
- package/dist/dsh/request-interpretation-guidance.d.ts +26 -0
- package/dist/dsh/request-interpretation-guidance.d.ts.map +1 -0
- package/dist/dsh/request-interpretation-guidance.js +35 -0
- package/dist/dsh/request-interpretation-guidance.js.map +1 -0
- package/dist/dsh/semantic-compaction/coordinator.d.ts.map +1 -1
- package/dist/dsh/semantic-compaction/coordinator.js +15 -1
- package/dist/dsh/semantic-compaction/coordinator.js.map +1 -1
- package/dist/dsh/task-completion-guidance.d.ts +25 -0
- package/dist/dsh/task-completion-guidance.d.ts.map +1 -0
- package/dist/dsh/task-completion-guidance.js +36 -0
- package/dist/dsh/task-completion-guidance.js.map +1 -0
- package/dist/dsh/task-completion-host.d.ts.map +1 -1
- package/dist/dsh/task-completion-host.js +17 -7
- package/dist/dsh/task-completion-host.js.map +1 -1
- package/dist/dsh/task-completion.d.ts +26 -2
- package/dist/dsh/task-completion.d.ts.map +1 -1
- package/dist/dsh/task-completion.js +27 -13
- package/dist/dsh/task-completion.js.map +1 -1
- package/dist/enno-oduno/coding-workflow.d.ts +1 -1
- package/dist/locale/en.json +1 -1
- package/dist/locale/ja.json +1 -1
- package/dist/locale/ko.json +1 -1
- package/dist/locale/zh-CN.json +1 -1
- package/docs/current-upstream-compatibility-report.md +85 -0
- package/docs/dsh-plugin.md +6 -2
- package/docs/getting-started.ja.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/guardrail.md +11 -4
- package/docs/lisp-prototype-planning.md +1 -1
- package/docs/lisp.md +1 -1
- package/docs/managed-operation-journal.md +21 -0
- package/docs/memory-lifecycle-verification.md +5 -4
- package/docs/tool-exposure.md +2 -0
- package/guardrail/aarch64-apple-darwin/kiokuko-guardrail +0 -0
- package/guardrail/aarch64-apple-darwin/manifest.json +14 -18
- package/guardrail/aarch64-unknown-linux-musl/kiokuko-guardrail +0 -0
- package/guardrail/aarch64-unknown-linux-musl/manifest.json +14 -16
- package/guardrail/build-records.json +198 -0
- package/guardrail/manifest.json +25 -137
- package/guardrail/x86_64-unknown-linux-musl/kiokuko-guardrail +0 -0
- package/guardrail/x86_64-unknown-linux-musl/manifest.json +14 -15
- package/migrations/047_managed_operation_journal.sql +21 -0
- package/package.json +7 -3
- package/scripts/guardrail-artifacts.d.mts +3 -0
- package/scripts/guardrail-artifacts.mjs +34 -2
- package/scripts/repair-continuation-source.mjs +11 -25
package/dist/dsh/lisp/manager.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ManagedOperationJournal } from '../managed-operation-journal.js';
|
|
2
|
+
import { runManagedOperation, observeManagedResult, managedAdmissionDenied, isManagedAdmissionDenied } from '../managed-operation-runner.js';
|
|
1
3
|
import { LispRecoverySession } from './recovery.js';
|
|
2
4
|
import { CodeIntelligenceAdapterV1 } from './code-intelligence.js';
|
|
3
5
|
import { CODE_METHODS } from './code-intelligence-contracts.js';
|
|
@@ -142,6 +144,12 @@ export class LispManager {
|
|
|
142
144
|
for (const session of await this.#store.start())
|
|
143
145
|
this.enabled.set(session.session_id, session.root_path);
|
|
144
146
|
await this.#hot.catalog.expire();
|
|
147
|
+
await this.#store.database(db => {
|
|
148
|
+
const journal = new ManagedOperationJournal(db);
|
|
149
|
+
for (const row of db.prepare(`SELECT scope_id FROM dsh_managed_scopes WHERE json_extract(scope_json,'$.runtimeIdentity') LIKE 'sbcl:%'`).all()) {
|
|
150
|
+
journal.recover(row.scope_id);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
145
153
|
}
|
|
146
154
|
catch (error) {
|
|
147
155
|
await unlink(lockPath);
|
|
@@ -293,21 +301,21 @@ export class LispManager {
|
|
|
293
301
|
if (this.#config.executionMode === 'protected') {
|
|
294
302
|
const canary = join(base, 'host-canary');
|
|
295
303
|
await writeFile(canary, 'protected', { mode: 0o600 });
|
|
296
|
-
const probe = await
|
|
304
|
+
const probe = await this.journalRequest(state, worker, 'eval', { inputs: [], code: `(let ((read-denied (handler-case (progn (with-open-file (s ${JSON.stringify(canary)}) (read-char s)) nil) (file-error () t))) (delete-denied (handler-case (progn (delete-file ${JSON.stringify(canary)}) nil) (file-error () t)))) (unless (and read-denied delete-denied) (error "ISOLATION_FAILED")) :protected)` }, this.#config.startupTimeoutMs, combined);
|
|
297
305
|
if (!probe.ok || await readFile(canary, 'utf8') !== 'protected')
|
|
298
306
|
fail('ISOLATION_FAILED', 'OS によるファイル保護を確認できません。');
|
|
299
307
|
}
|
|
300
308
|
assertCurrent();
|
|
301
309
|
state.state = 'EVALUATING';
|
|
302
310
|
if (mode === 'compile') {
|
|
303
|
-
const checked = await
|
|
311
|
+
const checked = await this.journalRequest(state, worker, 'task-compile', { code }, this.#config.timeoutMs, combined);
|
|
304
312
|
assertCurrent();
|
|
305
313
|
if (!checked.ok || checked.proposals.length)
|
|
306
314
|
fail('TASK_COMPILE_FAILED', String(checked.value).slice(0, 1000));
|
|
307
315
|
return { value: null, output: worker.output(), generation: worker.generation };
|
|
308
316
|
}
|
|
309
317
|
if (mode === 'eval') {
|
|
310
|
-
const evaluated = await
|
|
318
|
+
const evaluated = await this.journalRequest(state, worker, 'eval', { code, inputs: [] }, this.#config.timeoutMs, combined);
|
|
311
319
|
assertCurrent();
|
|
312
320
|
if (!evaluated.ok || evaluated.proposals.length)
|
|
313
321
|
fail('TASK_EVAL_FAILED', String(evaluated.value).slice(0, 1000));
|
|
@@ -321,7 +329,7 @@ export class LispManager {
|
|
|
321
329
|
await writeFile(inputPath, encoded, { flag: 'wx', mode: 0o400 });
|
|
322
330
|
assertCurrent();
|
|
323
331
|
state.state = 'EVALUATING';
|
|
324
|
-
const response = await
|
|
332
|
+
const response = await this.journalRequest(state, worker, 'task', { code, input: inputPath }, this.#config.timeoutMs, combined);
|
|
325
333
|
if (!response.ok || response.proposals.length)
|
|
326
334
|
fail('TASK_EXECUTION_FAILED', String(response.value).slice(0, 1000));
|
|
327
335
|
const result = await snapshot(layout.scratch, 'task-result.json', []);
|
|
@@ -380,7 +388,7 @@ export class LispManager {
|
|
|
380
388
|
layout.compiled = compiled.path;
|
|
381
389
|
layout.workspace = state.owner.root;
|
|
382
390
|
layout.protected = this.#config.executionMode === 'protected';
|
|
383
|
-
worker = new LispWorker(layout, this.#config, (method, args, context) => this.bridge(state, method, args, context), undefined, () => this.taskAuthority.bound(state.execution, async () => { await this.taskAuthority.authorizeEffect(state.owner, this.#config.executionMode === 'protected' ? 'protected' : 'direct'); }));
|
|
391
|
+
worker = new LispWorker(layout, this.#config, (method, args, context) => this.bridge(state, method, args, context), undefined, () => this.taskAuthority.bound(state.execution, async () => { await this.taskAuthority.authorizeEffect(state.owner, this.#config.executionMode === 'protected' ? 'protected' : 'direct'); }), (input, launch) => this.journalProtectedJob(state, input, launch));
|
|
384
392
|
state.worker = worker;
|
|
385
393
|
if (this.#closed || state.state !== 'PREFLIGHT' || abort.signal.aborted)
|
|
386
394
|
fail('CANCELLED', '起動は取り消されています。');
|
|
@@ -390,7 +398,7 @@ export class LispManager {
|
|
|
390
398
|
const canary = join(base, 'host-canary');
|
|
391
399
|
await writeFile(canary, 'protected', { mode: 0o600 });
|
|
392
400
|
const quote = (value) => JSON.stringify(value);
|
|
393
|
-
const probe = await
|
|
401
|
+
const probe = await this.journalRequest(state, worker, 'eval', { inputs: [], code: `(let ((read-denied (handler-case (progn (with-open-file (s ${quote(canary)}) (read-char s)) nil) (file-error () t))) (delete-denied (handler-case (progn (delete-file ${quote(canary)}) nil) (file-error () t)))) (unless (and read-denied delete-denied) (error "ISOLATION_FAILED")) (kioku.files:write-text (merge-pathnames "probe" (kioku.files:scratch)) "ok") :protected)` }, this.#config.startupTimeoutMs);
|
|
394
402
|
if (!probe.ok || await readFile(canary, 'utf8') !== 'protected')
|
|
395
403
|
fail('ISOLATION_FAILED', 'OS によるファイル保護を確認できません。');
|
|
396
404
|
}
|
|
@@ -562,7 +570,7 @@ export class LispManager {
|
|
|
562
570
|
}
|
|
563
571
|
retainOwned(state, value) {
|
|
564
572
|
const receipt = value?.receipt;
|
|
565
|
-
if (receipt && typeof receipt.operationId === 'string' && !(receipt.processStopped === true && ['completed', 'cancelled'].includes(receipt.state ?? '')))
|
|
573
|
+
if (receipt && typeof receipt.operationId === 'string' && !(receipt.processStopped === true && ['completed', 'cancelled'].includes(receipt.state ?? '') || receipt.state === 'denied' && receipt.processStarted === false))
|
|
566
574
|
(state.ownedJobs ??= new Set()).add(receipt.operationId);
|
|
567
575
|
}
|
|
568
576
|
async ownedDispatch(state, action) {
|
|
@@ -606,8 +614,70 @@ export class LispManager {
|
|
|
606
614
|
state.ownedStop = stopping.finally(() => { delete state.ownedStop; });
|
|
607
615
|
return state.ownedStop;
|
|
608
616
|
}
|
|
617
|
+
async journalProtectedJob(state, input, launch) {
|
|
618
|
+
const scope = state.managedScope;
|
|
619
|
+
if (!scope)
|
|
620
|
+
fail('JOURNAL_SCOPE_MISSING', 'Managed evaluation collection is unavailable.');
|
|
621
|
+
await scope.database(db => {
|
|
622
|
+
if (db.prepare(`SELECT 1 FROM dsh_managed_operations o JOIN dsh_managed_scopes s ON s.scope_id=o.scope_id
|
|
623
|
+
WHERE json_extract(s.scope_json,'$.sessionId')=? AND json_extract(o.operation_json,'$.route')='native' AND o.state='unknown' LIMIT 1`).get(state.owner.sessionId)) {
|
|
624
|
+
new ManagedOperationJournal(db).markIncomplete(scope.scopeId);
|
|
625
|
+
fail('JOURNAL_RECONCILE_REQUIRED', 'A previous native operation is unresolved; inspect it before another effect.');
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
const operation = await scope.database(db => new ManagedOperationJournal(db).prepare(scope.scopeId, { route: 'native', kind: 'process', request: { input, environment: { ...process.env }, cwd: state.worker?.layout.scratch, runtime: process.version } }));
|
|
629
|
+
if (!await scope.database(db => new ManagedOperationJournal(db).claim(operation.operationId)))
|
|
630
|
+
fail('JOURNAL_REPLAY', 'Process already dispatched.');
|
|
631
|
+
let job;
|
|
632
|
+
try {
|
|
633
|
+
job = await launch();
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
await scope.database(db => new ManagedOperationJournal(db).transition(operation.operationId, { state: isManagedAdmissionDenied(error) ? 'denied' : 'unknown' }));
|
|
637
|
+
throw error;
|
|
638
|
+
}
|
|
639
|
+
await scope.database(db => new ManagedOperationJournal(db).transition(operation.operationId, { state: 'running' }));
|
|
640
|
+
const done = job.done;
|
|
641
|
+
job.done = done.then(async () => {
|
|
642
|
+
await observeManagedResult({ ...scope, operationId: operation.operationId, kind: 'process' }, {
|
|
643
|
+
code: job.result?.code, receipt: { route: 'native', processStopped: job.settled === true },
|
|
644
|
+
});
|
|
645
|
+
await scope.database(db => new ManagedOperationJournal(db).setDelivery(operation.operationId, 'delivered'));
|
|
646
|
+
});
|
|
647
|
+
// Background completion persists independently of Lisp's final return value.
|
|
648
|
+
void job.done.catch(() => { });
|
|
649
|
+
return job;
|
|
650
|
+
}
|
|
651
|
+
async journalRequest(state, worker, ...args) {
|
|
652
|
+
const lease = state.execution?.lease ?? this.taskAuthority.current()?.lease;
|
|
653
|
+
const scope = await this.#store.database(db => new ManagedOperationJournal(db).createScope({
|
|
654
|
+
...(lease ? { binding: { taskId: lease.taskId, workerGeneration: worker.generation, leaseAuthorityGeneration: lease.generation, leaseRevision: lease.revision } } : {}),
|
|
655
|
+
sessionId: state.owner.sessionId, parentId: randomUUID(), runtimeIdentity: `sbcl:${worker.generation}`,
|
|
656
|
+
}));
|
|
657
|
+
const managedScope = { database: this.#store.database, scopeId: scope.scopeId };
|
|
658
|
+
state.managedScope = managedScope;
|
|
659
|
+
try {
|
|
660
|
+
return await worker.request(...args);
|
|
661
|
+
}
|
|
662
|
+
finally {
|
|
663
|
+
if (state.managedScope === managedScope)
|
|
664
|
+
delete state.managedScope;
|
|
665
|
+
await this.#store.database(db => new ManagedOperationJournal(db).seal(scope.scopeId));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
609
668
|
bridge(state, method, args, context) {
|
|
610
|
-
const pending = this.taskAuthority.bound(state.execution, () =>
|
|
669
|
+
const pending = this.taskAuthority.bound(state.execution, () => {
|
|
670
|
+
const parsed = args;
|
|
671
|
+
const processEffect = ['run', 'start-job', 'ci-verify'].includes(method) || method === 'tool-call' && parsed?.name === 'kioku_exec';
|
|
672
|
+
const file = method === 'tool-call' && ['kioku_write', 'kioku_edit', 'kioku_remove'].includes(parsed?.name ?? '');
|
|
673
|
+
if (!processEffect && !file)
|
|
674
|
+
return this.bridgeBound(state, method, args, context);
|
|
675
|
+
if (!state.managedScope)
|
|
676
|
+
fail('JOURNAL_SCOPE_MISSING', 'Managed evaluation collection is unavailable; no operation was dispatched.');
|
|
677
|
+
const route = method === 'run' && this.taskAuthority.current()?.nativeCommands && this.#config.executionMode === 'development' ? 'native' : 'owned';
|
|
678
|
+
return runManagedOperation(state.managedScope, { route, kind: file ? 'file' : 'process',
|
|
679
|
+
request: { method, args, cwd: state.owner.root, workerGeneration: context.generation, evaluationId: context.evaluationId, rpcId: context.rpcId, environment: { ...process.env }, runtime: process.version } }, () => this.bridgeBound(state, method, args, context));
|
|
680
|
+
});
|
|
611
681
|
if (['run', 'start-job', 'tool-call', 'ci-verify'].includes(method)) {
|
|
612
682
|
(state.ownedCalls ??= new Set()).add(pending);
|
|
613
683
|
const settled = () => { state.ownedCalls?.delete(pending); };
|
|
@@ -745,8 +815,9 @@ export class LispManager {
|
|
|
745
815
|
const active = [...state.active];
|
|
746
816
|
if (active.length !== 1)
|
|
747
817
|
fail('HOST_STATE', 'CI 呼び出しの実行主体を一意に確認できません。');
|
|
818
|
+
// This authority check precedes the CI adapter; a refusal proves no dispatch.
|
|
748
819
|
if (request.kind === 'verify')
|
|
749
|
-
await this.taskAuthority.authorizeEffect(state.owner);
|
|
820
|
+
await this.taskAuthority.authorizeEffect(state.owner).catch(managedAdmissionDenied);
|
|
750
821
|
context.signal.throwIfAborted();
|
|
751
822
|
const result = await this.options.ciCall(state.owner, request, active[0].signal, state.worker.layout.scratch);
|
|
752
823
|
if (request.kind === 'verify')
|
|
@@ -814,6 +885,22 @@ export class LispManager {
|
|
|
814
885
|
}
|
|
815
886
|
return true;
|
|
816
887
|
}
|
|
888
|
+
managedUnresolved(owner) {
|
|
889
|
+
return this.#store.database(db => {
|
|
890
|
+
// Safety decisions use the full set, never the bounded diagnostic page.
|
|
891
|
+
const counts = db.prepare(`SELECT COUNT(*) AS total, COALESCE(SUM(CASE WHEN o.state='unknown' THEN 1 ELSE 0 END),0) AS unknown_count
|
|
892
|
+
FROM dsh_managed_operations o JOIN dsh_managed_scopes s ON s.scope_id=o.scope_id
|
|
893
|
+
WHERE json_extract(s.scope_json,'$.sessionId')=? AND o.state IN ('unknown','dispatching','running','prepared')`)
|
|
894
|
+
.get(owner.sessionId);
|
|
895
|
+
const operations = db.prepare(`SELECT o.operation_json FROM dsh_managed_operations o JOIN dsh_managed_scopes s ON s.scope_id=o.scope_id
|
|
896
|
+
WHERE json_extract(s.scope_json,'$.sessionId')=? AND o.state IN ('unknown','dispatching','running','prepared') ORDER BY o.rowid DESC LIMIT 100`)
|
|
897
|
+
.all(owner.sessionId).map(row => {
|
|
898
|
+
const value = JSON.parse(row.operation_json);
|
|
899
|
+
return { id: value.operationId, scopeId: value.scopeId, route: value.route, kind: value.kind, state: value.state, ...(value.originalRef ? { originalRef: value.originalRef } : {}) };
|
|
900
|
+
});
|
|
901
|
+
return { operations, total: counts.total, unknownCount: counts.unknown_count, truncated: counts.total > operations.length };
|
|
902
|
+
});
|
|
903
|
+
}
|
|
817
904
|
async status(owner, offset) {
|
|
818
905
|
const policy = this.options.questions?.approvalPolicy;
|
|
819
906
|
const approval = { mode: policy?.mode() ?? this.#config.approvalMode, scope: 'profile', writable: policy?.writable() ?? false };
|
|
@@ -821,13 +908,16 @@ export class LispManager {
|
|
|
821
908
|
return { approval, enabled: false, state: 'DISABLED', recovery: '/kioku-lisp enable' };
|
|
822
909
|
const state = this.entry(owner);
|
|
823
910
|
const taskMode = await this.isTaskMode(owner);
|
|
911
|
+
const managed = await this.managedUnresolved(owner);
|
|
912
|
+
const managedOperations = managed.operations;
|
|
913
|
+
const managedReconciliation = managed.unknownCount > 0;
|
|
824
914
|
const unconfirmed = [...this.#agents.values()].find(s => s.owner.sessionId === owner.sessionId && s.state === 'STOP_UNCONFIRMED');
|
|
825
915
|
if (state.state === 'READY' && !state.worker?.healthy)
|
|
826
916
|
this.halted(state, new LispError('WORKER_EXITED', 'Lisp が終了しています。新しい Lisp の起動前に状態を確認してください。'));
|
|
827
917
|
const summary = await this.#store.operationSummaries(owner.sessionId, offset);
|
|
828
918
|
const taskSummary = taskMode ? await this.#store.taskSummary(owner) : undefined;
|
|
829
919
|
const operations = summary.operations.map(o => ({ id: o.operation_id, agent: o.agent_id, kind: o.kind, state: o.state, updatedAt: o.updated_at }));
|
|
830
|
-
return { approval, enabled: true, state: unconfirmed ? 'STOP_UNCONFIRMED' : taskMode && state.state === 'RECOVERY_REQUIRED' && !state.worker ? 'TASK_READY' : state.state,
|
|
920
|
+
return { approval, enabled: true, managedOperations, managedOperationCount: managed.total, managedOperationsTruncated: managed.truncated, managedReconciliationRequired: managedReconciliation, state: managedReconciliation ? 'RECONCILIATION_REQUIRED' : unconfirmed ? 'STOP_UNCONFIRMED' : taskMode && state.state === 'RECOVERY_REQUIRED' && !state.worker ? 'TASK_READY' : state.state,
|
|
831
921
|
generation: state.worker?.generation ?? null, supervisorPid: state.worker?.supervisorPid ?? null, error: unconfirmed?.error ?? (taskMode && !state.worker ? null : state.error ?? null),
|
|
832
922
|
jobs: [...(state.worker?.jobStatus() ?? []), ...[...state.ownedJobs ?? []].map(operationId => ({ operationId, owner: 'kiokuko-execution' }))],
|
|
833
923
|
executionMode: this.#config.executionMode,
|
|
@@ -838,14 +928,21 @@ export class LispManager {
|
|
|
838
928
|
...(taskSummary ? { task: taskSummary } : {}),
|
|
839
929
|
hot: await this.#hot.status(owner),
|
|
840
930
|
...(offset === undefined ? {} : { operationCount: summary.count, pendingCount: Object.values(summary.pendingStates).reduce((a, b) => a + b, 0), pendingStates: summary.pendingStates, offset, nextOffset: offset + 10 < summary.count ? offset + 10 : null }),
|
|
841
|
-
recovery: unconfirmed ? '停止と操作記録を照合してください。自動再実行しません。' : taskMode && !state.worker ? null : state.state === 'SUSPENDED' ? 'Lisp は休止中です。次の利用時に自動起動します。変数・関数定義は保持されません。' : state.state === 'READY' ? null : '停止理由と操作履歴を確認し、/kioku-lisp recover を実行してください。' };
|
|
931
|
+
recovery: managedReconciliation ? 'Managed operations remain unresolved. Inspect the listed operation IDs and original receipts; restarting or abandoning Lisp does not reconcile external effects.' : unconfirmed ? '停止と操作記録を照合してください。自動再実行しません。' : taskMode && !state.worker ? null : state.state === 'SUSPENDED' ? 'Lisp は休止中です。次の利用時に自動起動します。変数・関数定義は保持されません。' : state.state === 'READY' ? null : '停止理由と操作履歴を確認し、/kioku-lisp recover を実行してください。' };
|
|
842
932
|
}
|
|
843
933
|
async diagnostics(owner, id) {
|
|
844
934
|
this.entry(owner);
|
|
845
935
|
if (id) {
|
|
846
936
|
const operation = await this.#store.get(owner, identifier.parse(id));
|
|
847
|
-
if (!operation)
|
|
937
|
+
if (!operation) {
|
|
938
|
+
const managed = await this.#store.database(db => db.prepare(`SELECT o.operation_json FROM dsh_managed_operations o JOIN dsh_managed_scopes s ON s.scope_id=o.scope_id
|
|
939
|
+
WHERE o.operation_id=? AND json_extract(s.scope_json,'$.sessionId')=?`).get(id, owner.sessionId));
|
|
940
|
+
if (managed) {
|
|
941
|
+
const value = JSON.parse(managed.operation_json);
|
|
942
|
+
return { operationId: value.operationId, scopeId: value.scopeId, parentId: value.parentId, route: value.route, kind: value.kind, state: value.state, originalRef: value.originalRef ?? null, cause: value.cause ?? null, delivery: value.delivery };
|
|
943
|
+
}
|
|
848
944
|
fail('UNKNOWN_OPERATION', 'この主体の操作記録がありません。');
|
|
945
|
+
}
|
|
849
946
|
return { ...operation, payload: JSON.parse(operation.payload), result: operation.result ? JSON.parse(operation.result) : null };
|
|
850
947
|
}
|
|
851
948
|
const operations = await this.#store.operations(owner.sessionId);
|
|
@@ -1257,7 +1354,7 @@ export class LispManager {
|
|
|
1257
1354
|
reserved = true;
|
|
1258
1355
|
if (tool === 'lisp_eval')
|
|
1259
1356
|
state.currentVerification = { operationId: id, generation: worker.generation, results: [] };
|
|
1260
|
-
const response = await
|
|
1357
|
+
const response = await this.journalRequest(state, worker, tool === 'lisp_eval' ? 'eval' : tool === 'lisp_describe' ? 'describe' : 'inspect', args, timeout, combined);
|
|
1261
1358
|
const result = { ok: response.ok, operationId: id, value: response.value, output: worker.output(), generation: worker.generation, proposals: response.proposals };
|
|
1262
1359
|
evidence = { ...result, state: response.ok ? 'RUNNING' : 'FAILED' };
|
|
1263
1360
|
await this.#store.transition(owner, id, ['RUNNING'], response.ok ? 'RUNNING' : 'FAILED', evidence);
|
|
@@ -1413,6 +1510,10 @@ export class LispManager {
|
|
|
1413
1510
|
});
|
|
1414
1511
|
}
|
|
1415
1512
|
async recoverBound(owner, signal) {
|
|
1513
|
+
const managed = await this.managedUnresolved(owner);
|
|
1514
|
+
if (managed.unknownCount > 0)
|
|
1515
|
+
return { ok: false, code: 'RECONCILIATION_REQUIRED',
|
|
1516
|
+
message: 'External operation results remain unknown. Inspect the listed originals. Native results without a verifiable host receipt cannot be cleared by restarting Lisp; no command was retried.', managedOperations: managed.operations, managedOperationCount: managed.total, managedOperationsTruncated: managed.truncated };
|
|
1416
1517
|
if (await this.isTaskMode(owner)) {
|
|
1417
1518
|
await this.stopTaskWorkers(owner.sessionId);
|
|
1418
1519
|
await Promise.allSettled([...this.#executions].filter(([, session]) => session === owner.sessionId).map(([promise]) => promise));
|