kiokuko-dsh 0.2.26 → 0.2.28

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.
Files changed (99) hide show
  1. package/dist/context/replay-model-memory.d.ts +2 -2
  2. package/dist/context/replay-model-memory.d.ts.map +1 -1
  3. package/dist/context/replay-model-memory.js +70 -16
  4. package/dist/context/replay-model-memory.js.map +1 -1
  5. package/dist/dsh/agenticreplay-host.d.ts.map +1 -1
  6. package/dist/dsh/agenticreplay-host.js +5 -1
  7. package/dist/dsh/agenticreplay-host.js.map +1 -1
  8. package/dist/dsh/agenticreplay-libraries.d.ts +1 -0
  9. package/dist/dsh/agenticreplay-libraries.d.ts.map +1 -1
  10. package/dist/dsh/agenticreplay-libraries.js.map +1 -1
  11. package/dist/dsh/agenticreplay-recorder.d.ts.map +1 -1
  12. package/dist/dsh/agenticreplay-recorder.js +22 -10
  13. package/dist/dsh/agenticreplay-recorder.js.map +1 -1
  14. package/dist/dsh/agenticreplay-security.d.ts.map +1 -1
  15. package/dist/dsh/agenticreplay-security.js +40 -6
  16. package/dist/dsh/agenticreplay-security.js.map +1 -1
  17. package/dist/dsh/agenticreplay-types.d.ts +3 -0
  18. package/dist/dsh/agenticreplay-types.d.ts.map +1 -1
  19. package/dist/dsh/agenticreplay-types.js.map +1 -1
  20. package/dist/dsh/coding-workflow/host.d.ts +1 -0
  21. package/dist/dsh/coding-workflow/host.d.ts.map +1 -1
  22. package/dist/dsh/coding-workflow/host.js +10 -0
  23. package/dist/dsh/coding-workflow/host.js.map +1 -1
  24. package/dist/dsh/coding-workflow/service.d.ts +6 -2
  25. package/dist/dsh/coding-workflow/service.d.ts.map +1 -1
  26. package/dist/dsh/coding-workflow/service.js +6 -5
  27. package/dist/dsh/coding-workflow/service.js.map +1 -1
  28. package/dist/dsh/core/host.d.ts.map +1 -1
  29. package/dist/dsh/core/host.js +10 -1
  30. package/dist/dsh/core/host.js.map +1 -1
  31. package/dist/dsh/execution-support.d.ts.map +1 -1
  32. package/dist/dsh/execution-support.js +2 -0
  33. package/dist/dsh/execution-support.js.map +1 -1
  34. package/dist/dsh/host-adapter/lifecycle.d.ts +20 -18
  35. package/dist/dsh/host-adapter/lifecycle.d.ts.map +1 -1
  36. package/dist/dsh/host-adapter/lifecycle.js +298 -102
  37. package/dist/dsh/host-adapter/lifecycle.js.map +1 -1
  38. package/dist/dsh/host-adapter.d.ts +47 -47
  39. package/dist/dsh/host-adapter.d.ts.map +1 -1
  40. package/dist/dsh/host-adapter.js +1213 -592
  41. package/dist/dsh/host-adapter.js.map +1 -1
  42. package/dist/dsh/index.d.ts +42 -41
  43. package/dist/dsh/index.d.ts.map +1 -1
  44. package/dist/dsh/index.js +166 -92
  45. package/dist/dsh/index.js.map +1 -1
  46. package/dist/dsh/lifecycle-memory.d.ts +12 -7
  47. package/dist/dsh/lifecycle-memory.d.ts.map +1 -1
  48. package/dist/dsh/lifecycle-memory.js +606 -172
  49. package/dist/dsh/lifecycle-memory.js.map +1 -1
  50. package/dist/dsh/memory-application.d.ts +9 -9
  51. package/dist/dsh/memory-application.d.ts.map +1 -1
  52. package/dist/dsh/memory-application.js +448 -147
  53. package/dist/dsh/memory-application.js.map +1 -1
  54. package/dist/dsh/on-demand-intake.d.ts +13 -0
  55. package/dist/dsh/on-demand-intake.d.ts.map +1 -1
  56. package/dist/dsh/on-demand-intake.js +30 -7
  57. package/dist/dsh/on-demand-intake.js.map +1 -1
  58. package/dist/dsh/repository-learning-reflector.d.ts +58 -0
  59. package/dist/dsh/repository-learning-reflector.d.ts.map +1 -0
  60. package/dist/dsh/repository-learning-reflector.js +230 -0
  61. package/dist/dsh/repository-learning-reflector.js.map +1 -0
  62. package/dist/dsh/repository-learning.d.ts +34 -0
  63. package/dist/dsh/repository-learning.d.ts.map +1 -0
  64. package/dist/dsh/repository-learning.js +512 -0
  65. package/dist/dsh/repository-learning.js.map +1 -0
  66. package/dist/dsh/task-completion.d.ts +7 -7
  67. package/dist/dsh/task-completion.d.ts.map +1 -1
  68. package/dist/dsh/task-completion.js +554 -194
  69. package/dist/dsh/task-completion.js.map +1 -1
  70. package/dist/dsh/task-state-host.d.ts +10 -10
  71. package/dist/dsh/task-state-host.d.ts.map +1 -1
  72. package/dist/dsh/task-state-host.js +337 -145
  73. package/dist/dsh/task-state-host.js.map +1 -1
  74. package/dist/index.js +1 -0
  75. package/dist/locale/en.json +1 -1
  76. package/dist/locale/ja.json +1 -1
  77. package/dist/locale/ko.json +1 -1
  78. package/dist/locale/zh-CN.json +1 -1
  79. package/dist/memory/forget.d.ts +2 -2
  80. package/dist/memory/forget.d.ts.map +1 -1
  81. package/dist/memory/forget.js +175 -74
  82. package/dist/memory/forget.js.map +1 -1
  83. package/dist/memory/replay-reflection.d.ts +94 -0
  84. package/dist/memory/replay-reflection.d.ts.map +1 -0
  85. package/dist/memory/replay-reflection.js +149 -0
  86. package/dist/memory/replay-reflection.js.map +1 -0
  87. package/dist/memory/replay-review.d.ts +18 -12
  88. package/dist/memory/replay-review.d.ts.map +1 -1
  89. package/dist/memory/replay-review.js +107 -46
  90. package/dist/memory/replay-review.js.map +1 -1
  91. package/dist/memory/repository-learning.d.ts +106 -0
  92. package/dist/memory/repository-learning.d.ts.map +1 -0
  93. package/dist/memory/repository-learning.js +348 -0
  94. package/dist/memory/repository-learning.js.map +1 -0
  95. package/docs/agenticreplay-recording.md +20 -2
  96. package/docs/on-demand-intake.md +8 -2
  97. package/docs/repository-learning.md +109 -0
  98. package/migrations/048_repository_learning.sql +65 -0
  99. package/package.json +6 -1
@@ -1,147 +1,147 @@
1
- import { assessRequestIntent } from './decisions/intent-assessment.js';
2
- import { nativeExecutionOwnership } from './native-execution-ownership.js';
3
- import { NativeTaskAuthority } from './native-task-authority.js';
4
- import { readOwnedIdentity } from './owned-read-owner.js';
5
- import { NativeWorkerRouting } from './native-worker-routing.js';
6
- import { validateHeadWorker } from './head-worker-configuration.js';
7
- import { getHeadWorkerSessionSelection, clearHeadWorkerForSession, updateHeadWorkerEffortForSession } from './models/session-selection.js';
8
- import { answerSkillContext } from './answer-skills.js';
9
- import { DshAnswerContext } from './answer-context.js';
10
- import { IntakeModeConfig } from './intake-mode.js';
11
- import { OnDemandIntake } from './on-demand-intake.js';
12
- import { LISP_ASSEMBLY_SERVICE } from './lisp-service-key.js';
13
- import { DshTaskWorkflow, TASK_STATE_EVENT, TASK_WORKFLOW_SERVICE } from './task-state-host.js';
14
- import { mountOwnedExecution } from './owned-execution.js';
15
- import { mountPlanTransition } from './plan-transition.js';
16
- import { classifyTaskForIntake } from './decisions/workflows.js';
17
- import { classifyRequestIntent, requestIntentMessageRefs } from './decisions/request-intent.js';
18
- import { authorizeTaskLease } from './task-state.js';
19
- import { dshTurnRequestId } from './intake-profile-resolver.js';
20
- import { resolveProjectWorkspaceReadOnly } from '../memory/workspaces.js';
21
- import { MemoryIndexReasoningConfig } from '../memory/index-reasoning/contracts.js';
22
- import { createTurnState } from './host-adapter/turn-state.js';
23
- import { createRouting } from './host-adapter/routing.js';
24
- import { createAdmission } from './host-adapter/admission.js';
25
- import { createSessionObservation } from './host-adapter/session-observation.js';
26
- import { createContextMessages } from './host-adapter/context.js';
27
- import { createToolHost } from './host-adapter/tool-host.js';
28
- import { createBoundaries } from './host-adapter/boundaries.js';
29
- import { isNativeSubagent } from './native-subagent.js';
30
- import { createLifecycle } from './host-adapter/lifecycle.js';
31
- import { mountHostMemoryApplication } from './host-adapter/memory-application-host.js';
32
- import { mountTaskCompletion } from './task-completion-host.js';
33
- import { mountCodingWorkflow } from './coding-workflow/host.js';
34
- import { readCodingWorkflow } from './coding-workflow/store.js';
35
- import { stableLispCapabilities } from './lisp-service-key.js';
36
- import { createEfficiencyHost } from './host-adapter/efficiency-host.js';
37
- import { createMemoryReviewHost } from './host-adapter/memory-review-host.js';
38
- import { createEnnoMemoryHost } from './host-adapter/enno-memory-host.js';
39
- import { createSessionAccess } from './host-adapter/session-access.js';
40
- import { createEvolutionHost } from './host-adapter/evolution-host.js';
41
- import { onNativeEvent, onNativeServiceEvent } from './host-adapter/native-events.js';
42
- import { isKiokukoDshSource, KIOKUKO_DSH_SOURCE_KIND } from './plugin-source.js';
43
- import { SemanticCompactionCoordinator } from './semantic-compaction/coordinator.js';
44
- import { ModelHandoff } from './model-handoff.js';
45
- import { DshLifecycleMemory } from './lifecycle-memory.js';
46
- import { ModelAutoConfig } from './model-auto/contracts.js';
47
- import { ModelAutoCoordinator } from './model-auto/coordinator.js';
48
- import { ModelAutoStore } from './model-auto/store.js';
49
- import { SemanticCompactionConfig } from './semantic-compaction/contracts.js';
50
- import { MemoryReuseConfig } from '../memory/reuse.js';
51
- import { createDecisionService } from './decisions/host.js';
52
- import { createIntakeDiagnosticSink } from './decisions/diagnostics.js';
53
- import { TypedDecisionsConfig } from './decisions/config.js';
54
- import { AnswerReviewCoordinator } from './answer-review/coordinator.js';
55
- import { AnswerReviewConfig } from './answer-review/contracts.js';
56
- import { AutoMemoryReviewCoordinator } from './auto-memory-review.js';
57
- import { MemoryReviewConfig } from '../memory/review/contracts.js';
58
- import { MemoryRetrievalConfig } from '../memory/retrieval-contracts.js';
59
- import { DshEnnoMemoryRefresh } from './enno-memory-refresh.js';
60
- import { EnnoMemoryConfig } from './config.js';
61
- import { CompletionConfig } from './task-completion.js';
62
- import { saveSessionNotice } from './plugin-records.js';
63
- import { MemoryEvolutionConfig } from '../memory/evolution/contracts.js';
64
- import { AgenticReplayConfig, EfficiencyConfig, FinalizationConfig, AkinatorMemoryConfig, ContinuityConfig } from './config.js';
65
- import { readExecutionSelection, writeExecutionSelection } from './execution-selection.js';
66
- import { LISP_CODING_SERVICE } from './lisp/coding-choice.js';
67
- import { DshSkillPrompts } from './skill-prompts.js';
68
- import { nativeModelCatalog } from './native-model-catalog.js';
69
- import { DshEnnoDelegation } from './enno-delegation.js';
70
- import { createDshAgenticReplayHost } from './agenticreplay-host.js';
71
- import { fileURLToPath } from 'node:url';
72
- import { realpathSync } from 'node:fs';
73
- import { KIOKUKO_DSH_HOST_SERVICE } from './composition.js';
74
- import { DshRuntime } from './runtime.js';
75
- import { DshToolPolicy } from './tool-policy.js';
76
- import { ToolExposureConfig } from './tool-exposure.js';
77
- import { DiffReviewConfig } from './config.js';
78
- import { DiffReviewController } from '../diff-review/controller.js';
79
- import { DshMemoryFinalizer } from './session-memory-finalizer.js';
80
- import { DshPonytailModes } from './commands.js';
81
- import { createDshConfirmationAnswerer } from './user-interaction.js';
82
- import { createDshCapabilityCatalog } from './capability-catalog.js';
83
- import { STANDARD_SKILL_MANIFESTS } from './standard-skills.js';
84
- import { canonicalContentHash, compareCanonicalStrings } from '../serialization/validate.js';
85
- import { KiokukoError } from '../errors.js';
86
- import { stateForSnapshot } from '../enno-oduno/service.js';
87
- import { readEnnoSnapshot } from '../enno-oduno/store.js';
88
- import { DeepPlanningController } from '../deep-thinker/controller.js';
89
- import { DshSessionLogMirror } from './session-log-mirror.js';
90
- import { DshExecutionSupport } from './execution-support.js';
1
+ import { assessRequestIntent } from "./decisions/intent-assessment.js";
2
+ import { nativeExecutionOwnership } from "./native-execution-ownership.js";
3
+ import { NativeTaskAuthority } from "./native-task-authority.js";
4
+ import { readOwnedIdentity } from "./owned-read-owner.js";
5
+ import { NativeWorkerRouting } from "./native-worker-routing.js";
6
+ import { validateHeadWorker } from "./head-worker-configuration.js";
7
+ import { getHeadWorkerSessionSelection, clearHeadWorkerForSession, updateHeadWorkerEffortForSession, } from "./models/session-selection.js";
8
+ import { answerSkillContext, } from "./answer-skills.js";
9
+ import { DshAnswerContext } from "./answer-context.js";
10
+ import { IntakeModeConfig } from "./intake-mode.js";
11
+ import { OnDemandIntake } from "./on-demand-intake.js";
12
+ import { LISP_ASSEMBLY_SERVICE } from "./lisp-service-key.js";
13
+ import { DshTaskWorkflow, TASK_STATE_EVENT, TASK_WORKFLOW_SERVICE, } from "./task-state-host.js";
14
+ import { mountOwnedExecution } from "./owned-execution.js";
15
+ import { mountPlanTransition } from "./plan-transition.js";
16
+ import { classifyTaskForIntake } from "./decisions/workflows.js";
17
+ import { classifyRequestIntent, requestIntentMessageRefs, } from "./decisions/request-intent.js";
18
+ import { authorizeTaskLease } from "./task-state.js";
19
+ import { dshTurnRequestId } from "./intake-profile-resolver.js";
20
+ import { resolveProjectWorkspaceReadOnly } from "../memory/workspaces.js";
21
+ import { MemoryIndexReasoningConfig } from "../memory/index-reasoning/contracts.js";
22
+ import { createTurnState, } from "./host-adapter/turn-state.js";
23
+ import { createRouting } from "./host-adapter/routing.js";
24
+ import { createAdmission } from "./host-adapter/admission.js";
25
+ import { createSessionObservation } from "./host-adapter/session-observation.js";
26
+ import { createContextMessages } from "./host-adapter/context.js";
27
+ import { createToolHost } from "./host-adapter/tool-host.js";
28
+ import { createBoundaries } from "./host-adapter/boundaries.js";
29
+ import { isNativeSubagent } from "./native-subagent.js";
30
+ import { createLifecycle } from "./host-adapter/lifecycle.js";
31
+ import { mountHostMemoryApplication } from "./host-adapter/memory-application-host.js";
32
+ import { mountTaskCompletion } from "./task-completion-host.js";
33
+ import { mountCodingWorkflow } from "./coding-workflow/host.js";
34
+ import { readCodingWorkflow } from "./coding-workflow/store.js";
35
+ import { stableLispCapabilities } from "./lisp-service-key.js";
36
+ import { createEfficiencyHost } from "./host-adapter/efficiency-host.js";
37
+ import { createMemoryReviewHost } from "./host-adapter/memory-review-host.js";
38
+ import { createEnnoMemoryHost } from "./host-adapter/enno-memory-host.js";
39
+ import { createSessionAccess } from "./host-adapter/session-access.js";
40
+ import { createEvolutionHost } from "./host-adapter/evolution-host.js";
41
+ import { onNativeEvent, onNativeServiceEvent, } from "./host-adapter/native-events.js";
42
+ import { isKiokukoDshSource, KIOKUKO_DSH_SOURCE_KIND, } from "./plugin-source.js";
43
+ import { SemanticCompactionCoordinator } from "./semantic-compaction/coordinator.js";
44
+ import { ModelHandoff } from "./model-handoff.js";
45
+ import { DshLifecycleMemory } from "./lifecycle-memory.js";
46
+ import { ModelAutoConfig } from "./model-auto/contracts.js";
47
+ import { ModelAutoCoordinator } from "./model-auto/coordinator.js";
48
+ import { ModelAutoStore } from "./model-auto/store.js";
49
+ import { SemanticCompactionConfig } from "./semantic-compaction/contracts.js";
50
+ import { MemoryReuseConfig } from "../memory/reuse.js";
51
+ import { createDecisionService } from "./decisions/host.js";
52
+ import { createIntakeDiagnosticSink } from "./decisions/diagnostics.js";
53
+ import { TypedDecisionsConfig } from "./decisions/config.js";
54
+ import { AnswerReviewCoordinator } from "./answer-review/coordinator.js";
55
+ import { AnswerReviewConfig } from "./answer-review/contracts.js";
56
+ import { AutoMemoryReviewCoordinator, } from "./auto-memory-review.js";
57
+ import { MemoryReviewConfig } from "../memory/review/contracts.js";
58
+ import { MemoryRetrievalConfig } from "../memory/retrieval-contracts.js";
59
+ import { DshEnnoMemoryRefresh } from "./enno-memory-refresh.js";
60
+ import { EnnoMemoryConfig } from "./config.js";
61
+ import { CompletionConfig } from "./task-completion.js";
62
+ import { saveSessionNotice } from "./plugin-records.js";
63
+ import { MemoryEvolutionConfig, } from "../memory/evolution/contracts.js";
64
+ import { AgenticReplayConfig, EfficiencyConfig, FinalizationConfig, AkinatorMemoryConfig, ContinuityConfig, } from "./config.js";
65
+ import { readExecutionSelection, writeExecutionSelection, } from "./execution-selection.js";
66
+ import { LISP_CODING_SERVICE, } from "./lisp/coding-choice.js";
67
+ import { DshSkillPrompts } from "./skill-prompts.js";
68
+ import { nativeModelCatalog } from "./native-model-catalog.js";
69
+ import { DshEnnoDelegation } from "./enno-delegation.js";
70
+ import { createDshAgenticReplayHost } from "./agenticreplay-host.js";
71
+ import { fileURLToPath } from "node:url";
72
+ import { realpathSync } from "node:fs";
73
+ import { KIOKUKO_DSH_HOST_SERVICE, } from "./composition.js";
74
+ import { DshRuntime } from "./runtime.js";
75
+ import { DshToolPolicy } from "./tool-policy.js";
76
+ import { ToolExposureConfig, } from "./tool-exposure.js";
77
+ import { DiffReviewConfig } from "./config.js";
78
+ import { DiffReviewController } from "../diff-review/controller.js";
79
+ import { DshMemoryFinalizer, } from "./session-memory-finalizer.js";
80
+ import { DshPonytailModes } from "./commands.js";
81
+ import { createDshConfirmationAnswerer, } from "./user-interaction.js";
82
+ import { createDshCapabilityCatalog, } from "./capability-catalog.js";
83
+ import { STANDARD_SKILL_MANIFESTS } from "./standard-skills.js";
84
+ import { canonicalContentHash, compareCanonicalStrings, } from "../serialization/validate.js";
85
+ import { KiokukoError } from "../errors.js";
86
+ import { stateForSnapshot } from "../enno-oduno/service.js";
87
+ import { readEnnoSnapshot } from "../enno-oduno/store.js";
88
+ import { DeepPlanningController } from "../deep-thinker/controller.js";
89
+ import { DshSessionLogMirror, } from "./session-log-mirror.js";
90
+ import { DshExecutionSupport } from "./execution-support.js";
91
91
  function sessionEventSource(value) {
92
92
  const source = value;
93
- if (typeof source?.snapshotEvents !== 'function') {
94
- throw new KiokukoError('INTEGRITY_ERROR', 'The exact native DSH session event source is unavailable');
93
+ if (typeof source?.snapshotEvents !== "function") {
94
+ throw new KiokukoError("INTEGRITY_ERROR", "The exact native DSH session event source is unavailable");
95
95
  }
96
96
  return source;
97
97
  }
98
98
  function textFromMessages(messages, fallback) {
99
99
  const userTexts = [];
100
100
  for (const value of messages) {
101
- if (typeof value !== 'object' || value === null || Array.isArray(value))
101
+ if (typeof value !== "object" || value === null || Array.isArray(value))
102
102
  continue;
103
103
  const message = value;
104
- if (message.role !== undefined && message.role !== 'user')
104
+ if (message.role !== undefined && message.role !== "user")
105
105
  continue;
106
106
  const source = message.source;
107
- const sourceKind = typeof source === 'object' && source !== null && !Array.isArray(source)
107
+ const sourceKind = typeof source === "object" && source !== null && !Array.isArray(source)
108
108
  ? source.kind
109
109
  : undefined;
110
110
  // File/session context and other host instructions may intentionally use
111
111
  // the user role so the model sees them. They are still not the human's
112
112
  // request and must not influence intake classification or task identity.
113
113
  // Only messages carrying explicit user provenance are the human's task.
114
- if (sourceKind !== 'user')
114
+ if (sourceKind !== "user")
115
115
  continue;
116
116
  const content = message.content;
117
117
  if (!Array.isArray(content))
118
118
  continue;
119
119
  for (const block of content) {
120
- if (typeof block !== 'object' || block === null || Array.isArray(block))
120
+ if (typeof block !== "object" || block === null || Array.isArray(block))
121
121
  continue;
122
122
  const text = block.text;
123
- if (typeof text !== 'string' || text.length === 0)
123
+ if (typeof text !== "string" || text.length === 0)
124
124
  continue;
125
125
  userTexts.push(text);
126
126
  }
127
127
  }
128
- const task = userTexts.join('\n').trim();
128
+ const task = userTexts.join("\n").trim();
129
129
  if (task.length === 0) {
130
130
  if (fallback !== undefined && fallback.trim().length > 0)
131
131
  return fallback;
132
- throw new Error('dsh pre-step did not contain a user task');
132
+ throw new Error("dsh pre-step did not contain a user task");
133
133
  }
134
134
  return task;
135
135
  }
136
136
  function objectRecord(value) {
137
- return typeof value === 'object' && value !== null && !Array.isArray(value)
137
+ return typeof value === "object" && value !== null && !Array.isArray(value)
138
138
  ? value
139
139
  : undefined;
140
140
  }
141
141
  function isHumanMessage(value) {
142
142
  const message = objectRecord(value);
143
143
  const source = objectRecord(message?.source);
144
- return source?.kind === 'user';
144
+ return source?.kind === "user";
145
145
  }
146
146
  const CONTINUATION_ID = /^[0-9a-f]{64}$/u;
147
147
  export function pluginContinuationId(value) {
@@ -150,43 +150,54 @@ export function pluginContinuationId(value) {
150
150
  if (!isKiokukoDshSource(source))
151
151
  return undefined;
152
152
  const messageId = message?.id;
153
- if (source.form === 'instructions' && typeof messageId === 'string' && CONTINUATION_ID.test(messageId)) {
153
+ if (source.form === "instructions" &&
154
+ typeof messageId === "string" &&
155
+ CONTINUATION_ID.test(messageId)) {
154
156
  return messageId;
155
157
  }
156
- if ((source.form !== 'continuation' && source.form !== 'loop-recovery' && source.form !== 'instructions')
157
- || typeof source.deliveryId !== 'string' || !CONTINUATION_ID.test(source.deliveryId))
158
+ if ((source.form !== "continuation" &&
159
+ source.form !== "loop-recovery" &&
160
+ source.form !== "instructions") ||
161
+ typeof source.deliveryId !== "string" ||
162
+ !CONTINUATION_ID.test(source.deliveryId))
158
163
  return undefined;
159
164
  return source.deliveryId;
160
165
  }
161
166
  function isLoopRecoveryMessage(value) {
162
167
  const source = objectRecord(objectRecord(value)?.source);
163
- return isKiokukoDshSource(source) && source?.form === 'loop-recovery';
168
+ return isKiokukoDshSource(source) && source?.form === "loop-recovery";
164
169
  }
165
170
  export function recoveryMessage(continuationId, answer) {
166
171
  return Object.freeze({
167
172
  id: continuationId,
168
- role: 'user',
169
- content: [{
170
- type: 'text',
173
+ role: "user",
174
+ content: [
175
+ {
176
+ type: "text",
171
177
  text: `The user reviewed the stopped Kiokuko loop and supplied this recovery instruction:\n\n${answer}`,
172
- }],
173
- source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: 'instructions' },
178
+ },
179
+ ],
180
+ source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: "instructions" },
174
181
  });
175
182
  }
176
183
  function boundedMessageText(value) {
177
184
  const content = objectRecord(value)?.content;
178
185
  if (!Array.isArray(content))
179
186
  return undefined;
180
- const block = content.map(objectRecord).find((candidate) => candidate?.type === 'text' && typeof candidate.text === 'string');
181
- return typeof block?.text === 'string' ? block.text.slice(0, 2_000) : undefined;
187
+ const block = content
188
+ .map(objectRecord)
189
+ .find((candidate) => candidate?.type === "text" && typeof candidate.text === "string");
190
+ return typeof block?.text === "string"
191
+ ? block.text.slice(0, 2_000)
192
+ : undefined;
182
193
  }
183
194
  function boundedUtf8Text(value, maximumBytes) {
184
- if (Buffer.byteLength(value, 'utf8') <= maximumBytes)
195
+ if (Buffer.byteLength(value, "utf8") <= maximumBytes)
185
196
  return value;
186
- let result = '';
197
+ let result = "";
187
198
  let bytes = 0;
188
199
  for (const point of value) {
189
- const size = Buffer.byteLength(point, 'utf8');
200
+ const size = Buffer.byteLength(point, "utf8");
190
201
  if (bytes + size > maximumBytes)
191
202
  break;
192
203
  result += point;
@@ -202,24 +213,28 @@ export function eventContinuationId(data) {
202
213
  return pluginContinuationId(record?.message);
203
214
  }
204
215
  export function continuationMessage(continuationId, nextAction) {
205
- const work = nextAction === 'execute_work_unit'
206
- ? 'The current WorkUnit is not accepted unless the latest Enno result says so. Correct or report only that WorkUnit.'
216
+ const work = nextAction === "execute_work_unit"
217
+ ? "The current WorkUnit is not accepted unless the latest Enno result says so. Correct or report only that WorkUnit."
207
218
  : `Continue only the current Kiokuko phase for nextAction=${nextAction}. Do not skip ahead.`;
208
219
  return Object.freeze({
209
220
  id: continuationId,
210
- role: 'user',
211
- content: [{ type: 'text', text: work }],
212
- source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: 'instructions' },
221
+ role: "user",
222
+ content: [{ type: "text", text: work }],
223
+ source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: "instructions" },
213
224
  });
214
225
  }
215
226
  async function capabilityCatalog(skills, tools, context) {
216
227
  if (skills?.snapshot === undefined || tools?.schemas === undefined) {
217
- throw new Error('kiokuko-dsh requires native Skill and tool snapshots');
228
+ throw new Error("kiokuko-dsh requires native Skill and tool snapshots");
218
229
  }
219
230
  const scope = context.nativeAgent ?? context.agent;
220
- const skillSnapshot = await skills.snapshot({ scope, cwd: context.cwd, signal: context.signal });
231
+ const skillSnapshot = await skills.snapshot({
232
+ scope,
233
+ cwd: context.cwd,
234
+ signal: context.signal,
235
+ });
221
236
  if (skillSnapshot.complete !== true)
222
- throw new Error('kiokuko-dsh native Skill snapshot is incomplete');
237
+ throw new Error("kiokuko-dsh native Skill snapshot is incomplete");
223
238
  // A Skill visible to a user but not model-invocable is not a capability
224
239
  // that can satisfy the model's required route. Treat it as unavailable by
225
240
  // excluding it before the mandatory-catalog check below.
@@ -228,7 +243,13 @@ async function capabilityCatalog(skills, tools, context) {
228
243
  const mandatoryOrder = new Map();
229
244
  STANDARD_SKILL_MANIFESTS.forEach((manifest, index) => mandatoryOrder.set(manifest.name, index));
230
245
  const skillDescriptors = nativeSkills
231
- .map((skill) => ({ kind: 'skill', name: skill.name, ...(skill.description === undefined ? {} : { description: skill.description }) }))
246
+ .map((skill) => ({
247
+ kind: "skill",
248
+ name: skill.name,
249
+ ...(skill.description === undefined
250
+ ? {}
251
+ : { description: skill.description }),
252
+ }))
232
253
  .sort((left, right) => {
233
254
  const leftMandatory = mandatoryOrder.has(left.name);
234
255
  const rightMandatory = mandatoryOrder.has(right.name);
@@ -239,9 +260,18 @@ async function capabilityCatalog(skills, tools, context) {
239
260
  return compareCanonicalStrings(left.name, right.name);
240
261
  });
241
262
  const toolDescriptors = nativeTools
242
- .map((tool) => ({ kind: 'tool', name: tool.name, ...(tool.description === undefined ? {} : { description: tool.description }) }))
263
+ .map((tool) => ({
264
+ kind: "tool",
265
+ name: tool.name,
266
+ ...(tool.description === undefined
267
+ ? {}
268
+ : { description: tool.description }),
269
+ }))
243
270
  .sort((left, right) => compareCanonicalStrings(left.name, right.name));
244
- return createDshCapabilityCatalog({ skills: skillDescriptors, tools: toolDescriptors });
271
+ return createDshCapabilityCatalog({
272
+ skills: skillDescriptors,
273
+ tools: toolDescriptors,
274
+ });
245
275
  }
246
276
  export function createDshHostAdapter(ctx, options = {}) {
247
277
  let skillPrompts = options.skillPrompts ?? new DshSkillPrompts();
@@ -251,15 +281,22 @@ export function createDshHostAdapter(ctx, options = {}) {
251
281
  const reportedToolExposureProjections = new Set();
252
282
  const reportToolExposureFallback = (fallback) => {
253
283
  fallback = `${toolExposureConfig.mode}:${fallback}`;
254
- if (toolExposureConfig.mode === 'full' || reportedToolExposureFallbacks.has(fallback))
284
+ if (toolExposureConfig.mode === "full" ||
285
+ reportedToolExposureFallbacks.has(fallback))
255
286
  return;
256
287
  reportedToolExposureFallbacks.add(fallback);
257
288
  console.warn(`[kiokuko-dsh] [warn] toolExposure left the native surface unchanged: ${fallback}`);
258
289
  };
259
290
  const reportToolExposureProjection = (mode, reason, metrics) => {
260
- if (toolExposureConfig.mode !== 'lean' && toolExposureConfig.mode !== 'auto')
291
+ if (toolExposureConfig.mode !== "lean" &&
292
+ toolExposureConfig.mode !== "auto")
261
293
  return;
262
- const diagnostic = { requestedMode: toolExposureConfig.mode, mode, reason, ...metrics };
294
+ const diagnostic = {
295
+ requestedMode: toolExposureConfig.mode,
296
+ mode,
297
+ reason,
298
+ ...metrics,
299
+ };
263
300
  const key = JSON.stringify(diagnostic);
264
301
  if (reportedToolExposureProjections.has(key))
265
302
  return;
@@ -272,97 +309,174 @@ export function createDshHostAdapter(ctx, options = {}) {
272
309
  const finalizationConfig = FinalizationConfig.parse(options.finalization ?? {});
273
310
  const memoryRetrievalConfig = MemoryRetrievalConfig.parse(options.memoryRetrieval ?? {});
274
311
  const native = ctx;
275
- const skills = native.get('skills', false);
276
- const systemPrompt = native.get('systemPrompt', false);
277
- const tools = native.get('tools', false);
278
- const commands = native.get('commands', false);
279
- const userQuestions = native.get('userQuestions', false);
280
- const sessions = native.get('sessions', false);
281
- const agents = native.get('agents', false);
282
- const attachments = native.get('attachments', false);
283
- const sessionQuery = options.sessionQuery ?? native.get('sessionQuery', false);
284
- const llm = options.llm ?? native.get('llm', false);
312
+ const skills = native.get("skills", false);
313
+ const systemPrompt = native.get("systemPrompt", false);
314
+ const tools = native.get("tools", false);
315
+ const commands = native.get("commands", false);
316
+ const userQuestions = native.get("userQuestions", false);
317
+ const sessions = native.get("sessions", false);
318
+ const agents = native.get("agents", false);
319
+ const attachments = native.get("attachments", false);
320
+ const sessionQuery = options.sessionQuery ??
321
+ native.get("sessionQuery", false);
322
+ const llm = options.llm ?? native.get("llm", false);
285
323
  const reviewConfig = DiffReviewConfig.parse(options.diffReview ?? {});
286
324
  const completionMode = CompletionConfig.parse(options.completion ?? {}).mode;
287
- const advisory = options.advisory ?? native.get('dshAdvisory', false);
288
- const modelCatalog = nativeModelCatalog(native.get('llm', false), native.get('settings', false));
289
- const modelCompatibility = options.modelCompatibility ?? native.get('dshModelCompatibility', false);
325
+ const advisory = options.advisory ??
326
+ native.get("dshAdvisory", false);
327
+ const modelCatalog = nativeModelCatalog(native.get("llm", false), native.get("settings", false));
328
+ const modelCompatibility = options.modelCompatibility ??
329
+ native.get("dshModelCompatibility", false);
290
330
  const selections = new Map();
291
331
  const root = realpathSync(options.repositoryRoot ?? process.cwd());
292
- const runtime = options.runtime ?? new DshRuntime({
293
- repositoryRoot: root,
294
- ...(options.databasePath === undefined ? {} : { databasePath: options.databasePath }),
295
- migrationsDirectory: options.migrationsDirectory ?? fileURLToPath(new URL('../../migrations/', import.meta.url)),
296
- embeddingConfig: { mode: 'off', provider: 'openai-compatible', allowRemote: false, vectorBackend: 'auto', timeoutMs: 30_000, batchSize: 16 },
297
- autoRegisterRepository: true,
298
- ...(options.now === undefined ? {} : { now: options.now }),
299
- });
300
- const diffReview = reviewConfig.enabled ? new DiffReviewController({
301
- runtime,
302
- ...(sessions ? { sessions: sessions } : {}),
303
- ...(native.get('sessionPersistence', false) ? { persistence: native.get('sessionPersistence', false) } : {}),
304
- ...(native.get('subprocess', false) ? { subprocess: native.get('subprocess', false) } : {}),
305
- ...(native.get('workspaceChanges', false) ? { workspaceChanges: native.get('workspaceChanges', false) } : {}),
306
- ...(llm ? { llm } : {}),
307
- ...(modelCatalog ? { catalog: modelCatalog } : {}),
308
- }, reviewConfig) : undefined;
309
- const decisions = options.decisions ?? createDecisionService(ctx, runtime, TypedDecisionsConfig.parse(options.typedDecisions ?? {}), MemoryReuseConfig.parse(options.memoryReuse ?? {}), SemanticCompactionConfig.parse(options.semanticCompaction ?? {}), root);
332
+ const runtime = options.runtime ??
333
+ new DshRuntime({
334
+ repositoryRoot: root,
335
+ ...(options.databasePath === undefined
336
+ ? {}
337
+ : { databasePath: options.databasePath }),
338
+ migrationsDirectory: options.migrationsDirectory ??
339
+ fileURLToPath(new URL("../../migrations/", import.meta.url)),
340
+ embeddingConfig: {
341
+ mode: "off",
342
+ provider: "openai-compatible",
343
+ allowRemote: false,
344
+ vectorBackend: "auto",
345
+ timeoutMs: 30_000,
346
+ batchSize: 16,
347
+ },
348
+ autoRegisterRepository: true,
349
+ ...(options.now === undefined ? {} : { now: options.now }),
350
+ });
351
+ const diffReview = reviewConfig.enabled
352
+ ? new DiffReviewController({
353
+ runtime,
354
+ ...(sessions ? { sessions: sessions } : {}),
355
+ ...(native.get("sessionPersistence", false)
356
+ ? { persistence: native.get("sessionPersistence", false) }
357
+ : {}),
358
+ ...(native.get("subprocess", false)
359
+ ? { subprocess: native.get("subprocess", false) }
360
+ : {}),
361
+ ...(native.get("workspaceChanges", false)
362
+ ? { workspaceChanges: native.get("workspaceChanges", false) }
363
+ : {}),
364
+ ...(llm ? { llm } : {}),
365
+ ...(modelCatalog ? { catalog: modelCatalog } : {}),
366
+ }, reviewConfig)
367
+ : undefined;
368
+ const decisions = options.decisions ??
369
+ createDecisionService(ctx, runtime, TypedDecisionsConfig.parse(options.typedDecisions ?? {}), MemoryReuseConfig.parse(options.memoryReuse ?? {}), SemanticCompactionConfig.parse(options.semanticCompaction ?? {}), root);
310
370
  const modelAutoConfig = ModelAutoConfig.parse(options.modelAutoMode ?? {});
311
371
  const modelAuto = new ModelAutoCoordinator(new ModelAutoStore(runtime, modelAutoConfig.mode, canonicalContentHash(modelAutoConfig)), decisions, modelCatalog, modelAutoConfig);
312
372
  const answerReview = new AnswerReviewCoordinator(runtime, decisions, AnswerReviewConfig.parse(options.answerReview ?? {}));
313
- const semanticCompaction = options.semanticCompactionCoordinator ?? new SemanticCompactionCoordinator(ctx, decisions, root, options.observationPack);
373
+ const semanticCompaction = options.semanticCompactionCoordinator ??
374
+ new SemanticCompactionCoordinator(ctx, decisions, root, options.observationPack);
314
375
  const modelHandoff = new ModelHandoff(ctx, decisions, root, options.modelHandoff);
315
376
  const lifecycleMemory = new DshLifecycleMemory(ctx, runtime, root);
316
- const delegation = new DshEnnoDelegation(runtime, native.get('subagents', false));
317
- const deepPlanning = new DeepPlanningController({ runtime, decisions, ctx: ctx, backend: native.get('subagents', false),
318
- sessions, agents, catalog: modelCatalog, questions: userQuestions, routes: options.modelRoutes ?? [], compatibility: modelCompatibility, sessionQuery, config: options.deepPlanning,
377
+ const delegation = new DshEnnoDelegation(runtime, native.get("subagents", false));
378
+ const deepPlanning = new DeepPlanningController({
379
+ runtime,
380
+ decisions,
381
+ ctx: ctx,
382
+ backend: native.get("subagents", false),
383
+ sessions,
384
+ agents,
385
+ catalog: modelCatalog,
386
+ questions: userQuestions,
387
+ routes: options.modelRoutes ?? [],
388
+ compatibility: modelCompatibility,
389
+ sessionQuery,
390
+ config: options.deepPlanning,
319
391
  capabilities: async (agent, signal) => {
320
- const catalog = await capabilityCatalog(skills, tools, { cwd: root, signal, agent, nativeAgent: agent });
392
+ const catalog = await capabilityCatalog(skills, tools, {
393
+ cwd: root,
394
+ signal,
395
+ agent,
396
+ nativeAgent: agent,
397
+ });
321
398
  return [...catalog.skills, ...catalog.tools];
322
- }, });
323
- const isGenericNativeChild = (agent) => isNativeSubagent(agent) && !delegation.isChild(agent) && !deepPlanning.executor.isChild(agent);
399
+ },
400
+ });
401
+ const isGenericNativeChild = (agent) => isNativeSubagent(agent) &&
402
+ !delegation.isChild(agent) &&
403
+ !deepPlanning.executor.isChild(agent);
324
404
  const childGuardDisposer = tools?.guard((value) => {
325
405
  const execution = value;
326
- return execution.agent ? delegation.toolDenial(execution.agent, execution.name ?? '', execution.arguments) : undefined;
406
+ return execution.agent
407
+ ? delegation.toolDenial(execution.agent, execution.name ?? "", execution.arguments)
408
+ : undefined;
327
409
  });
328
- const childExecutionDisposer = onNativeEvent(ctx, 'tools/execute', async (execution, next) => {
410
+ const childExecutionDisposer = onNativeEvent(ctx, "tools/execute", async (execution, next) => {
329
411
  if (execution.agent && delegation.isChild(execution.agent)) {
330
412
  await delegation.assertCurrent(execution.agent);
331
413
  const denial = delegation.toolDenial(execution.agent, execution.name, execution.arguments);
332
414
  if (denial)
333
- throw new KiokukoError('CONFLICT', denial);
415
+ throw new KiokukoError("CONFLICT", denial);
334
416
  }
335
417
  return next();
336
418
  }, { prepend: true });
337
- const sessionCachePath = options.sessionCachePath
338
- ?? (options.databasePath === undefined ? undefined : `${options.databasePath}.session-cache`);
419
+ const sessionCachePath = options.sessionCachePath ??
420
+ (options.databasePath === undefined
421
+ ? undefined
422
+ : `${options.databasePath}.session-cache`);
339
423
  const sessionMirror = new DshSessionLogMirror({
340
424
  runtime,
341
- ...(sessionCachePath === undefined ? {} : { databasePath: sessionCachePath }),
342
- ...(attachments === undefined ? {} : { readAttachment: attachments.readImage.bind(attachments) }),
425
+ ...(sessionCachePath === undefined
426
+ ? {}
427
+ : { databasePath: sessionCachePath }),
428
+ ...(attachments === undefined
429
+ ? {}
430
+ : { readAttachment: attachments.readImage.bind(attachments) }),
343
431
  ...(options.now === undefined ? {} : { now: options.now }),
344
432
  });
345
- const { finalizationQuery, sessionExport } = createSessionAccess({ native, sessions, sessionQuery, sessionMirror });
346
- const policy = new DshToolPolicy({ phase: 'intake', runId: 'pending', workspace: 'pending', orchestrationId: 'pending', revision: 1, routeEpoch: 0 });
433
+ const { finalizationQuery, sessionExport } = createSessionAccess({
434
+ native,
435
+ sessions,
436
+ sessionQuery,
437
+ sessionMirror,
438
+ });
439
+ const policy = new DshToolPolicy({
440
+ phase: "intake",
441
+ runId: "pending",
442
+ workspace: "pending",
443
+ orchestrationId: "pending",
444
+ revision: 1,
445
+ routeEpoch: 0,
446
+ });
347
447
  const modes = new DshPonytailModes();
348
- const turnState = createTurnState(modes, policy, runId => selections.get(runId));
448
+ const turnState = createTurnState(modes, policy, (runId) => selections.get(runId));
349
449
  const currentSession = turnState.currentSession;
350
450
  const currentForAgentEvent = turnState.currentForAgentEvent;
351
- const executionSupport = new DshExecutionSupport(runtime, { continuity: continuityConfig,
352
- observe: value => efficiencyHost.efficiency?.recordContinuity(value) });
353
- executionSupport.mount({ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
451
+ const executionSupport = new DshExecutionSupport(runtime, {
452
+ continuity: continuityConfig,
453
+ observe: (value) => efficiencyHost.efficiency?.recordContinuity(value),
454
+ });
455
+ executionSupport.mount({
456
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
354
457
  ...(systemPrompt === undefined ? {} : { systemPrompt }),
355
- ...(tools === undefined ? {} : { tools: { guard: tools.guard.bind(tools) } }) });
356
- const ennoMemory = new DshEnnoMemoryRefresh(runtime, EnnoMemoryConfig.parse(options.ennoMemory ?? {}), value => efficiencyHost.efficiency?.recordEnnoMemory(value));
458
+ ...(tools === undefined
459
+ ? {}
460
+ : { tools: { guard: tools.guard.bind(tools) } }),
461
+ });
462
+ const ennoMemory = new DshEnnoMemoryRefresh(runtime, EnnoMemoryConfig.parse(options.ennoMemory ?? {}), (value) => efficiencyHost.efficiency?.recordEnnoMemory(value));
357
463
  const { refreshEnnoMemory } = createEnnoMemoryHost({
358
- ennoMemory, runtime, executionSupport, delegation, getSelection: runId => selections.get(runId),
359
- turnState, currentSession, capabilityCatalog, skills, tools,
464
+ ennoMemory,
465
+ runtime,
466
+ executionSupport,
467
+ delegation,
468
+ getSelection: (runId) => selections.get(runId),
469
+ turnState,
470
+ currentSession,
471
+ capabilityCatalog,
472
+ skills,
473
+ tools,
360
474
  assertTurnStoppingCatalog: (expected, actual) => gate.assertTurnStoppingCatalog(expected, actual),
361
475
  isHumanMessage,
362
476
  });
363
477
  const executionBinding = turnState.executionBinding;
364
478
  const memoryFinalizer = new DshMemoryFinalizer({
365
- onDeepFinalized: sessionId => deepPlanning.deliver(sessionId),
479
+ onDeepFinalized: (sessionId) => deepPlanning.deliver(sessionId),
366
480
  memoryEvolution: evolutionConfig,
367
481
  memoryIndexReasoning: MemoryIndexReasoningConfig.parse(options.memoryIndexReasoning ?? {}),
368
482
  autoGlobalizationEnabled: options.autoGlobalization?.enabled ?? true,
@@ -372,278 +486,464 @@ export function createDshHostAdapter(ctx, options = {}) {
372
486
  ...(llm === undefined ? {} : { llm }),
373
487
  ...(options.now === undefined ? {} : { now: options.now }),
374
488
  });
375
- const autoReview = new AutoMemoryReviewCoordinator({ runtime, mirror: sessionMirror,
376
- config: MemoryReviewConfig.parse(options.memoryReview ?? {}), ...(llm ? { llm } : {}),
489
+ const autoReview = new AutoMemoryReviewCoordinator({
490
+ runtime,
491
+ mirror: sessionMirror,
492
+ config: MemoryReviewConfig.parse(options.memoryReview ?? {}),
493
+ ...(llm ? { llm } : {}),
377
494
  onCapturePolicy: async (sessionId, mode) => {
378
495
  const item = currentSession(sessionId);
379
496
  if (!item)
380
497
  return;
381
- await runtime.withDatabase(db => saveSessionNotice(db, { id: `capture-notice:${item.runId}:${mode}`, runId: item.runId, sessionId, rootPath: item.cwd, kind: 'status', anchorSeq: 0,
382
- text: mode === 'held' ? '保存拒否の可能性を検出したため、この会話の自動メモリ生成を保留しました。/kioku-memory-review exclude session で除外を確定できます。再開する場合は履歴を継承しない新しい会話を開始してください。' : 'この会話の自動メモリ生成を除外しました。保存済み記憶と会話ログは残ります。' }));
498
+ await runtime.withDatabase((db) => saveSessionNotice(db, {
499
+ id: `capture-notice:${item.runId}:${mode}`,
500
+ runId: item.runId,
501
+ sessionId,
502
+ rootPath: item.cwd,
503
+ kind: "status",
504
+ anchorSeq: 0,
505
+ text: mode === "held"
506
+ ? "保存拒否の可能性を検出したため、この会話の自動メモリ生成を保留しました。/kioku-memory-review exclude session で除外を確定できます。再開する場合は履歴を継承しない新しい会話を開始してください。"
507
+ : "この会話の自動メモリ生成を除外しました。保存済み記憶と会話ログは残ります。",
508
+ }));
383
509
  },
384
- onChanged: async (job, result) => { await runtime.withDatabase(db => saveSessionNotice(db, { id: `review-notice:${job.id}`, runId: job.run_id, sessionId: job.session_id, rootPath: root, kind: 'status', text: `記憶を更新しました(追加${result.added}件、更新${result.updated}件)`, anchorSeq: job.end_seq })); },
385
- ...(sessions?.flush ? { flush: session => sessions.flush(session) } : {}), ...(options.now ? { now: options.now } : {}) });
386
- const reviewBinding = (item, session) => ({ workspace: item.workspace, runId: item.runId, session: session, startSeq: 0 });
510
+ onChanged: async (job, result) => {
511
+ await runtime.withDatabase((db) => saveSessionNotice(db, {
512
+ id: `review-notice:${job.id}`,
513
+ runId: job.run_id,
514
+ sessionId: job.session_id,
515
+ rootPath: root,
516
+ kind: "status",
517
+ text: `記憶を更新しました(追加${result.added}件、更新${result.updated}件)`,
518
+ anchorSeq: job.end_seq,
519
+ }));
520
+ },
521
+ ...(sessions?.flush
522
+ ? { flush: (session) => sessions.flush(session) }
523
+ : {}),
524
+ ...(options.now ? { now: options.now } : {}),
525
+ });
526
+ const reviewBinding = (item, session) => ({
527
+ workspace: item.workspace,
528
+ runId: item.runId,
529
+ session: session,
530
+ startSeq: 0,
531
+ });
387
532
  deepPlanning.attachFinalizer(() => memoryFinalizer.kick());
388
- const confirmationAnswerer = userQuestions === undefined ? undefined : createDshConfirmationAnswerer(userQuestions);
533
+ const confirmationAnswerer = userQuestions === undefined
534
+ ? undefined
535
+ : createDshConfirmationAnswerer(userQuestions);
389
536
  const observation = createSessionObservation(runtime);
390
537
  const captureInitialInput = observation.captureInitialInput;
391
538
  let retireSupersededRun;
392
539
  const admission = createAdmission({
393
- native, skills, tools, userQuestions, sessions, agents, deepPlanning, modelCatalog, modelCompatibility,
394
- modelRoutes: options.modelRoutes, now: options.now, runtime, decisions, answerReview,
395
- delegation, executionSupport, ennoMemory, memoryFinalizer, autoReview, sessionMirror,
396
- akinatorMemoryConfig, memoryRetrievalConfig, completionMode, turnState,
397
- getSelection: runId => selections.get(runId), setSelection: (runId, value) => { selections.set(runId, value); },
398
- refreshEnnoMemory, executionBinding, captureInitialInput,
540
+ native,
541
+ skills,
542
+ tools,
543
+ userQuestions,
544
+ sessions,
545
+ agents,
546
+ deepPlanning,
547
+ modelCatalog,
548
+ modelCompatibility,
549
+ modelRoutes: options.modelRoutes,
550
+ now: options.now,
551
+ runtime,
552
+ decisions,
553
+ answerReview,
554
+ delegation,
555
+ executionSupport,
556
+ ennoMemory,
557
+ memoryFinalizer,
558
+ autoReview,
559
+ sessionMirror,
560
+ akinatorMemoryConfig,
561
+ memoryRetrievalConfig,
562
+ completionMode,
563
+ turnState,
564
+ getSelection: (runId) => selections.get(runId),
565
+ setSelection: (runId, value) => {
566
+ selections.set(runId, value);
567
+ },
568
+ refreshEnnoMemory,
569
+ executionBinding,
570
+ captureInitialInput,
399
571
  contextMessages: (event, pending) => contextMessages(event, pending),
400
572
  resolveIdleClose: (agentId, sessionId, nativeSession, nativeAgent) => resolveIdleClose(agentId, sessionId, nativeSession, nativeAgent),
401
573
  retireSupersededRun: (item, status) => {
402
574
  if (retireSupersededRun === undefined)
403
- throw new Error('kiokuko-dsh run lifecycle is unavailable');
575
+ throw new Error("kiokuko-dsh run lifecycle is unavailable");
404
576
  return retireSupersededRun(item, status);
405
577
  },
406
- cancelBoundarySession: sessionId => boundaryWorker.cancelSession(sessionId),
407
- isSelectionBlocked: agent => routing.isSelectionBlocked(agent),
408
- closeTurn: input => runLifecycle.closeTurn(input),
409
- readStateForRun: item => runtime.withDatabase(db => stateForRun(db, item)),
410
- capabilityCatalog, sessionEventSource, objectRecord, isHumanMessage,
411
- textFromMessages, pluginContinuationId, isLoopRecoveryMessage,
578
+ cancelBoundarySession: (sessionId) => boundaryWorker.cancelSession(sessionId),
579
+ isSelectionBlocked: (agent) => routing.isSelectionBlocked(agent),
580
+ closeTurn: (input) => runLifecycle.closeTurn(input),
581
+ readStateForRun: (item) => runtime.withDatabase((db) => stateForRun(db, item)),
582
+ capabilityCatalog,
583
+ sessionEventSource,
584
+ objectRecord,
585
+ isHumanMessage,
586
+ textFromMessages,
587
+ pluginContinuationId,
588
+ isLoopRecoveryMessage,
412
589
  });
413
590
  const gate = admission.gate;
414
591
  const mapPreStep = admission.mapPreStep;
415
592
  const detachedDemandSessions = new Set();
416
593
  // Archive/session-query adapters own no live execution ingress. A partial live
417
594
  // tool/agent plane is not that read-only case and must not silently downgrade.
418
- const conversationFirst = IntakeModeConfig.parse(options.intakeMode) === 'on-demand';
595
+ const conversationFirst = IntakeModeConfig.parse(options.intakeMode) === "on-demand";
419
596
  const hasExecutionIngress = tools !== undefined || agents !== undefined;
420
- const hasDemandTools = typeof objectRecord(tools)?.get === 'function' && typeof tools?.guard === 'function' && typeof tools?.register === 'function';
421
- if (conversationFirst && hasExecutionIngress && (!hasDemandTools || !agents || !sessions)) {
422
- throw new Error('Conversation-first execution requires native tools, agents and sessions; read-only history adapters must not expose a partial execution plane');
597
+ const hasDemandTools = typeof objectRecord(tools)?.get === "function" &&
598
+ typeof tools?.guard === "function" &&
599
+ typeof tools?.register === "function";
600
+ if (conversationFirst &&
601
+ hasExecutionIngress &&
602
+ (!hasDemandTools || !agents || !sessions)) {
603
+ throw new Error("Conversation-first execution requires native tools, agents and sessions; read-only history adapters must not expose a partial execution plane");
423
604
  }
424
605
  const answerCwd = (agent) => {
425
606
  const session = agent.session;
426
- if (!session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session
427
- || typeof session.header?.cwd !== 'string' || !session.header.cwd)
428
- throw new Error('On-demand native identity mismatch');
607
+ if (!session ||
608
+ agents?.get(agent.id) !== agent ||
609
+ sessions?.get(session.id) !== session ||
610
+ typeof session.header?.cwd !== "string" ||
611
+ !session.header.cwd)
612
+ throw new Error("On-demand native identity mismatch");
429
613
  return realpathSync(session.header.cwd);
430
614
  };
431
- const demand = hasDemandTools && agents && sessions ? new OnDemandIntake({
432
- diagnostic: createIntakeDiagnosticSink(runtime),
433
- assess: (input, context, decision) => assessRequestIntent(decisions, dshTurnRequestId({ dshSessionId: input.agent.session.id, turn: input.turn }), context, decision, input.signal),
434
- ...(userQuestions ? { questions: userQuestions } : {}),
435
- answerContext: new DshAnswerContext(runtime, { root, cwd: answerCwd, projectOnly: false, memoryRetrieval: memoryRetrievalConfig,
436
- instructions: (input, task, taskType) => answerSkillContext(input, task, taskType, { skills: skills, prompts: skillPrompts, decisions, cwd: answerCwd(input.agent) }),
437
- }),
438
- prepareNativeCoding: async (input, task, requestIntentContext) => {
439
- const lisp = native.get(LISP_CODING_SERVICE, false);
440
- const sessionId = input.agent.session?.id;
441
- if (!lisp?.prepareNative || !sessionId)
442
- return;
443
- const requestIntent = requestIntentContext
444
- ? await classifyRequestIntent(decisions, dshTurnRequestId({ dshSessionId: sessionId, turn: input.turn }), requestIntentContext, input.signal)
445
- : undefined;
446
- await lisp.prepareNative({ agent: input.agent, turn: input.turn, task, taskType: null, signal: input.signal,
447
- ...(requestIntent ? { requestIntent } : {}) });
448
- },
449
- nativeOwnership: async (input) => {
450
- const agent = input.agent;
451
- answerCwd(agent);
452
- const session = agent.session;
453
- if (!session?.header)
454
- throw new Error('Native ownership requires the current session header');
455
- const header = session.header;
456
- if (header.parentSession || header.isSeeded)
457
- return 'owned';
458
- const jobs = native.get('jobs', false);
459
- if (jobs && jobs.list(session.id).some(job => !['completed', 'killed', 'failed'].includes(job.status)))
460
- return 'owned';
461
- const current = currentSession(session.id);
462
- const ownership = await runtime.withDatabase(db => nativeExecutionOwnership(db, session.id, current?.runId));
463
- input.signal.throwIfAborted();
464
- // Retire only the exact completed in-memory projection proven above.
465
- // Durable history remains intact; no memory lookup or save is involved.
466
- if (ownership === 'unowned' && current && currentSession(session.id) === current)
467
- turnState.releaseRun(current.runId, current.authority);
468
- return ownership;
469
- },
470
- nativeChild: agent => agents?.get(agent.id) === agent && sessions?.get(agent.session?.id ?? '') === agent.session && isNativeSubagent(agent),
471
- validate: async (input) => {
472
- const agent = input.agent, session = agent.session;
473
- answerCwd(agent);
474
- await captureInitialInput(session.id, input.turn, input.messages);
475
- },
476
- advance: async (input) => {
477
- policy.beginTurn(input.agent.session.id, input.turn);
478
- },
479
- resumeConfirmation: async (input) => runtime.withDatabase(async (db) => {
480
- const sessionId = input.agent.session.id;
481
- if (detachedDemandSessions.has(sessionId))
482
- return false;
483
- const current = currentSession(sessionId);
484
- if (current !== undefined) {
485
- if (current.nativeAgent !== input.agent || current.nativeSession !== input.agent.session
486
- || current.turn > input.turn) {
487
- if (process.env.KIOKUKO_INTENT_DEBUG === '1')
488
- console.error('confirmation resume current mismatch', {
489
- turn: input.turn, currentTurn: current.turn, agent: current.nativeAgent === input.agent,
490
- session: current.nativeSession === input.agent.session,
491
- });
615
+ const demand = hasDemandTools && agents && sessions
616
+ ? new OnDemandIntake({
617
+ diagnostic: createIntakeDiagnosticSink(runtime),
618
+ assess: (input, context, decision) => assessRequestIntent(decisions, dshTurnRequestId({
619
+ dshSessionId: input.agent.session.id,
620
+ turn: input.turn,
621
+ }), context, decision, input.signal),
622
+ ...(userQuestions ? { questions: userQuestions } : {}),
623
+ answerContext: new DshAnswerContext(runtime, {
624
+ root,
625
+ cwd: answerCwd,
626
+ projectOnly: false,
627
+ memoryRetrieval: memoryRetrievalConfig,
628
+ instructions: (input, task, taskType) => answerSkillContext(input, task, taskType, {
629
+ skills: skills,
630
+ prompts: skillPrompts,
631
+ decisions,
632
+ cwd: answerCwd(input.agent),
633
+ }),
634
+ }),
635
+ prepareNativeCoding: async (input, task, requestIntentContext) => {
636
+ const lisp = native.get(LISP_CODING_SERVICE, false);
637
+ const sessionId = input.agent.session?.id;
638
+ if (!lisp?.prepareNative || !sessionId)
639
+ return;
640
+ const requestIntent = requestIntentContext
641
+ ? await classifyRequestIntent(decisions, dshTurnRequestId({
642
+ dshSessionId: sessionId,
643
+ turn: input.turn,
644
+ }), requestIntentContext, input.signal)
645
+ : undefined;
646
+ await lisp.prepareNative({
647
+ agent: input.agent,
648
+ turn: input.turn,
649
+ task,
650
+ taskType: null,
651
+ signal: input.signal,
652
+ ...(requestIntent ? { requestIntent } : {}),
653
+ });
654
+ },
655
+ nativeOwnership: async (input) => {
656
+ const agent = input.agent;
657
+ answerCwd(agent);
658
+ const session = agent.session;
659
+ if (!session?.header)
660
+ throw new Error("Native ownership requires the current session header");
661
+ const header = session.header;
662
+ if (header.parentSession || header.isSeeded)
663
+ return "owned";
664
+ const jobs = native.get("jobs", false);
665
+ if (jobs &&
666
+ jobs
667
+ .list(session.id)
668
+ .some((job) => !["completed", "killed", "failed"].includes(job.status)))
669
+ return "owned";
670
+ const current = currentSession(session.id);
671
+ const ownership = await runtime.withDatabase((db) => nativeExecutionOwnership(db, session.id, current?.runId));
672
+ input.signal.throwIfAborted();
673
+ // Retire only the exact completed in-memory projection proven above.
674
+ // Durable history remains intact; no memory lookup or save is involved.
675
+ if (ownership === "unowned" &&
676
+ current &&
677
+ currentSession(session.id) === current)
678
+ turnState.releaseRun(current.runId, current.authority);
679
+ return ownership;
680
+ },
681
+ nativeChild: (agent) => agents?.get(agent.id) === agent &&
682
+ sessions?.get(agent.session?.id ?? "") === agent.session &&
683
+ isNativeSubagent(agent),
684
+ validate: async (input) => {
685
+ const agent = input.agent, session = agent.session;
686
+ answerCwd(agent);
687
+ await captureInitialInput(session.id, input.turn, input.messages);
688
+ },
689
+ advance: async (input) => {
690
+ policy.beginTurn(input.agent.session.id, input.turn);
691
+ },
692
+ resumeConfirmation: async (input) => runtime.withDatabase(async (db) => {
693
+ const sessionId = input.agent.session.id;
694
+ if (detachedDemandSessions.has(sessionId))
492
695
  return false;
696
+ const current = currentSession(sessionId);
697
+ if (current !== undefined) {
698
+ if (current.nativeAgent !== input.agent ||
699
+ current.nativeSession !== input.agent.session ||
700
+ current.turn > input.turn) {
701
+ if (process.env.KIOKUKO_INTENT_DEBUG === "1")
702
+ console.error("confirmation resume current mismatch", {
703
+ turn: input.turn,
704
+ currentTurn: current.turn,
705
+ agent: current.nativeAgent === input.agent,
706
+ session: current.nativeSession === input.agent.session,
707
+ });
708
+ return false;
709
+ }
493
710
  }
494
- }
495
- const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
496
- if (!project)
497
- return false;
498
- const candidates = db.prepare(`SELECT lr.run_id AS runId
711
+ const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
712
+ if (!project)
713
+ return false;
714
+ const candidates = db
715
+ .prepare(`SELECT lr.run_id AS runId
499
716
  FROM ledger_runs AS lr
500
717
  JOIN enno_contracts AS ec ON ec.run_id = lr.run_id
501
718
  WHERE lr.workspace = ? AND lr.dsh_session_id = ? AND lr.status = 'active'
502
719
  AND ec.repository_root = ? AND ec.status = 'needs_confirmation'
503
720
  ORDER BY lr.created_at, lr.run_id LIMIT 2`)
504
- .all(project.workspace, sessionId, project.repositoryRoot);
505
- if (process.env.KIOKUKO_INTENT_DEBUG === '1')
506
- console.error('confirmation resume candidates', candidates.length);
507
- return candidates.length === 1 && (current === undefined || current.runId === candidates[0].runId);
508
- }),
509
- replay: async (input) => runtime.withDatabase(db => {
510
- const sessionId = input.agent.session.id;
511
- if (detachedDemandSessions.has(sessionId))
512
- return false;
513
- const current = currentSession(sessionId);
514
- // Matching persisted text is a cold continuation, not a replay of a
515
- // currently admitted native turn. Leave it on the interpretation path.
516
- if (!current || current.turn !== input.turn || current.nativeAgent !== input.agent
517
- || current.nativeSession !== input.agent.session || agents?.get(input.agent.id) !== input.agent
518
- || sessions?.get(sessionId) !== input.agent.session || current.closed || current.failed
519
- || !current.authority || current.prepared.run.status !== 'active'
520
- || !['ready', 'exhausted'].includes(current.prepared.intake.status)
521
- || current.prepared.nextAction !== 'proceed' || selections.get(current.runId)?.value.discussion)
522
- return false;
523
- const human = input.messages.filter(isHumanMessage);
524
- if (!human.length)
525
- return false;
526
- const task = textFromMessages(human);
527
- const references = current.requestIntentContext?.messageRefs;
528
- if (current.task !== task || !references
529
- || canonicalContentHash(requestIntentMessageRefs(human, task)) !== canonicalContentHash(references))
530
- return false;
531
- try {
532
- authorizeTaskLease(db, current.authority);
533
- }
534
- catch {
535
- return false;
536
- }
537
- return true;
538
- }),
539
- existing: async (input, requestIntent) => runtime.withDatabase(async (db) => {
540
- if (detachedDemandSessions.has(input.agent.session.id))
541
- return false;
542
- const current = currentSession(input.agent.session.id);
543
- // A retired native identity is not live execution authority. Keep its durable
544
- // owner intact, but let a reopened session answer before attempting recovery.
545
- // A queued human request is not a continuation grant from a stale normal
546
- // turn. Preserve its owner, but infer the new request before any effects.
547
- const text = input.messages.filter(isHumanMessage).flatMap((message) => typeof message.content === 'string' ? [message.content] : (message.content ?? []).filter((block) => block.type === 'text').map((block) => block.text)).join('\n');
548
- const keepsCurrentScope = requestIntent?.relation !== 'new';
549
- const resumeCoding = keepsCurrentScope && current && readCodingWorkflow(db, current.runId);
550
- if (current && current.turn < input.turn && input.messages.some(isHumanMessage) && !current.prepared.ennoOduno.applicable && !resumeCoding)
551
- return false;
552
- if (current)
553
- return !current.closed && !current.failed && current.nativeAgent === input.agent && current.nativeSession === input.agent.session;
554
- const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
555
- if (!project)
556
- return false;
557
- // The full adapter owns ledger runs, not the modular core ownership table.
558
- // Recovery still goes through admission's exact workspace/session checks.
559
- return Boolean(db.prepare(`SELECT 1 FROM ledger_runs lr
721
+ .all(project.workspace, sessionId, project.repositoryRoot);
722
+ if (process.env.KIOKUKO_INTENT_DEBUG === "1")
723
+ console.error("confirmation resume candidates", candidates.length);
724
+ return (candidates.length === 1 &&
725
+ (current === undefined ||
726
+ current.runId === candidates[0].runId));
727
+ }),
728
+ replay: async (input) => runtime.withDatabase((db) => {
729
+ const sessionId = input.agent.session.id;
730
+ if (detachedDemandSessions.has(sessionId))
731
+ return false;
732
+ const current = currentSession(sessionId);
733
+ // Matching persisted text is a cold continuation, not a replay of a
734
+ // currently admitted native turn. Leave it on the interpretation path.
735
+ if (!current ||
736
+ current.turn !== input.turn ||
737
+ current.nativeAgent !== input.agent ||
738
+ current.nativeSession !== input.agent.session ||
739
+ agents?.get(input.agent.id) !== input.agent ||
740
+ sessions?.get(sessionId) !== input.agent.session ||
741
+ current.closed ||
742
+ current.failed ||
743
+ !current.authority ||
744
+ current.prepared.run.status !== "active" ||
745
+ !["ready", "exhausted"].includes(current.prepared.intake.status) ||
746
+ current.prepared.nextAction !== "proceed" ||
747
+ selections.get(current.runId)?.value.discussion)
748
+ return false;
749
+ const human = input.messages.filter(isHumanMessage);
750
+ if (!human.length)
751
+ return false;
752
+ const task = textFromMessages(human);
753
+ const references = current.requestIntentContext?.messageRefs;
754
+ if (current.task !== task ||
755
+ !references ||
756
+ canonicalContentHash(requestIntentMessageRefs(human, task)) !== canonicalContentHash(references))
757
+ return false;
758
+ try {
759
+ authorizeTaskLease(db, current.authority);
760
+ }
761
+ catch {
762
+ return false;
763
+ }
764
+ return true;
765
+ }),
766
+ existing: async (input, requestIntent) => runtime.withDatabase(async (db) => {
767
+ if (detachedDemandSessions.has(input.agent.session.id))
768
+ return false;
769
+ const current = currentSession(input.agent.session.id);
770
+ // A retired native identity is not live execution authority. Keep its durable
771
+ // owner intact, but let a reopened session answer before attempting recovery.
772
+ // A queued human request is not a continuation grant from a stale normal
773
+ // turn. Preserve its owner, but infer the new request before any effects.
774
+ const text = input.messages
775
+ .filter(isHumanMessage)
776
+ .flatMap((message) => typeof message.content === "string"
777
+ ? [message.content]
778
+ : (message.content ?? [])
779
+ .filter((block) => block.type === "text")
780
+ .map((block) => block.text))
781
+ .join("\n");
782
+ const keepsCurrentScope = requestIntent?.relation !== "new";
783
+ const resumeCoding = keepsCurrentScope &&
784
+ current &&
785
+ readCodingWorkflow(db, current.runId);
786
+ if (current &&
787
+ current.turn < input.turn &&
788
+ input.messages.some(isHumanMessage) &&
789
+ !current.prepared.ennoOduno.applicable &&
790
+ !resumeCoding)
791
+ return false;
792
+ if (current)
793
+ return (!current.closed &&
794
+ !current.failed &&
795
+ current.nativeAgent === input.agent &&
796
+ current.nativeSession === input.agent.session);
797
+ const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
798
+ if (!project)
799
+ return false;
800
+ // The full adapter owns ledger runs, not the modular core ownership table.
801
+ // Recovery still goes through admission's exact workspace/session checks.
802
+ return Boolean(db
803
+ .prepare(`SELECT 1 FROM ledger_runs lr
560
804
  LEFT JOIN enno_contracts ec ON ec.run_id=lr.run_id
561
805
  LEFT JOIN dsh_coding_workflows cw ON cw.run_id=lr.run_id
562
806
  WHERE lr.workspace=? AND lr.dsh_session_id=? AND lr.status='active'
563
807
  AND ((ec.repository_root=? AND ec.status NOT IN ('completed','cancelled','blocked'))
564
808
  OR (?=1 AND json_extract(cw.snapshot_json,'$.state') NOT IN ('completed','cancelled','superseded'))) LIMIT 1`)
565
- .get(project.workspace, input.agent.session.id, project.repositoryRoot, requestIntent?.relation === 'new' ? 0 : 1));
566
- }),
567
- classify: (input, task) => classifyTaskForIntake(decisions, dshTurnRequestId({ dshSessionId: input.agent.session.id, turn: input.turn }), task, undefined, input.signal),
568
- interpret: input => admission.interpret({ agent: input.agent, messages: input.messages, turn: input.turn, step: input.step, signal: input.signal }),
569
- prepare: async (input, taskType, requestIntent) => {
570
- const event = await admission.mapPreStep(input, taskType, requestIntent);
571
- const result = await gate.prepareRequestedWork(event);
572
- if (result.admitted)
573
- detachedDemandSessions.delete(input.agent.session.id);
574
- return result.admitted && result.prepared.intake.profile.taskType !== 'chat';
575
- },
576
- ready: (agent, turn) => {
577
- if (agents?.get(agent.id) !== agent || sessions?.get(agent.session?.id ?? '') !== agent.session)
578
- return false;
579
- const current = agent.session && currentSession(agent.session.id);
580
- return !!current && current.nativeAgent === agent && current.nativeSession === agent.session && (turn === undefined || current.turn === turn)
581
- && !current.closed && !current.failed && current.prepared.run.status === 'active'
582
- && ['ready', 'exhausted'].includes(current.prepared.intake.status) && current.prepared.nextAction === 'proceed'
583
- && !selections.get(current.runId)?.value.discussion;
584
- },
585
- }, { onlyWhenDeferred: !conversationFirst }) : undefined;
809
+ .get(project.workspace, input.agent.session.id, project.repositoryRoot, requestIntent?.relation === "new" ? 0 : 1));
810
+ }),
811
+ classify: (input, task) => classifyTaskForIntake(decisions, dshTurnRequestId({
812
+ dshSessionId: input.agent.session.id,
813
+ turn: input.turn,
814
+ }), task, undefined, input.signal),
815
+ interpret: (input) => admission.interpret({
816
+ agent: input.agent,
817
+ messages: input.messages,
818
+ turn: input.turn,
819
+ step: input.step,
820
+ signal: input.signal,
821
+ }),
822
+ prepare: async (input, taskType, requestIntent) => {
823
+ const event = await admission.mapPreStep(input, taskType, requestIntent);
824
+ const result = await gate.prepareRequestedWork(event);
825
+ if (result.admitted)
826
+ detachedDemandSessions.delete(input.agent.session.id);
827
+ return (result.admitted &&
828
+ result.prepared.intake.profile.taskType !== "chat");
829
+ },
830
+ ready: (agent, turn) => {
831
+ if (agents?.get(agent.id) !== agent ||
832
+ sessions?.get(agent.session?.id ?? "") !== agent.session)
833
+ return false;
834
+ const current = agent.session && currentSession(agent.session.id);
835
+ return (!!current &&
836
+ current.nativeAgent === agent &&
837
+ current.nativeSession === agent.session &&
838
+ (turn === undefined || current.turn === turn) &&
839
+ !current.closed &&
840
+ !current.failed &&
841
+ current.prepared.run.status === "active" &&
842
+ ["ready", "exhausted"].includes(current.prepared.intake.status) &&
843
+ current.prepared.nextAction === "proceed" &&
844
+ !selections.get(current.runId)?.value.discussion);
845
+ },
846
+ }, { onlyWhenDeferred: !conversationFirst })
847
+ : undefined;
586
848
  if (demand)
587
849
  lifecycleMemory.connectIntake(demand);
588
850
  const taskWorkflow = demand && agents && sessions && skills?.snapshot && tools?.schemas
589
- ? new DshTaskWorkflow({ runtime, demand, agents, sessions, skills: { snapshot: options => skills.snapshot(options) },
590
- tools: { schemas: agent => tools.schemas(agent) }, lisp: () => native.get(LISP_ASSEMBLY_SERVICE, false),
591
- checkpointSource: async (agent) => { await sessions.flush?.(agent.session); try {
592
- await sessionMirror.checkpointAfterNativeFlush(agent.session);
593
- }
594
- catch { /* Optional mirror cannot veto native completion or Stop. */ } },
595
- kickFinalizer: () => memoryFinalizer.kick(), emit: task => { ctx.emit(TASK_STATE_EVENT, task); } }) : undefined;
596
- const demandEnd = demand ? onNativeEvent(ctx, 'session/event', (session, event) => {
597
- if (event.type === 'turn/end')
598
- demand.finish(session, event.data?.turn);
599
- if (event.type === 'request/context' && !currentSession(session.id)) {
600
- const answer = demand.answerOwner(session);
601
- if (answer) {
602
- const header = [...(answer.agent.session?.snapshotEvents?.() ?? [])].reverse().find(e => e.type === 'request/header')?.data;
603
- void memoryFinalizer.admitConversationIndex(answer.workspace, session.id, { ...header?.header?.config, contextWindow: event.data?.contextWindow }, () => agents?.get(answer.agent.id) === answer.agent && sessions?.get(session.id) === session
604
- && demand.answerOwner(session)?.workspace === answer.workspace).catch(() => { });
851
+ ? new DshTaskWorkflow({
852
+ runtime,
853
+ demand,
854
+ agents,
855
+ sessions,
856
+ skills: { snapshot: (options) => skills.snapshot(options) },
857
+ tools: { schemas: (agent) => tools.schemas(agent) },
858
+ lisp: () => native.get(LISP_ASSEMBLY_SERVICE, false),
859
+ checkpointSource: async (agent) => {
860
+ await sessions.flush?.(agent.session);
861
+ try {
862
+ await sessionMirror.checkpointAfterNativeFlush(agent.session);
863
+ }
864
+ catch {
865
+ /* Optional mirror cannot veto native completion or Stop. */
866
+ }
867
+ },
868
+ onCompleted: (task) => lifecycle.completeTask(task),
869
+ kickFinalizer: () => memoryFinalizer.kick(),
870
+ emit: (task) => {
871
+ ctx.emit(TASK_STATE_EVENT, task);
872
+ },
873
+ })
874
+ : undefined;
875
+ const demandEnd = demand
876
+ ? onNativeEvent(ctx, "session/event", (session, event) => {
877
+ if (event.type === "turn/end")
878
+ demand.finish(session, event.data?.turn);
879
+ if (event.type === "request/context" && !currentSession(session.id)) {
880
+ const answer = demand.answerOwner(session);
881
+ if (answer) {
882
+ const header = [...(answer.agent.session?.snapshotEvents?.() ?? [])]
883
+ .reverse()
884
+ .find((e) => e.type === "request/header")?.data;
885
+ void memoryFinalizer
886
+ .admitConversationIndex(answer.workspace, session.id, {
887
+ ...header?.header?.config,
888
+ contextWindow: event.data?.contextWindow,
889
+ }, () => agents?.get(answer.agent.id) === answer.agent &&
890
+ sessions?.get(session.id) === session &&
891
+ demand.answerOwner(session)?.workspace === answer.workspace)
892
+ .catch(() => { });
893
+ }
605
894
  }
606
- }
607
- }) : undefined;
608
- const demandDisposed = demand ? onNativeEvent(ctx, 'agent/disposed', ({ agent }) => {
609
- demand.retire(agent);
610
- const item = agent.session && currentSession(agent.session.id);
611
- if (item?.nativeAgent !== agent || item.nativeSession !== agent.session)
612
- return;
613
- // Drop only dead in-memory bindings. Durable ownership and obligations remain
614
- // untouched; a reopened session may answer but cannot borrow the old grant.
615
- detachedDemandSessions.add(item.sessionId);
616
- gate.clearTurn(item.sessionId, item.turn);
617
- executionSupport.clear(item.sessionId);
618
- turnState.releaseRun(item.runId);
619
- }) : undefined;
895
+ })
896
+ : undefined;
897
+ const demandDisposed = demand
898
+ ? onNativeEvent(ctx, "agent/disposed", ({ agent }) => {
899
+ demand.retire(agent);
900
+ const item = agent.session && currentSession(agent.session.id);
901
+ if (item?.nativeAgent !== agent || item.nativeSession !== agent.session)
902
+ return;
903
+ // Drop only dead in-memory bindings. Durable ownership and obligations remain
904
+ // untouched; a reopened session may answer but cannot borrow the old grant.
905
+ detachedDemandSessions.add(item.sessionId);
906
+ gate.clearTurn(item.sessionId, item.turn);
907
+ executionSupport.clear(item.sessionId);
908
+ turnState.releaseRun(item.runId);
909
+ })
910
+ : undefined;
620
911
  const discussionGuardDisposer = tools?.guard((value) => {
621
912
  const agent = value.agent;
622
913
  if (!agent?.session)
623
914
  return undefined;
624
915
  const lispCoding = native.get(LISP_CODING_SERVICE, false);
625
916
  if (lispCoding?.discussing(agent))
626
- return 'Lispモードの選択への自由入力に回答中です。ツールを使わず、ユーザーの発言に回答してください。';
917
+ return "Lispモードの選択への自由入力に回答中です。ツールを使わず、ユーザーの発言に回答してください。";
627
918
  const item = currentSession(agent.session.id);
628
- if (item?.nativeAgent === agent && item.nativeSession === agent.session && selections.get(item.runId)?.value.discussion) {
629
- return '自由入力への回答中です。実行方式は未確定です。ツールを使わず、ユーザーの発言に回答してください。';
919
+ if (item?.nativeAgent === agent &&
920
+ item.nativeSession === agent.session &&
921
+ selections.get(item.runId)?.value.discussion) {
922
+ return "自由入力への回答中です。実行方式は未確定です。ツールを使わず、ユーザーの発言に回答してください。";
630
923
  }
631
924
  return undefined;
632
925
  });
633
926
  const pairChanges = new Map();
634
- const pairLlm = native.get('llm', false);
927
+ const pairLlm = native.get("llm", false);
635
928
  const ownsPairRoot = (agent) => {
636
- if (!agent.session || isNativeSubagent(agent) || agents?.get(agent.id) !== agent || sessions?.get(agent.session.id) !== agent.session)
929
+ if (!agent.session ||
930
+ isNativeSubagent(agent) ||
931
+ agents?.get(agent.id) !== agent ||
932
+ sessions?.get(agent.session.id) !== agent.session)
637
933
  return false;
638
934
  try {
639
- return typeof agent.session.header?.cwd === 'string' && realpathSync(agent.session.header.cwd) === root;
935
+ return (typeof agent.session.header?.cwd === "string" &&
936
+ realpathSync(agent.session.header.cwd) === root);
640
937
  }
641
938
  catch {
642
939
  return false;
643
940
  }
644
941
  };
645
942
  const nativeWorkers = new NativeWorkerRouting({
646
- runtime, backend: native.get('subagents', false), agents, sessions,
943
+ runtime,
944
+ backend: native.get("subagents", false),
945
+ agents,
946
+ sessions,
647
947
  resolveOwner: async (agent, signal) => {
648
948
  if (!ownsPairRoot(agent))
649
949
  return undefined;
@@ -651,35 +951,51 @@ export function createDshHostAdapter(ctx, options = {}) {
651
951
  signal.throwIfAborted();
652
952
  const item = currentSession(agent.session.id);
653
953
  if (item && !item.closed) {
654
- const stored = await runtime.withDatabase(db => readExecutionSelection(db, item.runId));
954
+ const stored = await runtime.withDatabase((db) => readExecutionSelection(db, item.runId));
655
955
  if (stored?.value.headWorker) {
656
- if (item.nativeAgent !== agent || item.nativeSession !== agent.session || item.failed)
657
- throw new KiokukoError('CONFLICT', 'Head/worker execution owner changed');
658
- if (stored.value.status !== 'ready' || stored.value.discussion)
659
- throw new KiokukoError('CONFLICT', 'Head/worker selection is not ready');
660
- return { id: `run:${item.runId}`, sessionId: item.sessionId, selectionId: String(stored.revision), pair: stored.value.headWorker };
956
+ if (item.nativeAgent !== agent ||
957
+ item.nativeSession !== agent.session ||
958
+ item.failed)
959
+ throw new KiokukoError("CONFLICT", "Head/worker execution owner changed");
960
+ if (stored.value.status !== "ready" || stored.value.discussion)
961
+ throw new KiokukoError("CONFLICT", "Head/worker selection is not ready");
962
+ return {
963
+ id: `run:${item.runId}`,
964
+ sessionId: item.sessionId,
965
+ selectionId: String(stored.revision),
966
+ pair: stored.value.headWorker,
967
+ };
661
968
  }
662
969
  // An existing approved Enno or Deep configuration owns its own roles.
663
- if (stored?.value.mode === 'enno' || stored?.value.mode === 'deep-thinker')
970
+ if (stored?.value.mode === "enno" ||
971
+ stored?.value.mode === "deep-thinker")
664
972
  return undefined;
665
973
  }
666
974
  if (!pairLlm)
667
975
  return undefined;
668
976
  const saved = await getHeadWorkerSessionSelection(pairLlm, agent.session.id);
669
- return saved.configuration ? { id: `session:${agent.session.id}`, sessionId: agent.session.id, selectionId: String(saved.revision), pair: saved.configuration } : undefined;
977
+ return saved.configuration
978
+ ? {
979
+ id: `session:${agent.session.id}`,
980
+ sessionId: agent.session.id,
981
+ selectionId: String(saved.revision),
982
+ pair: saved.configuration,
983
+ }
984
+ : undefined;
670
985
  },
671
986
  validate: async (pair, signal) => {
672
987
  if (!modelCatalog)
673
- throw new KiokukoError('SERVICE_UNAVAILABLE', 'Head/worker model catalog is unavailable');
988
+ throw new KiokukoError("SERVICE_UNAVAILABLE", "Head/worker model catalog is unavailable");
674
989
  signal.throwIfAborted();
675
990
  const problems = await validateHeadWorker(pair, modelCatalog, options.modelRoutes ?? [], modelCompatibility);
676
991
  signal.throwIfAborted();
677
992
  if (problems.length)
678
- throw new KiokukoError('CONFLICT', problems.join('\n'));
993
+ throw new KiokukoError("CONFLICT", problems.join("\n"));
679
994
  },
680
995
  });
681
- const nativeWorkerToolDisposer = onNativeEvent(ctx, 'tools/execute', async (execution, next) => {
682
- if (execution.agent && isGenericNativeChild(execution.agent))
996
+ const nativeWorkerToolDisposer = onNativeEvent(ctx, "tools/execute", async (execution, next) => {
997
+ if (execution.agent &&
998
+ isGenericNativeChild(execution.agent))
683
999
  await nativeWorkers.assertCurrent(execution.agent);
684
1000
  return next();
685
1001
  }, { prepend: true });
@@ -690,72 +1006,103 @@ export function createDshHostAdapter(ctx, options = {}) {
690
1006
  pairChanges.set(agent.session.id, pending);
691
1007
  void pending.catch(() => { });
692
1008
  };
693
- const freezePairDisposer = onNativeEvent(ctx, 'agent/created', ({ agent }) => freezePair(agent));
1009
+ const freezePairDisposer = onNativeEvent(ctx, "agent/created", ({ agent }) => freezePair(agent));
694
1010
  for (const agent of agents?.list?.() ?? [])
695
1011
  freezePair(agent);
696
1012
  const clearRunPair = async (sessionId, isCurrent = () => true) => {
697
1013
  const session = sessions?.get(sessionId);
698
- const agent = agents?.list?.().find(candidate => candidate.session === session);
1014
+ const agent = agents
1015
+ ?.list?.()
1016
+ .find((candidate) => candidate.session === session);
699
1017
  if (!agent || !ownsPairRoot(agent))
700
1018
  return;
701
1019
  const item = currentSession(sessionId);
702
- if (item && !item.closed && item.nativeAgent === agent && item.nativeSession === session)
703
- await runtime.withDatabase(db => {
1020
+ if (item &&
1021
+ !item.closed &&
1022
+ item.nativeAgent === agent &&
1023
+ item.nativeSession === session)
1024
+ await runtime.withDatabase((db) => {
704
1025
  if (!isCurrent())
705
1026
  return;
706
1027
  const stored = readExecutionSelection(db, item.runId);
707
- if (stored?.value.mode === 'normal' && stored.value.headWorker) {
1028
+ if (stored?.value.mode === "normal" && stored.value.headWorker) {
708
1029
  const { headWorker: _pair, ...value } = stored.value;
709
1030
  selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, value));
710
1031
  }
711
1032
  });
712
1033
  };
713
- const pairSettingsDisposer = onNativeServiceEvent(ctx, 'kiokuko/head-worker-selected', (sessionId) => {
1034
+ const pairSettingsDisposer = onNativeServiceEvent(ctx, "kiokuko/head-worker-selected", (sessionId) => {
714
1035
  // The settings commit and normal-run override removal are one dispatch fence.
715
1036
  const pending = Promise.resolve().then(() => clearRunPair(sessionId, () => pairChanges.get(sessionId) === pending));
716
1037
  pairChanges.set(sessionId, pending);
717
1038
  void pending.catch(() => { });
718
1039
  return pending;
719
1040
  });
720
- const pairSelectionDisposer = onNativeEvent(ctx, 'session/event', (session, event) => {
721
- if (event.type !== 'model/selection' || sessions?.get(session.id) !== session || !pairLlm)
1041
+ const pairSelectionDisposer = onNativeEvent(ctx, "session/event", (session, event) => {
1042
+ if (event.type !== "model/selection" ||
1043
+ sessions?.get(session.id) !== session ||
1044
+ !pairLlm)
722
1045
  return;
723
- const agent = agents?.list?.().find(candidate => candidate.session === session);
1046
+ const agent = agents
1047
+ ?.list?.()
1048
+ .find((candidate) => candidate.session === session);
724
1049
  if (!agent || !ownsPairRoot(agent))
725
1050
  return;
726
1051
  const previous = pairChanges.get(session.id);
727
- const pending = Promise.resolve(previous).catch(() => { }).then(async () => {
1052
+ const pending = Promise.resolve(previous)
1053
+ .catch(() => { })
1054
+ .then(async () => {
728
1055
  const isCurrent = () => pairChanges.get(session.id) === pending;
729
1056
  if (!isCurrent())
730
1057
  return;
731
1058
  const item = currentSession(session.id);
732
- const stored = item && !item.closed ? await runtime.withDatabase(db => readExecutionSelection(db, item.runId)) : undefined;
1059
+ const stored = item && !item.closed
1060
+ ? await runtime.withDatabase((db) => readExecutionSelection(db, item.runId))
1061
+ : undefined;
733
1062
  if (!isCurrent())
734
1063
  return;
735
- const configured = stored?.value.headWorker ?? (await getHeadWorkerSessionSelection(pairLlm, session.id)).configuration;
1064
+ const configured = stored?.value.headWorker ??
1065
+ (await getHeadWorkerSessionSelection(pairLlm, session.id))
1066
+ .configuration;
736
1067
  if (!isCurrent())
737
1068
  return;
738
1069
  const selected = event.data;
739
1070
  // Native pickers may publish an idempotent re-selection of the same head.
740
- if (configured && selected?.provider === configured.head.provider && selected.model === configured.head.model) {
741
- if (typeof selected.reasoningEffort === 'string' && selected.reasoningEffort && selected.reasoningEffort !== configured.head.reasoningEffort) {
742
- const pair = { ...configured, head: { ...configured.head, reasoningEffort: selected.reasoningEffort } };
743
- if (stored?.value.mode === 'normal' && stored.value.headWorker && item) {
1071
+ if (configured &&
1072
+ selected?.provider === configured.head.provider &&
1073
+ selected.model === configured.head.model) {
1074
+ if (typeof selected.reasoningEffort === "string" &&
1075
+ selected.reasoningEffort &&
1076
+ selected.reasoningEffort !== configured.head.reasoningEffort) {
1077
+ const pair = {
1078
+ ...configured,
1079
+ head: {
1080
+ ...configured.head,
1081
+ reasoningEffort: selected.reasoningEffort,
1082
+ },
1083
+ };
1084
+ if (stored?.value.mode === "normal" &&
1085
+ stored.value.headWorker &&
1086
+ item) {
744
1087
  if (!modelCatalog)
745
- throw new KiokukoError('SERVICE_UNAVAILABLE', 'Head/worker model catalog is unavailable');
1088
+ throw new KiokukoError("SERVICE_UNAVAILABLE", "Head/worker model catalog is unavailable");
746
1089
  const problems = await validateHeadWorker(pair, modelCatalog, options.modelRoutes ?? [], modelCompatibility);
747
1090
  if (problems.length)
748
- throw new KiokukoError('CONFLICT', problems.join('\n'));
749
- await runtime.withDatabase(db => {
1091
+ throw new KiokukoError("CONFLICT", problems.join("\n"));
1092
+ await runtime.withDatabase((db) => {
750
1093
  if (!isCurrent())
751
1094
  return;
752
- selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, { ...stored.value, headWorker: pair }));
1095
+ selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, {
1096
+ ...stored.value,
1097
+ headWorker: pair,
1098
+ }));
753
1099
  });
754
1100
  }
755
1101
  const saved = await getHeadWorkerSessionSelection(pairLlm, session.id);
756
1102
  if (!isCurrent())
757
1103
  return;
758
- if (saved.configuration?.head.provider === selected.provider && saved.configuration.head.model === selected.model)
1104
+ if (saved.configuration?.head.provider === selected.provider &&
1105
+ saved.configuration.head.model === selected.model)
759
1106
  await updateHeadWorkerEffortForSession(pairLlm, session.id, selected.reasoningEffort, isCurrent);
760
1107
  }
761
1108
  return;
@@ -767,155 +1114,350 @@ export function createDshHostAdapter(ctx, options = {}) {
767
1114
  void pending.catch(() => { });
768
1115
  });
769
1116
  const routing = createRouting({
770
- ctx, native, tools, agents, sessions, runtime, modelAuto, answerReview, semanticCompaction, delegation, deepPlanning, isGenericNativeChild, demand, nativeWorkers,
1117
+ ctx,
1118
+ native,
1119
+ tools,
1120
+ agents,
1121
+ sessions,
1122
+ runtime,
1123
+ modelAuto,
1124
+ answerReview,
1125
+ semanticCompaction,
1126
+ delegation,
1127
+ deepPlanning,
1128
+ isGenericNativeChild,
1129
+ demand,
1130
+ nativeWorkers,
771
1131
  getSkillPrompts: () => skillPrompts,
772
- getToolExposureConfig: () => toolExposureConfig, reportToolExposureFallback, reportToolExposureProjection, modelCatalog,
773
- getSelection: runId => selections.get(runId), setSelection: (runId, value) => { selections.set(runId, value); },
774
- hasSelection: runId => selections.has(runId), getPolicyState: runId => turnState.policyState(runId),
775
- captureInitialInput, prepareTurn: event => gate.prepare(event), mapPreStep, currentSession,
776
- readStateForRun: item => runtime.withDatabase(db => stateForRun(db, item)),
1132
+ getToolExposureConfig: () => toolExposureConfig,
1133
+ reportToolExposureFallback,
1134
+ reportToolExposureProjection,
1135
+ modelCatalog,
1136
+ getSelection: (runId) => selections.get(runId),
1137
+ setSelection: (runId, value) => {
1138
+ selections.set(runId, value);
1139
+ },
1140
+ hasSelection: (runId) => selections.has(runId),
1141
+ getPolicyState: (runId) => turnState.policyState(runId),
1142
+ captureInitialInput,
1143
+ prepareTurn: (event) => gate.prepare(event),
1144
+ mapPreStep,
1145
+ currentSession,
1146
+ readStateForRun: (item) => runtime.withDatabase((db) => stateForRun(db, item)),
777
1147
  refreshMemoryOwner: admission.refreshMemoryOwner,
778
1148
  });
779
1149
  const contextMessages = createContextMessages({
780
- ctx, runtime, memoryRetrievalConfig, decisions, deepPlanning, executionSupport, continuityMode: continuityConfig.mode,
781
- getSkillPrompts: () => skillPrompts, systemSkillsFor: routing.systemSkillsFor,
782
- getSelection: runId => selections.get(runId), currentForAgentEvent, advisoryEvidenceFor: (item, state) => toolHostModule.advisoryEvidenceFor(item, state),
783
- executionBinding, sessionEventSource,
1150
+ ctx,
1151
+ runtime,
1152
+ memoryRetrievalConfig,
1153
+ decisions,
1154
+ deepPlanning,
1155
+ executionSupport,
1156
+ continuityMode: continuityConfig.mode,
1157
+ getSkillPrompts: () => skillPrompts,
1158
+ systemSkillsFor: routing.systemSkillsFor,
1159
+ getSelection: (runId) => selections.get(runId),
1160
+ currentForAgentEvent,
1161
+ advisoryEvidenceFor: (item, state) => toolHostModule.advisoryEvidenceFor(item, state),
1162
+ executionBinding,
1163
+ sessionEventSource,
784
1164
  });
785
1165
  const toolHostModule = createToolHost({
786
- runtime, turnState, currentSession, currentForAgentEvent, skills, tools,
787
- sessions, agents, gate, decisions, delegation, llm, modelCatalog,
788
- executionSupport, executionBinding, policy, advisory, capabilityCatalog, objectRecord,
1166
+ runtime,
1167
+ turnState,
1168
+ currentSession,
1169
+ currentForAgentEvent,
1170
+ skills,
1171
+ tools,
1172
+ sessions,
1173
+ agents,
1174
+ gate,
1175
+ decisions,
1176
+ delegation,
1177
+ llm,
1178
+ modelCatalog,
1179
+ executionSupport,
1180
+ executionBinding,
1181
+ policy,
1182
+ advisory,
1183
+ capabilityCatalog,
1184
+ objectRecord,
789
1185
  });
790
1186
  const { toolHost, advisoryRunner, assertTurnBoundary, submitAdvisory } = toolHostModule;
791
1187
  const advisoryEvidenceFor = toolHostModule.advisoryEvidenceFor;
792
1188
  const boundaries = createBoundaries({
793
1189
  isGenericNativeChild,
794
- ctx, runtime, now: options.now, agents, sessions, skills, tools, userQuestions, gate,
795
- delegation, executionSupport, answerReview, sessionMirror, currentSession, currentForAgentEvent,
796
- stateForRun, systemSkillsFor: routing.systemSkillsFor, getSkillPrompts: () => skillPrompts,
797
- refreshEnnoMemory, confirmationAnswerer, assertTurnBoundary, advisoryRunner, submitAdvisory,
798
- advisoryEvidenceFor, applyPolicy: turnState.applyPolicy, capabilityCatalog,
799
- closeTurn: input => runLifecycle.closeTurn(input), sessionEventSource,
800
- boundedUtf8Text, boundedMessageText, recoveryMessage, continuationMessage,
1190
+ ctx,
1191
+ runtime,
1192
+ now: options.now,
1193
+ agents,
1194
+ sessions,
1195
+ skills,
1196
+ tools,
1197
+ userQuestions,
1198
+ gate,
1199
+ delegation,
1200
+ executionSupport,
1201
+ answerReview,
1202
+ sessionMirror,
1203
+ currentSession,
1204
+ currentForAgentEvent,
1205
+ stateForRun,
1206
+ systemSkillsFor: routing.systemSkillsFor,
1207
+ getSkillPrompts: () => skillPrompts,
1208
+ refreshEnnoMemory,
1209
+ confirmationAnswerer,
1210
+ assertTurnBoundary,
1211
+ advisoryRunner,
1212
+ submitAdvisory,
1213
+ advisoryEvidenceFor,
1214
+ applyPolicy: turnState.applyPolicy,
1215
+ capabilityCatalog,
1216
+ closeTurn: (input) => runLifecycle.closeTurn(input),
1217
+ sessionEventSource,
1218
+ boundedUtf8Text,
1219
+ boundedMessageText,
1220
+ recoveryMessage,
1221
+ continuationMessage,
801
1222
  });
802
- const { boundaryWorker, ennoController, deliverCompletionReport, boundarySessionStartDisposer } = boundaries;
1223
+ const { boundaryWorker, ennoController, deliverCompletionReport, boundarySessionStartDisposer, } = boundaries;
803
1224
  const applicationDisposer = mountHostMemoryApplication({
804
1225
  questions: userQuestions,
805
- ctx, runtime, tools, commands, skills, agents, sessions, delegation, currentSession,
806
- turnState, gate, capabilityCatalog, memoryRetrievalConfig, demand,
807
- });
808
- const codingDisposer = tools ? mountCodingWorkflow({ tools: tools,
809
- on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
810
- runtime, ...(userQuestions ? { questions: userQuestions } : {}),
811
- lisp: () => native.get(LISP_CODING_SERVICE, false),
812
- preparationOnly: execution => demand?.preparationOnly(execution) === true,
813
- nativeCommand: execution => demand?.nativeCommand(execution) === true,
814
- nativeLisp: execution => demand?.nativeLisp(execution) === true,
815
- resolve(execution) {
816
- const agent = execution.agent, session = agent?.session;
817
- if (!agent || !session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session)
818
- return undefined;
819
- const child = delegation.observationBinding(agent);
820
- const item = currentSession(child?.parentSessionId ?? session.id);
821
- if (!item || item.closed || child && child.runId !== item.runId || !child && (item.nativeAgent !== agent || item.nativeSession !== session))
822
- return undefined;
823
- return { runId: item.runId, sessionId: item.sessionId, repositoryRoot: item.repositoryRoot, agent, task: item.task,
824
- requestIntent: item.requestIntent, requestIntentContext: item.requestIntentContext };
825
- },
826
- }) : undefined;
827
- const completionDisposer = tools ? mountTaskCompletion({ tools: tools,
828
- on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
1226
+ ctx,
829
1227
  runtime,
830
- resolve(execution) {
831
- const agent = execution.agent;
832
- const session = agent?.session;
833
- const item = session ? currentSession(session.id) : undefined;
834
- if (!agent || !session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session
835
- || !item || item.closed || item.nativeAgent !== agent || item.nativeSession !== session
836
- || delegation.isChild(agent) || isGenericNativeChild(agent))
837
- return undefined;
838
- return { runId: item.runId, sessionId: item.sessionId, repositoryRoot: item.repositoryRoot, agent };
839
- },
840
- async approve() { return true; },
841
- }) : undefined;
1228
+ tools,
1229
+ commands,
1230
+ skills,
1231
+ agents,
1232
+ sessions,
1233
+ delegation,
1234
+ currentSession,
1235
+ turnState,
1236
+ gate,
1237
+ capabilityCatalog,
1238
+ memoryRetrievalConfig,
1239
+ demand,
1240
+ });
1241
+ const codingDisposer = tools
1242
+ ? mountCodingWorkflow({
1243
+ tools: tools,
1244
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
1245
+ }, {
1246
+ runtime,
1247
+ ...(userQuestions ? { questions: userQuestions } : {}),
1248
+ lisp: () => native.get(LISP_CODING_SERVICE, false),
1249
+ preparationOnly: (execution) => demand?.preparationOnly(execution) === true,
1250
+ nativeCommand: (execution) => demand?.nativeCommand(execution) === true,
1251
+ nativeLisp: (execution) => demand?.nativeLisp(execution) === true,
1252
+ resolve(execution) {
1253
+ const agent = execution.agent, session = agent?.session;
1254
+ if (!agent ||
1255
+ !session ||
1256
+ agents?.get(agent.id) !== agent ||
1257
+ sessions?.get(session.id) !== session)
1258
+ return undefined;
1259
+ const child = delegation.observationBinding(agent);
1260
+ const item = currentSession(child?.parentSessionId ?? session.id);
1261
+ if (!item ||
1262
+ item.closed ||
1263
+ (child && child.runId !== item.runId) ||
1264
+ (!child &&
1265
+ (item.nativeAgent !== agent || item.nativeSession !== session)))
1266
+ return undefined;
1267
+ return {
1268
+ runId: item.runId,
1269
+ sessionId: item.sessionId,
1270
+ repositoryRoot: item.repositoryRoot,
1271
+ agent,
1272
+ task: item.task,
1273
+ requestIntent: item.requestIntent,
1274
+ requestIntentContext: item.requestIntentContext,
1275
+ };
1276
+ },
1277
+ })
1278
+ : undefined;
1279
+ const completionDisposer = tools
1280
+ ? mountTaskCompletion({
1281
+ tools: tools,
1282
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
1283
+ }, {
1284
+ runtime,
1285
+ resolve(execution) {
1286
+ const agent = execution.agent;
1287
+ const session = agent?.session;
1288
+ const item = session ? currentSession(session.id) : undefined;
1289
+ if (!agent ||
1290
+ !session ||
1291
+ agents?.get(agent.id) !== agent ||
1292
+ sessions?.get(session.id) !== session ||
1293
+ !item ||
1294
+ item.closed ||
1295
+ item.nativeAgent !== agent ||
1296
+ item.nativeSession !== session ||
1297
+ delegation.isChild(agent) ||
1298
+ isGenericNativeChild(agent))
1299
+ return undefined;
1300
+ return {
1301
+ runId: item.runId,
1302
+ sessionId: item.sessionId,
1303
+ repositoryRoot: item.repositoryRoot,
1304
+ agent,
1305
+ };
1306
+ },
1307
+ async approve() {
1308
+ return true;
1309
+ },
1310
+ })
1311
+ : undefined;
842
1312
  const resolveParentOwned = (execution) => {
843
1313
  const agent = execution.agent, session = agent?.session;
844
- if (!agent || !session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session || isGenericNativeChild(agent))
1314
+ if (!agent ||
1315
+ !session ||
1316
+ agents?.get(agent.id) !== agent ||
1317
+ sessions?.get(session.id) !== session ||
1318
+ isGenericNativeChild(agent))
845
1319
  return undefined;
846
1320
  const child = delegation.observationBinding(agent);
847
1321
  const item = currentSession(child?.parentSessionId ?? session.id);
848
- if (!item || item.closed || child && child.runId !== item.runId || !child && (item.nativeAgent !== agent || item.nativeSession !== session))
1322
+ if (!item ||
1323
+ item.closed ||
1324
+ (child && child.runId !== item.runId) ||
1325
+ (!child && (item.nativeAgent !== agent || item.nativeSession !== session)))
849
1326
  return undefined;
850
- if (child && delegation.toolDenial(agent, execution.name, execution.arguments))
1327
+ if (child &&
1328
+ delegation.toolDenial(agent, execution.name, execution.arguments))
851
1329
  return undefined;
852
- return { runId: item.runId, sessionId: session.id, workflowSessionId: item.sessionId, workspace: item.workspace, repositoryRoot: item.repositoryRoot, generation: executionBinding(item).generation, agent,
853
- requestIntent: item.requestIntent, requestIntentContext: item.requestIntentContext };
1330
+ return {
1331
+ runId: item.runId,
1332
+ sessionId: session.id,
1333
+ workflowSessionId: item.sessionId,
1334
+ workspace: item.workspace,
1335
+ repositoryRoot: item.repositoryRoot,
1336
+ generation: executionBinding(item).generation,
1337
+ agent,
1338
+ requestIntent: item.requestIntent,
1339
+ requestIntentContext: item.requestIntentContext,
1340
+ };
854
1341
  };
855
- const nativeTaskAuthority = new NativeTaskAuthority({ runtime, repositoryRoot: root, backend: native.get('subagents', false), agents, sessions, resolveParent: resolveParentOwned });
856
- const ownedDisposer = tools ? mountOwnedExecution({ tools: tools, on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
1342
+ const nativeTaskAuthority = new NativeTaskAuthority({
857
1343
  runtime,
858
- unownedNative: execution => demand?.unownedNative(execution) === true,
859
- nativeCommand: execution => demand?.nativeCommand(execution) === true,
860
- nativeLisp: execution => demand?.nativeLisp(execution) === true,
861
- isTaskControl: execution => ctx.get(TASK_WORKFLOW_SERVICE, false)?.isControl(execution) === true,
862
- resolve: execution => nativeTaskAuthority.resolve(execution) ?? resolveParentOwned(execution),
863
- async resolveRead(execution) {
864
- const agent = execution.agent, session = agent?.session;
865
- if (!agent || !session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session)
866
- return undefined;
867
- let cwd;
868
- try {
869
- if (typeof session.header?.cwd !== 'string')
870
- return undefined;
871
- cwd = realpathSync(session.header.cwd);
872
- }
873
- catch {
874
- return undefined;
875
- }
876
- // Child scopes retain their independent lineage checks. A primary session
877
- // may have been admitted from a directory other than plugin startup cwd.
878
- if (isGenericNativeChild(agent))
879
- return cwd === root ? nativeTaskAuthority.read(execution) : undefined;
880
- if (delegation.isChild(agent))
881
- return cwd === root ? resolveParentOwned(execution) : undefined;
882
- const current = resolveParentOwned(execution);
883
- if (execution.name === 'kioku_read' && current) {
884
- const item = currentSession(session.id);
885
- if (!item?.authority || item.cwd !== cwd || item.repositoryRoot !== current.repositoryRoot)
1344
+ repositoryRoot: root,
1345
+ backend: native.get("subagents", false),
1346
+ agents,
1347
+ sessions,
1348
+ resolveParent: resolveParentOwned,
1349
+ });
1350
+ const ownedDisposer = tools
1351
+ ? mountOwnedExecution({
1352
+ tools: tools,
1353
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
1354
+ }, {
1355
+ runtime,
1356
+ unownedNative: (execution) => demand?.unownedNative(execution) === true,
1357
+ nativeCommand: (execution) => demand?.nativeCommand(execution) === true,
1358
+ nativeLisp: (execution) => demand?.nativeLisp(execution) === true,
1359
+ isTaskControl: (execution) => ctx.get(TASK_WORKFLOW_SERVICE, false)?.isControl(execution) === true,
1360
+ resolve: (execution) => nativeTaskAuthority.resolve(execution) ??
1361
+ resolveParentOwned(execution),
1362
+ async resolveRead(execution) {
1363
+ const agent = execution.agent, session = agent?.session;
1364
+ if (!agent ||
1365
+ !session ||
1366
+ agents?.get(agent.id) !== agent ||
1367
+ sessions?.get(session.id) !== session)
886
1368
  return undefined;
887
- const authority = item.authority;
1369
+ let cwd;
888
1370
  try {
889
- await runtime.withDatabase(db => authorizeTaskLease(db, authority));
1371
+ if (typeof session.header?.cwd !== "string")
1372
+ return undefined;
1373
+ cwd = realpathSync(session.header.cwd);
890
1374
  }
891
1375
  catch {
892
1376
  return undefined;
893
1377
  }
894
- if (currentSession(session.id) !== item || item.authority !== authority || item.closed
895
- || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session)
896
- return undefined;
897
- return current;
898
- }
899
- return await runtime.withDatabase(async (db) => {
900
- const project = await resolveProjectWorkspaceReadOnly(db, cwd, { allowDirectory: true });
901
- return project ? readOwnedIdentity(db, agent, project.repositoryRoot, execution.name === 'kioku_result' ? execution.arguments?.operationId : undefined) : undefined;
902
- }) ?? resolveParentOwned(execution);
903
- },
904
- planActive: agent => ctx.get('planMode', false)?.get(agent)?.active === true,
905
- async confirm(identity, detail, signal) {
906
- if (!userQuestions)
907
- return false;
908
- const id = `kioku-destructive-${crypto.randomUUID()}`;
909
- const answer = await userQuestions.ask({ agent: identity.agent, signal, questions: [{ id, header: '破壊的変更の確認', question: 'この対象への変更を許可しますか?', detail, options: [{ label: '許可しない' }, { label: '許可する' }] }] });
910
- return answer.answers?.[0]?.id === id && answer.answers[0].selected?.[0] === '許可する';
911
- },
912
- }) : undefined;
913
- const planDisposer = mountPlanTransition({ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, ctx.get('planMode', false));
1378
+ // Child scopes retain their independent lineage checks. A primary session
1379
+ // may have been admitted from a directory other than plugin startup cwd.
1380
+ if (isGenericNativeChild(agent))
1381
+ return cwd === root
1382
+ ? nativeTaskAuthority.read(execution)
1383
+ : undefined;
1384
+ if (delegation.isChild(agent))
1385
+ return cwd === root ? resolveParentOwned(execution) : undefined;
1386
+ const current = resolveParentOwned(execution);
1387
+ if (execution.name === "kioku_read" && current) {
1388
+ const item = currentSession(session.id);
1389
+ if (!item?.authority ||
1390
+ item.cwd !== cwd ||
1391
+ item.repositoryRoot !== current.repositoryRoot)
1392
+ return undefined;
1393
+ const authority = item.authority;
1394
+ try {
1395
+ await runtime.withDatabase((db) => authorizeTaskLease(db, authority));
1396
+ }
1397
+ catch {
1398
+ return undefined;
1399
+ }
1400
+ if (currentSession(session.id) !== item ||
1401
+ item.authority !== authority ||
1402
+ item.closed ||
1403
+ agents?.get(agent.id) !== agent ||
1404
+ sessions?.get(session.id) !== session)
1405
+ return undefined;
1406
+ return current;
1407
+ }
1408
+ return ((await runtime.withDatabase(async (db) => {
1409
+ const project = await resolveProjectWorkspaceReadOnly(db, cwd, {
1410
+ allowDirectory: true,
1411
+ });
1412
+ return project
1413
+ ? readOwnedIdentity(db, agent, project.repositoryRoot, execution.name === "kioku_result"
1414
+ ? execution.arguments?.operationId
1415
+ : undefined)
1416
+ : undefined;
1417
+ })) ?? resolveParentOwned(execution));
1418
+ },
1419
+ planActive: (agent) => ctx.get("planMode", false)?.get(agent)?.active === true,
1420
+ async confirm(identity, detail, signal) {
1421
+ if (!userQuestions)
1422
+ return false;
1423
+ const id = `kioku-destructive-${crypto.randomUUID()}`;
1424
+ const answer = await userQuestions.ask({
1425
+ agent: identity.agent,
1426
+ signal,
1427
+ questions: [
1428
+ {
1429
+ id,
1430
+ header: "破壊的変更の確認",
1431
+ question: "この対象への変更を許可しますか?",
1432
+ detail,
1433
+ options: [{ label: "許可しない" }, { label: "許可する" }],
1434
+ },
1435
+ ],
1436
+ });
1437
+ return (answer.answers?.[0]?.id === id &&
1438
+ answer.answers[0].selected?.[0] === "許可する");
1439
+ },
1440
+ })
1441
+ : undefined;
1442
+ const planDisposer = mountPlanTransition({
1443
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
1444
+ }, ctx.get("planMode", false));
914
1445
  const observationMount = observation.install({
915
- ctx, ennoMemory, evolutionConfig, memoryFinalizer, currentSession, currentForAgentEvent,
916
- answerReview, markModelUnavailable: agent => routing.markModelUnavailable(agent),
1446
+ ctx,
1447
+ ennoMemory,
1448
+ evolutionConfig,
1449
+ memoryFinalizer,
1450
+ currentSession,
1451
+ currentForAgentEvent,
1452
+ answerReview,
1453
+ markModelUnavailable: (agent) => routing.markModelUnavailable(agent),
917
1454
  recordManualChange: (sessionId, pending) => routing.recordManualChange(sessionId, pending),
918
- modelAuto, root, autoReview, reviewBinding, sessionMirror, executionSupport,
1455
+ modelAuto,
1456
+ root,
1457
+ autoReview,
1458
+ reviewBinding,
1459
+ sessionMirror,
1460
+ executionSupport,
919
1461
  kickBoundary: (sessionId, agent) => {
920
1462
  if (agent && isGenericNativeChild(agent))
921
1463
  return;
@@ -925,93 +1467,166 @@ export function createDshHostAdapter(ctx, options = {}) {
925
1467
  if (!nativeAgent || !isGenericNativeChild(nativeAgent))
926
1468
  boundaryWorker.kick(sessionId, agent);
927
1469
  },
928
- stateForRun, objectRecord, isHumanMessage, eventContinuationId,
1470
+ stateForRun,
1471
+ objectRecord,
1472
+ isHumanMessage,
1473
+ eventContinuationId,
929
1474
  });
930
1475
  const lifecycle = createLifecycle({
931
- awaitingClarification: agent => demand?.awaitingClarification(agent) ?? false,
932
- runtime, sessions, sessionMirror, memoryFinalizer, autoReview, answerReview, ennoController,
933
- ennoMemory, executionSupport, gate, turnState, getSelection: runId => selections.get(runId),
934
- currentSession, currentForAgentEvent, stateForRun, deliverCompletionReport, reviewBinding,
935
- evolutionConfig, clearToolRun: toolHostModule.clearRun, sessionEventSource,
936
- onRunClosed: (runId, status, sessionId) => lifecycleMemory.completed(runId, status, sessionId),
1476
+ awaitingClarification: (agent) => demand?.awaitingClarification(agent) ?? false,
1477
+ runtime,
1478
+ sessions,
1479
+ sessionMirror,
1480
+ memoryFinalizer,
1481
+ autoReview,
1482
+ answerReview,
1483
+ ennoController,
1484
+ ennoMemory,
1485
+ executionSupport,
1486
+ gate,
1487
+ turnState,
1488
+ getSelection: (runId) => selections.get(runId),
1489
+ currentSession,
1490
+ currentForAgentEvent,
1491
+ stateForRun,
1492
+ deliverCompletionReport,
1493
+ reviewBinding,
1494
+ evolutionConfig,
1495
+ clearToolRun: toolHostModule.clearRun,
1496
+ sessionEventSource,
1497
+ onRunClosed: (runId, status, sessionId, authority) => lifecycleMemory.completed(runId, status, sessionId, authority),
937
1498
  });
938
- const { runLifecycle, resolveIdleClose, resolveSessionRunId, resolveSessionClose } = lifecycle;
1499
+ const { runLifecycle, resolveIdleClose, resolveSessionRunId, resolveSessionClose, } = lifecycle;
939
1500
  retireSupersededRun = lifecycle.retireSupersededRun;
940
1501
  const agenticReplayConfig = AgenticReplayConfig.parse(options.agenticReplay ?? {});
941
- const agenticReplay = !agenticReplayConfig.enabled ? undefined : createDshAgenticReplayHost(ctx, agenticReplayConfig, runtime, {
942
- session: id => sessions?.get(id), agent: id => agents?.get(id), logicalRun: resolveSessionRunId,
943
- ...(userQuestions ? { questions: userQuestions } : {}),
944
- interactive: agent => !delegation.isChild(agent) && !deepPlanning.executor.isChild(agent),
945
- recordingRun: agent => deepPlanning.executor.recordingRun(agent),
946
- recordingParent: agent => deepPlanning.executor.recordingParent(agent),
947
- });
1502
+ const agenticReplay = !agenticReplayConfig.enabled
1503
+ ? undefined
1504
+ : createDshAgenticReplayHost(ctx, agenticReplayConfig, runtime, {
1505
+ session: (id) => sessions?.get(id),
1506
+ agent: (id) => agents?.get(id),
1507
+ logicalRun: resolveSessionRunId,
1508
+ ...(userQuestions ? { questions: userQuestions } : {}),
1509
+ interactive: (agent) => !delegation.isChild(agent) && !deepPlanning.executor.isChild(agent),
1510
+ recordingRun: (agent) => deepPlanning.executor.recordingRun(agent),
1511
+ recordingParent: (agent) => deepPlanning.executor.recordingParent(agent),
1512
+ });
948
1513
  let disposePromise;
949
1514
  if (agenticReplay)
950
1515
  lifecycleMemory.connectAgenticReplay(agenticReplay);
951
- const efficiencyHost = createEfficiencyHost({ ctx, memoryFinalizer, agents, sessions, delegation, deepPlanning, currentSession });
952
- efficiencyHost.configure({ observe: efficiencyConfig.observe, inputMode: finalizationConfig.inputMode });
1516
+ const efficiencyHost = createEfficiencyHost({
1517
+ ctx,
1518
+ memoryFinalizer,
1519
+ agents,
1520
+ sessions,
1521
+ delegation,
1522
+ deepPlanning,
1523
+ currentSession,
1524
+ });
1525
+ efficiencyHost.configure({
1526
+ observe: efficiencyConfig.observe,
1527
+ inputMode: finalizationConfig.inputMode,
1528
+ });
953
1529
  // Register last so deferred preparation precedes the existing memory/completion pre-execute checks.
954
1530
  if (demand)
955
1531
  demand.mount(ctx, tools, systemPrompt);
956
1532
  // Observe the bound identity before inner pre-execute policies can refuse a tool.
957
- executionSupport.mountPreExecution({ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) });
1533
+ executionSupport.mountPreExecution({
1534
+ on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
1535
+ });
958
1536
  const host = {
959
1537
  ...(demand ? { onDemandIntake: demand } : {}),
960
1538
  ...(taskWorkflow ? { taskWorkflow } : {}),
961
1539
  bypassNativeIntake: isGenericNativeChild,
962
- modelAuto: { coordinator: modelAuto, validSession: (agentId, sessionId) => {
1540
+ modelAuto: {
1541
+ coordinator: modelAuto,
1542
+ validSession: (agentId, sessionId) => {
963
1543
  const currentAgent = agents?.get(agentId);
964
1544
  const currentNativeSession = sessions?.get(sessionId);
965
1545
  // Web sessions can belong to a workspace other than DSH's launch directory.
966
- return Boolean(currentAgent && currentNativeSession && currentAgent.session === currentNativeSession);
967
- } },
1546
+ return Boolean(currentAgent &&
1547
+ currentNativeSession &&
1548
+ currentAgent.session === currentNativeSession);
1549
+ },
1550
+ },
968
1551
  ...(diffReview ? { diffReview } : {}),
969
1552
  decisions,
970
1553
  semanticCompaction,
971
1554
  deepPlanning,
972
- get efficiency() { return efficiencyHost.efficiency; },
1555
+ get efficiency() {
1556
+ return efficiencyHost.efficiency;
1557
+ },
973
1558
  configureEfficiency: efficiencyHost.configure,
974
- get skillPrompts() { return skillPrompts; },
975
- configureSkillPrompts(prompts) { skillPrompts = prompts; },
976
- configureEnnoMemory: config => ennoMemory.configure(config),
977
- configureToolExposure: config => { toolExposureConfig = ToolExposureConfig.parse(config); },
1559
+ get skillPrompts() {
1560
+ return skillPrompts;
1561
+ },
1562
+ configureSkillPrompts(prompts) {
1563
+ skillPrompts = prompts;
1564
+ },
1565
+ configureEnnoMemory: (config) => ennoMemory.configure(config),
1566
+ configureToolExposure: (config) => {
1567
+ toolExposureConfig = ToolExposureConfig.parse(config);
1568
+ },
978
1569
  modelToolDefinitionsChanged: routing.modelToolDefinitionsChanged,
979
- memoryReview: createMemoryReviewHost({ runtime, autoReview, root, currentSession, objectRecord,
980
- memoryFinalizer, sessionMirror, reviewBinding }),
981
- memoryIndexReasoning: { configure: config => memoryFinalizer.configureMemoryIndexReasoning(config), command: (sessionId, raw) => memoryFinalizer.indexCommand(sessionId, raw) },
982
- memoryEvolution: createEvolutionHost({ runtime, memoryFinalizer, evolutionConfig }),
983
- autoGlobalization: { configure(enabled) { memoryFinalizer.configureAutoGlobalization(enabled); } },
1570
+ memoryReview: createMemoryReviewHost({
1571
+ runtime,
1572
+ autoReview,
1573
+ root,
1574
+ currentSession,
1575
+ objectRecord,
1576
+ memoryFinalizer,
1577
+ sessionMirror,
1578
+ reviewBinding,
1579
+ }),
1580
+ memoryIndexReasoning: {
1581
+ configure: (config) => memoryFinalizer.configureMemoryIndexReasoning(config),
1582
+ command: (sessionId, raw) => memoryFinalizer.indexCommand(sessionId, raw),
1583
+ },
1584
+ memoryEvolution: createEvolutionHost({
1585
+ runtime,
1586
+ memoryFinalizer,
1587
+ evolutionConfig,
1588
+ }),
1589
+ autoGlobalization: {
1590
+ configure(enabled) {
1591
+ memoryFinalizer.configureAutoGlobalization(enabled);
1592
+ },
1593
+ },
984
1594
  ...(agenticReplay === undefined ? {} : { agenticReplay }),
985
1595
  ...(skills === undefined ? {} : { skills: skills }),
986
1596
  ...(systemPrompt === undefined ? {} : { systemPrompt }),
987
1597
  runtime,
988
- runtimeOwner: options.runtime ? 'external' : 'host',
1598
+ runtimeOwner: options.runtime ? "external" : "host",
989
1599
  ...(userQuestions === undefined ? {} : { userQuestions }),
990
1600
  ...(commands === undefined ? {} : { commands: commands }),
991
1601
  ponytailModes: modes,
992
- ...(tools === undefined ? {} : {
993
- tools: { register: tools.register.bind(tools), guard: tools.guard.bind(tools) },
994
- toolHost,
995
- toolPolicy: policy,
996
- }),
1602
+ ...(tools === undefined
1603
+ ? {}
1604
+ : {
1605
+ tools: {
1606
+ register: tools.register.bind(tools),
1607
+ guard: tools.guard.bind(tools),
1608
+ },
1609
+ toolHost,
1610
+ toolPolicy: policy,
1611
+ }),
997
1612
  ...(tools === undefined ? {} : { intakeGate: gate, mapPreStep }),
998
1613
  memoryFinalizer,
999
- memoryFinalizerOwner: 'host',
1614
+ memoryFinalizerOwner: "host",
1000
1615
  sessionMirror,
1001
- sessionMirrorOwner: 'host',
1616
+ sessionMirrorOwner: "host",
1002
1617
  sessionExport,
1003
1618
  checkpointSessionMirror: (session) => sessionMirror.checkpointAfterNativeFlush(session),
1004
1619
  resolveSessionRunId,
1005
1620
  boundaryWorker,
1006
- boundaryWorkerOwner: 'host',
1621
+ boundaryWorkerOwner: "host",
1007
1622
  lifecycle: runLifecycle,
1008
- lifecycleOwner: 'host',
1623
+ lifecycleOwner: "host",
1009
1624
  resolveIdleClose,
1010
1625
  resolveSessionClose,
1011
1626
  };
1012
1627
  return {
1013
1628
  host,
1014
- dispose: () => disposePromise ??= (async () => {
1629
+ dispose: () => (disposePromise ??= (async () => {
1015
1630
  demand?.stop();
1016
1631
  await ownedDisposer?.();
1017
1632
  planDisposer();
@@ -1046,7 +1661,7 @@ export function createDshHostAdapter(ctx, options = {}) {
1046
1661
  catch (error) {
1047
1662
  failures.push(error);
1048
1663
  }
1049
- const pausedSessions = new Set(turnState.sessionIds().filter(id => executionSupport.paused(id)));
1664
+ const pausedSessions = new Set(turnState.sessionIds().filter((id) => executionSupport.paused(id)));
1050
1665
  ennoMemory.close();
1051
1666
  executionSupport.dispose();
1052
1667
  try {
@@ -1091,7 +1706,7 @@ export function createDshHostAdapter(ctx, options = {}) {
1091
1706
  catch (error) {
1092
1707
  failures.push(error);
1093
1708
  }
1094
- failures.push(...await lifecycle.closeRemainingRuns(pausedSessions));
1709
+ failures.push(...(await lifecycle.closeRemainingRuns(pausedSessions)));
1095
1710
  try {
1096
1711
  await runLifecycle.dispose();
1097
1712
  }
@@ -1102,7 +1717,9 @@ export function createDshHostAdapter(ctx, options = {}) {
1102
1717
  try {
1103
1718
  await lifecycleMemory.whenIdle();
1104
1719
  }
1105
- catch { /* optional observations cannot veto shutdown */ }
1720
+ catch {
1721
+ /* optional observations cannot veto shutdown */
1722
+ }
1106
1723
  try {
1107
1724
  observationMount.disposeIdle();
1108
1725
  await autoReview.dispose();
@@ -1162,14 +1779,18 @@ export function createDshHostAdapter(ctx, options = {}) {
1162
1779
  if (failures.length === 1)
1163
1780
  throw failures[0];
1164
1781
  if (failures.length > 1)
1165
- throw new AggregateError(failures, 'kiokuko-dsh adapter disposal failed');
1166
- })(),
1782
+ throw new AggregateError(failures, "kiokuko-dsh adapter disposal failed");
1783
+ })()),
1167
1784
  };
1168
1785
  }
1169
1786
  function stateForRun(database, item) {
1170
1787
  if (!item.prepared.ennoOduno.applicable)
1171
1788
  return item.prepared.ennoOduno;
1172
- return stateForSnapshot(readEnnoSnapshot(database, { runId: item.runId, workspace: item.workspace, orchestrationId: item.orchestrationId }));
1789
+ return stateForSnapshot(readEnnoSnapshot(database, {
1790
+ runId: item.runId,
1791
+ workspace: item.workspace,
1792
+ orchestrationId: item.orchestrationId,
1793
+ }));
1173
1794
  }
1174
1795
  export { KIOKUKO_DSH_HOST_SERVICE };
1175
1796
  //# sourceMappingURL=host-adapter.js.map