@code-yeongyu/senpi 2026.8.10 → 2026.8.11-2

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 (203) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/brand-dir-migration.d.ts +28 -0
  3. package/dist/brand-dir-migration.d.ts.map +1 -0
  4. package/dist/brand-dir-migration.js +77 -0
  5. package/dist/brand-dir-migration.js.map +1 -0
  6. package/dist/cli/grok-neo-gate.d.ts +0 -8
  7. package/dist/cli/grok-neo-gate.d.ts.map +1 -1
  8. package/dist/cli/grok-neo-gate.js +4 -2
  9. package/dist/cli/grok-neo-gate.js.map +1 -1
  10. package/dist/cli-main.js +3 -0
  11. package/dist/cli-main.js.map +1 -1
  12. package/dist/cli.js +2 -2
  13. package/dist/cli.js.map +1 -1
  14. package/dist/config.d.ts +27 -1
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +41 -9
  17. package/dist/config.js.map +1 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +2 -1
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/brand.d.ts +79 -0
  22. package/dist/core/brand.d.ts.map +1 -0
  23. package/dist/core/brand.js +141 -0
  24. package/dist/core/brand.js.map +1 -0
  25. package/dist/core/dynamic-prompt/identity.d.ts.map +1 -1
  26. package/dist/core/dynamic-prompt/identity.js +2 -1
  27. package/dist/core/dynamic-prompt/identity.js.map +1 -1
  28. package/dist/core/experimental.d.ts.map +1 -1
  29. package/dist/core/experimental.js +2 -1
  30. package/dist/core/experimental.js.map +1 -1
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js +10 -1
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/session-commit-boundary.js.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/log.js +2 -1
  36. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  37. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.d.ts.map +1 -1
  38. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js +4 -4
  39. package/dist/core/extensions/builtin/config-reload/generated-shim-filter.js.map +1 -1
  40. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/goal/index.js +5 -0
  42. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  43. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +2 -2
  44. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +3 -3
  46. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  47. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/goal/monitor-continuation.js +6 -0
  49. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  50. package/dist/core/extensions/builtin/goal/store.d.ts +3 -2
  51. package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/goal/store.js +128 -101
  53. package/dist/core/extensions/builtin/goal/store.js.map +1 -1
  54. package/dist/core/extensions/builtin/help/index.d.ts.map +1 -1
  55. package/dist/core/extensions/builtin/help/index.js +3 -2
  56. package/dist/core/extensions/builtin/help/index.js.map +1 -1
  57. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  58. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +2 -1
  59. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  60. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +2 -1
  62. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
  63. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
  64. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +2 -1
  65. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
  66. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  67. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -1
  68. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  69. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -1
  70. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +6 -5
  71. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -1
  72. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  73. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +2 -1
  74. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  75. package/dist/core/footer-data-provider.d.ts +1 -4
  76. package/dist/core/footer-data-provider.d.ts.map +1 -1
  77. package/dist/core/footer-data-provider.js +0 -7
  78. package/dist/core/footer-data-provider.js.map +1 -1
  79. package/dist/core/generated-shim-banner.d.ts +15 -0
  80. package/dist/core/generated-shim-banner.d.ts.map +1 -0
  81. package/dist/core/generated-shim-banner.js +26 -0
  82. package/dist/core/generated-shim-banner.js.map +1 -0
  83. package/dist/core/model-runtime.d.ts.map +1 -1
  84. package/dist/core/model-runtime.js +7 -3
  85. package/dist/core/model-runtime.js.map +1 -1
  86. package/dist/core/package-manager.d.ts.map +1 -1
  87. package/dist/core/package-manager.js +2 -1
  88. package/dist/core/package-manager.js.map +1 -1
  89. package/dist/core/resource-loader.d.ts.map +1 -1
  90. package/dist/core/resource-loader.js +3 -5
  91. package/dist/core/resource-loader.js.map +1 -1
  92. package/dist/core/session-log.d.ts.map +1 -1
  93. package/dist/core/session-log.js +4 -2
  94. package/dist/core/session-log.js.map +1 -1
  95. package/dist/core/settings-manager.d.ts.map +1 -1
  96. package/dist/core/settings-manager.js +3 -2
  97. package/dist/core/settings-manager.js.map +1 -1
  98. package/dist/core/telemetry.d.ts.map +1 -1
  99. package/dist/core/telemetry.js +2 -1
  100. package/dist/core/telemetry.js.map +1 -1
  101. package/dist/core/timings.d.ts +0 -4
  102. package/dist/core/timings.d.ts.map +1 -1
  103. package/dist/core/timings.js +2 -1
  104. package/dist/core/timings.js.map +1 -1
  105. package/dist/inspector-policy.d.ts.map +1 -1
  106. package/dist/inspector-policy.js +2 -1
  107. package/dist/inspector-policy.js.map +1 -1
  108. package/dist/main.d.ts.map +1 -1
  109. package/dist/main.js +5 -4
  110. package/dist/main.js.map +1 -1
  111. package/dist/migrations.d.ts.map +1 -1
  112. package/dist/migrations.js +4 -0
  113. package/dist/migrations.js.map +1 -1
  114. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  115. package/dist/modes/interactive/components/footer.js +1 -8
  116. package/dist/modes/interactive/components/footer.js.map +1 -1
  117. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  118. package/dist/modes/interactive/interactive-mode.js +6 -7
  119. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  120. package/dist/modes/interactive/tips/catalog/cli-tips.d.ts.map +1 -1
  121. package/dist/modes/interactive/tips/catalog/cli-tips.js +2 -1
  122. package/dist/modes/interactive/tips/catalog/cli-tips.js.map +1 -1
  123. package/dist/modes/interactive/tips/catalog/ethos-tips.d.ts.map +1 -1
  124. package/dist/modes/interactive/tips/catalog/ethos-tips.js +4 -3
  125. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  126. package/dist/modes/interactive/tips/catalog/model-tips.d.ts.map +1 -1
  127. package/dist/modes/interactive/tips/catalog/model-tips.js +2 -1
  128. package/dist/modes/interactive/tips/catalog/model-tips.js.map +1 -1
  129. package/dist/modes/interactive/tips/catalog/session-tips.d.ts.map +1 -1
  130. package/dist/modes/interactive/tips/catalog/session-tips.js +2 -1
  131. package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
  132. package/dist/modes/interactive/tips/catalog/settings-tips.d.ts.map +1 -1
  133. package/dist/modes/interactive/tips/catalog/settings-tips.js +3 -2
  134. package/dist/modes/interactive/tips/catalog/settings-tips.js.map +1 -1
  135. package/dist/modes/interactive/tips/catalog/workspace-tips.d.ts.map +1 -1
  136. package/dist/modes/interactive/tips/catalog/workspace-tips.js +4 -3
  137. package/dist/modes/interactive/tips/catalog/workspace-tips.js.map +1 -1
  138. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  139. package/dist/modes/rpc/rpc-mode.js +2 -1
  140. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  141. package/dist/nearest-parent-config.d.ts +6 -1
  142. package/dist/nearest-parent-config.d.ts.map +1 -1
  143. package/dist/nearest-parent-config.js +18 -2
  144. package/dist/nearest-parent-config.js.map +1 -1
  145. package/dist/package-manager-cli.d.ts.map +1 -1
  146. package/dist/package-manager-cli.js +13 -1
  147. package/dist/package-manager-cli.js.map +1 -1
  148. package/dist/rpc-entry.js +2 -0
  149. package/dist/rpc-entry.js.map +1 -1
  150. package/dist/self-update-bootstrap.d.ts.map +1 -1
  151. package/dist/self-update-bootstrap.js +6 -0
  152. package/dist/self-update-bootstrap.js.map +1 -1
  153. package/dist/senpi +2 -2
  154. package/dist/utils/pi-user-agent.d.ts +1 -1
  155. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  156. package/dist/utils/pi-user-agent.js +4 -3
  157. package/dist/utils/pi-user-agent.js.map +1 -1
  158. package/dist/utils/tools-manager.d.ts.map +1 -1
  159. package/dist/utils/tools-manager.js +2 -1
  160. package/dist/utils/tools-manager.js.map +1 -1
  161. package/dist/utils/version-check.d.ts +3 -0
  162. package/dist/utils/version-check.d.ts.map +1 -1
  163. package/dist/utils/version-check.js +37 -6
  164. package/dist/utils/version-check.js.map +1 -1
  165. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
  166. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  167. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  168. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
  169. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +4 -2
  170. package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts.map +1 -1
  172. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js +2 -1
  173. package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js.map +1 -1
  174. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  175. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  176. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  177. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  178. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  179. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  180. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  181. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts +14 -0
  182. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.d.ts.map +1 -0
  183. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js +24 -0
  184. package/node_modules/@earendil-works/pi-ai/dist/wire-identity.js.map +1 -0
  185. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  186. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.d.ts.map +1 -1
  187. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js +11 -3
  188. package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js.map +1 -1
  189. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  190. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  191. package/package.json +6 -6
  192. package/dist/core/omo-native-detect.d.ts +0 -3
  193. package/dist/core/omo-native-detect.d.ts.map +0 -1
  194. package/dist/core/omo-native-detect.js +0 -64
  195. package/dist/core/omo-native-detect.js.map +0 -1
  196. package/dist/core/omo-native-detect.test.d.ts +0 -2
  197. package/dist/core/omo-native-detect.test.d.ts.map +0 -1
  198. package/dist/core/omo-native-detect.test.js +0 -47
  199. package/dist/core/omo-native-detect.test.js.map +0 -1
  200. package/dist/modes/interactive/components/footer-omo-native-badge.test.d.ts +0 -2
  201. package/dist/modes/interactive/components/footer-omo-native-badge.test.d.ts.map +0 -1
  202. package/dist/modes/interactive/components/footer-omo-native-badge.test.js +0 -52
  203. package/dist/modes/interactive/components/footer-omo-native-badge.test.js.map +0 -1
@@ -2,10 +2,23 @@ import { randomUUID } from "node:crypto";
2
2
  import { appendFile, mkdir, writeFile } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { GoalAlreadyExistsError, GoalNotFoundError } from "./errors.js";
5
- import { encodedThreadId, readGoalFile, writeGoalFile } from "./persistence.js";
5
+ import { encodedThreadId, goalFilePath, readGoalFile, writeGoalFile } from "./persistence.js";
6
6
  import { transitionGoalStatus } from "./transitions.js";
7
7
  import { resolveTokenBudget, validateObjective, validateTokenBudget } from "./validation.js";
8
- export { goalFilePath } from "./persistence.js";
8
+ export { goalFilePath };
9
+ const goalMutationTails = new Map();
10
+ function enqueueGoalMutation(ref, mutation) {
11
+ const key = goalFilePath(ref);
12
+ const previous = goalMutationTails.get(key) ?? Promise.resolve();
13
+ const run = previous.then(mutation);
14
+ const tail = run.then(() => undefined, () => undefined);
15
+ goalMutationTails.set(key, tail);
16
+ void tail.then(() => {
17
+ if (goalMutationTails.get(key) === tail)
18
+ goalMutationTails.delete(key);
19
+ });
20
+ return run;
21
+ }
9
22
  export function goalHistoryFilePath(ref) {
10
23
  return join(ref.baseDir, `${encodedThreadId(ref)}.history.jsonl`);
11
24
  }
@@ -19,84 +32,90 @@ export async function readGoal(ref) {
19
32
  return readGoalFile(ref);
20
33
  }
21
34
  export async function writeGoal(ref, goal) {
22
- await writeGoalFile(ref, goal);
35
+ await enqueueGoalMutation(ref, () => writeGoalFile(ref, goal));
23
36
  }
24
37
  export async function createGoal(ref, objective, tokenBudget) {
25
- const validatedObjective = validateObjective(objective, objectiveFullTextFileName(ref));
26
- const current = await readGoal(ref);
27
- if (current !== null && current.status !== "complete") {
28
- throw new GoalAlreadyExistsError("cannot create a new goal because this thread already has a goal");
29
- }
30
- if (validatedObjective.truncated)
31
- await writeFullObjectiveText(ref, objective);
32
- if (current?.status === "complete")
33
- await archiveGoal(ref, current);
34
- const now = nowSeconds();
35
- const goal = {
36
- id: randomUUID(),
37
- threadId: ref.threadId,
38
- objective: validatedObjective.objective,
39
- status: "active",
40
- tokensUsed: 0,
41
- timeUsedSeconds: 0,
42
- consecutiveContinuations: 0,
43
- createdAt: now,
44
- updatedAt: now,
45
- lastStartedAt: now,
46
- ...(tokenBudget === undefined ? {} : { tokenBudget: validateTokenBudget(tokenBudget) }),
47
- };
48
- await writeGoal(ref, goal);
49
- return goal;
50
- }
51
- export async function updateGoal(ref, update, source = "model") {
52
- const current = await readGoal(ref);
53
- if (!current)
54
- throw new GoalNotFoundError("cannot update goal: no goal exists");
55
- const validatedObjective = update.objective === undefined ? undefined : validateObjective(update.objective, objectiveFullTextFileName(ref));
56
- const objective = validatedObjective?.objective ?? current.objective;
57
- const tokenBudget = resolveTokenBudget(current.tokenBudget, update.tokenBudget);
58
- const now = nextUpdatedAt(current.updatedAt);
59
- const hasObjectiveUpdate = update.objective !== undefined;
60
- const replacesGoal = hasObjectiveUpdate && (objective !== current.objective || current.status === "complete");
61
- const requestedStatus = update.status ?? (hasObjectiveUpdate ? "active" : undefined);
62
- if (replacesGoal) {
63
- const status = requestedStatus ?? "active";
64
- if (status === "blocked")
65
- throw new Error("objective replacement cannot create a blocked goal");
66
- const next = {
38
+ return enqueueGoalMutation(ref, async () => {
39
+ const validatedObjective = validateObjective(objective, objectiveFullTextFileName(ref));
40
+ const current = await readGoalFile(ref);
41
+ if (current !== null && current.status !== "complete") {
42
+ throw new GoalAlreadyExistsError("cannot create a new goal because this thread already has a goal");
43
+ }
44
+ if (validatedObjective.truncated)
45
+ await writeFullObjectiveText(ref, objective);
46
+ if (current?.status === "complete")
47
+ await archiveGoal(ref, current);
48
+ const now = nowSeconds();
49
+ const goal = {
67
50
  id: randomUUID(),
68
51
  threadId: ref.threadId,
69
- objective,
70
- status,
52
+ objective: validatedObjective.objective,
53
+ status: "active",
71
54
  tokensUsed: 0,
72
55
  timeUsedSeconds: 0,
73
56
  consecutiveContinuations: 0,
74
57
  createdAt: now,
75
58
  updatedAt: now,
76
- ...(tokenBudget === undefined ? {} : { tokenBudget }),
59
+ lastStartedAt: now,
60
+ ...(tokenBudget === undefined ? {} : { tokenBudget: validateTokenBudget(tokenBudget) }),
77
61
  };
78
- if (status === "active")
79
- next.lastStartedAt = now;
80
- if (status === "complete")
81
- next.completedAt = now;
62
+ await writeGoalFile(ref, goal);
63
+ return goal;
64
+ });
65
+ }
66
+ export async function updateGoal(ref, update, source = "model") {
67
+ return enqueueGoalMutation(ref, async () => {
68
+ const current = await readGoalFile(ref);
69
+ if (!current)
70
+ throw new GoalNotFoundError("cannot update goal: no goal exists");
71
+ const validatedObjective = update.objective === undefined
72
+ ? undefined
73
+ : validateObjective(update.objective, objectiveFullTextFileName(ref));
74
+ const objective = validatedObjective?.objective ?? current.objective;
75
+ const tokenBudget = resolveTokenBudget(current.tokenBudget, update.tokenBudget);
76
+ const now = nextUpdatedAt(current.updatedAt);
77
+ const hasObjectiveUpdate = update.objective !== undefined;
78
+ const replacesGoal = hasObjectiveUpdate && (objective !== current.objective || current.status === "complete");
79
+ const requestedStatus = update.status ?? (hasObjectiveUpdate ? "active" : undefined);
80
+ if (replacesGoal) {
81
+ const status = requestedStatus ?? "active";
82
+ if (status === "blocked")
83
+ throw new Error("objective replacement cannot create a blocked goal");
84
+ const next = {
85
+ id: randomUUID(),
86
+ threadId: ref.threadId,
87
+ objective,
88
+ status,
89
+ tokensUsed: 0,
90
+ timeUsedSeconds: 0,
91
+ consecutiveContinuations: 0,
92
+ createdAt: now,
93
+ updatedAt: now,
94
+ ...(tokenBudget === undefined ? {} : { tokenBudget }),
95
+ };
96
+ if (status === "active")
97
+ next.lastStartedAt = now;
98
+ if (status === "complete")
99
+ next.completedAt = now;
100
+ if (validatedObjective?.truncated)
101
+ await writeFullObjectiveText(ref, update.objective ?? "");
102
+ await writeGoalFile(ref, next);
103
+ return next;
104
+ }
105
+ const next = transitionGoalStatus({ ...current, objective }, requestedStatus ?? current.status, source, update.reason, now);
106
+ if (next.status !== current.status) {
107
+ next.consecutiveContinuations = 0;
108
+ delete next.lastContinuationSignature;
109
+ }
110
+ if (tokenBudget === undefined)
111
+ delete next.tokenBudget;
112
+ else
113
+ next.tokenBudget = tokenBudget;
82
114
  if (validatedObjective?.truncated)
83
115
  await writeFullObjectiveText(ref, update.objective ?? "");
84
- await writeGoal(ref, next);
116
+ await writeGoalFile(ref, next);
85
117
  return next;
86
- }
87
- const next = transitionGoalStatus({ ...current, objective }, requestedStatus ?? current.status, source, update.reason, now);
88
- if (next.status !== current.status) {
89
- next.consecutiveContinuations = 0;
90
- delete next.lastContinuationSignature;
91
- }
92
- if (tokenBudget === undefined)
93
- delete next.tokenBudget;
94
- else
95
- next.tokenBudget = tokenBudget;
96
- if (validatedObjective?.truncated)
97
- await writeFullObjectiveText(ref, update.objective ?? "");
98
- await writeGoal(ref, next);
99
- return next;
118
+ });
100
119
  }
101
120
  export async function archiveGoal(ref, goal) {
102
121
  const filePath = goalHistoryFilePath(ref);
@@ -109,44 +128,52 @@ async function writeFullObjectiveText(ref, objective) {
109
128
  await writeFile(filePath, objective, "utf8");
110
129
  }
111
130
  export async function clearGoal(ref) {
112
- const hadGoal = (await readGoal(ref)) !== null;
113
- await writeGoal(ref, null);
114
- return hadGoal;
131
+ return enqueueGoalMutation(ref, async () => {
132
+ const hadGoal = (await readGoalFile(ref)) !== null;
133
+ await writeGoalFile(ref, null);
134
+ return hadGoal;
135
+ });
115
136
  }
116
137
  export async function accountGoalUsage(ref, usage, elapsedSeconds, mode = "active", expectedGoalId) {
117
- const goal = await readGoal(ref);
118
- if (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId) || !canAccountGoalUsage(goal, mode)) {
119
- return goal;
120
- }
121
- const next = {
122
- ...goal,
123
- tokensUsed: goal.tokensUsed + Math.max(0, usage.input) + Math.max(0, usage.output),
124
- timeUsedSeconds: goal.timeUsedSeconds + Math.max(0, Math.trunc(elapsedSeconds)),
125
- updatedAt: nextUpdatedAt(goal.updatedAt),
126
- };
127
- await writeGoal(ref, next);
128
- return next;
129
- }
130
- export async function recordContinuationDelivered(ref, signature) {
131
- const goal = await readGoal(ref);
132
- if (!goal)
133
- return goal;
134
- const next = {
135
- ...goal,
136
- consecutiveContinuations: (goal.consecutiveContinuations ?? 0) + 1,
137
- lastContinuationSignature: signature,
138
- };
139
- await writeGoal(ref, next);
140
- return next;
138
+ return enqueueGoalMutation(ref, async () => {
139
+ const goal = await readGoalFile(ref);
140
+ if (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId) || !canAccountGoalUsage(goal, mode)) {
141
+ return goal;
142
+ }
143
+ const next = {
144
+ ...goal,
145
+ tokensUsed: goal.tokensUsed + Math.max(0, usage.input) + Math.max(0, usage.output),
146
+ timeUsedSeconds: goal.timeUsedSeconds + Math.max(0, Math.trunc(elapsedSeconds)),
147
+ updatedAt: nextUpdatedAt(goal.updatedAt),
148
+ };
149
+ await writeGoalFile(ref, next);
150
+ return next;
151
+ });
152
+ }
153
+ export async function recordContinuationDelivered(ref, signature, expectedGoalId) {
154
+ return enqueueGoalMutation(ref, async () => {
155
+ const goal = await readGoalFile(ref);
156
+ if (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId))
157
+ return null;
158
+ const next = {
159
+ ...goal,
160
+ consecutiveContinuations: (goal.consecutiveContinuations ?? 0) + 1,
161
+ lastContinuationSignature: signature,
162
+ };
163
+ await writeGoalFile(ref, next);
164
+ return next;
165
+ });
141
166
  }
142
167
  export async function resetContinuationStreak(ref) {
143
- const goal = await readGoal(ref);
144
- if (!goal)
145
- return goal;
146
- const next = { ...goal, consecutiveContinuations: 0 };
147
- delete next.lastContinuationSignature;
148
- await writeGoal(ref, next);
149
- return next;
168
+ return enqueueGoalMutation(ref, async () => {
169
+ const goal = await readGoalFile(ref);
170
+ if (!goal)
171
+ return goal;
172
+ const next = { ...goal, consecutiveContinuations: 0 };
173
+ delete next.lastContinuationSignature;
174
+ await writeGoalFile(ref, next);
175
+ return next;
176
+ });
150
177
  }
151
178
  function canAccountGoalUsage(goal, mode) {
152
179
  if (mode === "active")
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { GoalAlreadyExistsError, GoalNotFoundError } from \"./errors.ts\";\nimport { encodedThreadId, readGoalFile, writeGoalFile } from \"./persistence.ts\";\nimport { transitionGoalStatus } from \"./transitions.ts\";\nimport type {\n\tGoal,\n\tGoalAccountingMode,\n\tGoalStoreRef,\n\tGoalUpdate,\n\tGoalUpdateSource,\n\tTokenUsageSnapshot,\n} from \"./types.ts\";\nimport { resolveTokenBudget, validateObjective, validateTokenBudget } from \"./validation.ts\";\n\nexport { goalFilePath } from \"./persistence.ts\";\n\nexport function goalHistoryFilePath(ref: GoalStoreRef): string {\n\treturn join(ref.baseDir, `${encodedThreadId(ref)}.history.jsonl`);\n}\n\nexport function objectiveFullTextFileName(ref: GoalStoreRef): string {\n\treturn `${encodedThreadId(ref)}.objective-full.txt`;\n}\n\nexport function objectiveFullTextFilePath(ref: GoalStoreRef): string {\n\treturn join(ref.baseDir, objectiveFullTextFileName(ref));\n}\n\nexport async function readGoal(ref: GoalStoreRef): Promise<Goal | null> {\n\treturn readGoalFile(ref);\n}\n\nexport async function writeGoal(ref: GoalStoreRef, goal: Goal | null): Promise<void> {\n\tawait writeGoalFile(ref, goal);\n}\n\nexport async function createGoal(ref: GoalStoreRef, objective: string, tokenBudget?: number): Promise<Goal> {\n\tconst validatedObjective = validateObjective(objective, objectiveFullTextFileName(ref));\n\tconst current = await readGoal(ref);\n\tif (current !== null && current.status !== \"complete\") {\n\t\tthrow new GoalAlreadyExistsError(\"cannot create a new goal because this thread already has a goal\");\n\t}\n\tif (validatedObjective.truncated) await writeFullObjectiveText(ref, objective);\n\tif (current?.status === \"complete\") await archiveGoal(ref, current);\n\tconst now = nowSeconds();\n\tconst goal: Goal = {\n\t\tid: randomUUID(),\n\t\tthreadId: ref.threadId,\n\t\tobjective: validatedObjective.objective,\n\t\tstatus: \"active\",\n\t\ttokensUsed: 0,\n\t\ttimeUsedSeconds: 0,\n\t\tconsecutiveContinuations: 0,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tlastStartedAt: now,\n\t\t...(tokenBudget === undefined ? {} : { tokenBudget: validateTokenBudget(tokenBudget) }),\n\t};\n\tawait writeGoal(ref, goal);\n\treturn goal;\n}\n\nexport async function updateGoal(\n\tref: GoalStoreRef,\n\tupdate: GoalUpdate,\n\tsource: GoalUpdateSource = \"model\",\n): Promise<Goal> {\n\tconst current = await readGoal(ref);\n\tif (!current) throw new GoalNotFoundError(\"cannot update goal: no goal exists\");\n\n\tconst validatedObjective =\n\t\tupdate.objective === undefined ? undefined : validateObjective(update.objective, objectiveFullTextFileName(ref));\n\tconst objective = validatedObjective?.objective ?? current.objective;\n\tconst tokenBudget = resolveTokenBudget(current.tokenBudget, update.tokenBudget);\n\tconst now = nextUpdatedAt(current.updatedAt);\n\tconst hasObjectiveUpdate = update.objective !== undefined;\n\tconst replacesGoal = hasObjectiveUpdate && (objective !== current.objective || current.status === \"complete\");\n\tconst requestedStatus = update.status ?? (hasObjectiveUpdate ? \"active\" : undefined);\n\n\tif (replacesGoal) {\n\t\tconst status = requestedStatus ?? \"active\";\n\t\tif (status === \"blocked\") throw new Error(\"objective replacement cannot create a blocked goal\");\n\t\tconst next: Goal = {\n\t\t\tid: randomUUID(),\n\t\t\tthreadId: ref.threadId,\n\t\t\tobjective,\n\t\t\tstatus,\n\t\t\ttokensUsed: 0,\n\t\t\ttimeUsedSeconds: 0,\n\t\t\tconsecutiveContinuations: 0,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\t...(tokenBudget === undefined ? {} : { tokenBudget }),\n\t\t};\n\t\tif (status === \"active\") next.lastStartedAt = now;\n\t\tif (status === \"complete\") next.completedAt = now;\n\t\tif (validatedObjective?.truncated) await writeFullObjectiveText(ref, update.objective ?? \"\");\n\t\tawait writeGoal(ref, next);\n\t\treturn next;\n\t}\n\n\tconst next = transitionGoalStatus(\n\t\t{ ...current, objective },\n\t\trequestedStatus ?? current.status,\n\t\tsource,\n\t\tupdate.reason,\n\t\tnow,\n\t);\n\tif (next.status !== current.status) {\n\t\tnext.consecutiveContinuations = 0;\n\t\tdelete next.lastContinuationSignature;\n\t}\n\tif (tokenBudget === undefined) delete next.tokenBudget;\n\telse next.tokenBudget = tokenBudget;\n\tif (validatedObjective?.truncated) await writeFullObjectiveText(ref, update.objective ?? \"\");\n\tawait writeGoal(ref, next);\n\treturn next;\n}\n\nexport async function archiveGoal(ref: GoalStoreRef, goal: Goal): Promise<void> {\n\tconst filePath = goalHistoryFilePath(ref);\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tawait appendFile(filePath, `${JSON.stringify(goal)}\\n`, \"utf8\");\n}\n\nasync function writeFullObjectiveText(ref: GoalStoreRef, objective: string): Promise<void> {\n\tconst filePath = objectiveFullTextFilePath(ref);\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tawait writeFile(filePath, objective, \"utf8\");\n}\n\nexport async function clearGoal(ref: GoalStoreRef): Promise<boolean> {\n\tconst hadGoal = (await readGoal(ref)) !== null;\n\tawait writeGoal(ref, null);\n\treturn hadGoal;\n}\n\nexport async function accountGoalUsage(\n\tref: GoalStoreRef,\n\tusage: TokenUsageSnapshot,\n\telapsedSeconds: number,\n\tmode: GoalAccountingMode = \"active\",\n\texpectedGoalId?: string,\n): Promise<Goal | null> {\n\tconst goal = await readGoal(ref);\n\tif (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId) || !canAccountGoalUsage(goal, mode)) {\n\t\treturn goal;\n\t}\n\tconst next: Goal = {\n\t\t...goal,\n\t\ttokensUsed: goal.tokensUsed + Math.max(0, usage.input) + Math.max(0, usage.output),\n\t\ttimeUsedSeconds: goal.timeUsedSeconds + Math.max(0, Math.trunc(elapsedSeconds)),\n\t\tupdatedAt: nextUpdatedAt(goal.updatedAt),\n\t};\n\tawait writeGoal(ref, next);\n\treturn next;\n}\n\nexport async function recordContinuationDelivered(ref: GoalStoreRef, signature: string): Promise<Goal | null> {\n\tconst goal = await readGoal(ref);\n\tif (!goal) return goal;\n\tconst next: Goal = {\n\t\t...goal,\n\t\tconsecutiveContinuations: (goal.consecutiveContinuations ?? 0) + 1,\n\t\tlastContinuationSignature: signature,\n\t};\n\tawait writeGoal(ref, next);\n\treturn next;\n}\n\nexport async function resetContinuationStreak(ref: GoalStoreRef): Promise<Goal | null> {\n\tconst goal = await readGoal(ref);\n\tif (!goal) return goal;\n\tconst next: Goal = { ...goal, consecutiveContinuations: 0 };\n\tdelete next.lastContinuationSignature;\n\tawait writeGoal(ref, next);\n\treturn next;\n}\n\nfunction canAccountGoalUsage(goal: Goal, mode: GoalAccountingMode): boolean {\n\tif (mode === \"active\") return goal.status === \"active\";\n\tif (mode === \"activeOrBlocked\") return goal.status === \"active\" || goal.status === \"blocked\";\n\treturn goal.status === \"active\" || goal.status === \"complete\";\n}\n\nfunction nextUpdatedAt(previousUpdatedAt: number): number {\n\treturn Math.max(nowSeconds(), previousUpdatedAt + 1);\n}\n\nfunction nowSeconds(): number {\n\treturn Math.trunc(Date.now() / 1000);\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { GoalAlreadyExistsError, GoalNotFoundError } from \"./errors.ts\";\nimport { encodedThreadId, goalFilePath, readGoalFile, writeGoalFile } from \"./persistence.ts\";\nimport { transitionGoalStatus } from \"./transitions.ts\";\nimport type {\n\tGoal,\n\tGoalAccountingMode,\n\tGoalStoreRef,\n\tGoalUpdate,\n\tGoalUpdateSource,\n\tTokenUsageSnapshot,\n} from \"./types.ts\";\nimport { resolveTokenBudget, validateObjective, validateTokenBudget } from \"./validation.ts\";\n\nexport { goalFilePath };\n\nconst goalMutationTails = new Map<string, Promise<void>>();\n\nfunction enqueueGoalMutation<T>(ref: GoalStoreRef, mutation: () => Promise<T>): Promise<T> {\n\tconst key = goalFilePath(ref);\n\tconst previous = goalMutationTails.get(key) ?? Promise.resolve();\n\tconst run = previous.then(mutation);\n\tconst tail = run.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\tgoalMutationTails.set(key, tail);\n\tvoid tail.then(() => {\n\t\tif (goalMutationTails.get(key) === tail) goalMutationTails.delete(key);\n\t});\n\treturn run;\n}\n\nexport function goalHistoryFilePath(ref: GoalStoreRef): string {\n\treturn join(ref.baseDir, `${encodedThreadId(ref)}.history.jsonl`);\n}\n\nexport function objectiveFullTextFileName(ref: GoalStoreRef): string {\n\treturn `${encodedThreadId(ref)}.objective-full.txt`;\n}\n\nexport function objectiveFullTextFilePath(ref: GoalStoreRef): string {\n\treturn join(ref.baseDir, objectiveFullTextFileName(ref));\n}\n\nexport async function readGoal(ref: GoalStoreRef): Promise<Goal | null> {\n\treturn readGoalFile(ref);\n}\n\nexport async function writeGoal(ref: GoalStoreRef, goal: Goal | null): Promise<void> {\n\tawait enqueueGoalMutation(ref, () => writeGoalFile(ref, goal));\n}\n\nexport async function createGoal(ref: GoalStoreRef, objective: string, tokenBudget?: number): Promise<Goal> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst validatedObjective = validateObjective(objective, objectiveFullTextFileName(ref));\n\t\tconst current = await readGoalFile(ref);\n\t\tif (current !== null && current.status !== \"complete\") {\n\t\t\tthrow new GoalAlreadyExistsError(\"cannot create a new goal because this thread already has a goal\");\n\t\t}\n\t\tif (validatedObjective.truncated) await writeFullObjectiveText(ref, objective);\n\t\tif (current?.status === \"complete\") await archiveGoal(ref, current);\n\t\tconst now = nowSeconds();\n\t\tconst goal: Goal = {\n\t\t\tid: randomUUID(),\n\t\t\tthreadId: ref.threadId,\n\t\t\tobjective: validatedObjective.objective,\n\t\t\tstatus: \"active\",\n\t\t\ttokensUsed: 0,\n\t\t\ttimeUsedSeconds: 0,\n\t\t\tconsecutiveContinuations: 0,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\tlastStartedAt: now,\n\t\t\t...(tokenBudget === undefined ? {} : { tokenBudget: validateTokenBudget(tokenBudget) }),\n\t\t};\n\t\tawait writeGoalFile(ref, goal);\n\t\treturn goal;\n\t});\n}\n\nexport async function updateGoal(\n\tref: GoalStoreRef,\n\tupdate: GoalUpdate,\n\tsource: GoalUpdateSource = \"model\",\n): Promise<Goal> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst current = await readGoalFile(ref);\n\t\tif (!current) throw new GoalNotFoundError(\"cannot update goal: no goal exists\");\n\n\t\tconst validatedObjective =\n\t\t\tupdate.objective === undefined\n\t\t\t\t? undefined\n\t\t\t\t: validateObjective(update.objective, objectiveFullTextFileName(ref));\n\t\tconst objective = validatedObjective?.objective ?? current.objective;\n\t\tconst tokenBudget = resolveTokenBudget(current.tokenBudget, update.tokenBudget);\n\t\tconst now = nextUpdatedAt(current.updatedAt);\n\t\tconst hasObjectiveUpdate = update.objective !== undefined;\n\t\tconst replacesGoal = hasObjectiveUpdate && (objective !== current.objective || current.status === \"complete\");\n\t\tconst requestedStatus = update.status ?? (hasObjectiveUpdate ? \"active\" : undefined);\n\n\t\tif (replacesGoal) {\n\t\t\tconst status = requestedStatus ?? \"active\";\n\t\t\tif (status === \"blocked\") throw new Error(\"objective replacement cannot create a blocked goal\");\n\t\t\tconst next: Goal = {\n\t\t\t\tid: randomUUID(),\n\t\t\t\tthreadId: ref.threadId,\n\t\t\t\tobjective,\n\t\t\t\tstatus,\n\t\t\t\ttokensUsed: 0,\n\t\t\t\ttimeUsedSeconds: 0,\n\t\t\t\tconsecutiveContinuations: 0,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t\t...(tokenBudget === undefined ? {} : { tokenBudget }),\n\t\t\t};\n\t\t\tif (status === \"active\") next.lastStartedAt = now;\n\t\t\tif (status === \"complete\") next.completedAt = now;\n\t\t\tif (validatedObjective?.truncated) await writeFullObjectiveText(ref, update.objective ?? \"\");\n\t\t\tawait writeGoalFile(ref, next);\n\t\t\treturn next;\n\t\t}\n\n\t\tconst next = transitionGoalStatus(\n\t\t\t{ ...current, objective },\n\t\t\trequestedStatus ?? current.status,\n\t\t\tsource,\n\t\t\tupdate.reason,\n\t\t\tnow,\n\t\t);\n\t\tif (next.status !== current.status) {\n\t\t\tnext.consecutiveContinuations = 0;\n\t\t\tdelete next.lastContinuationSignature;\n\t\t}\n\t\tif (tokenBudget === undefined) delete next.tokenBudget;\n\t\telse next.tokenBudget = tokenBudget;\n\t\tif (validatedObjective?.truncated) await writeFullObjectiveText(ref, update.objective ?? \"\");\n\t\tawait writeGoalFile(ref, next);\n\t\treturn next;\n\t});\n}\n\nexport async function archiveGoal(ref: GoalStoreRef, goal: Goal): Promise<void> {\n\tconst filePath = goalHistoryFilePath(ref);\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tawait appendFile(filePath, `${JSON.stringify(goal)}\\n`, \"utf8\");\n}\n\nasync function writeFullObjectiveText(ref: GoalStoreRef, objective: string): Promise<void> {\n\tconst filePath = objectiveFullTextFilePath(ref);\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tawait writeFile(filePath, objective, \"utf8\");\n}\n\nexport async function clearGoal(ref: GoalStoreRef): Promise<boolean> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst hadGoal = (await readGoalFile(ref)) !== null;\n\t\tawait writeGoalFile(ref, null);\n\t\treturn hadGoal;\n\t});\n}\n\nexport async function accountGoalUsage(\n\tref: GoalStoreRef,\n\tusage: TokenUsageSnapshot,\n\telapsedSeconds: number,\n\tmode: GoalAccountingMode = \"active\",\n\texpectedGoalId?: string,\n): Promise<Goal | null> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst goal = await readGoalFile(ref);\n\t\tif (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId) || !canAccountGoalUsage(goal, mode)) {\n\t\t\treturn goal;\n\t\t}\n\t\tconst next: Goal = {\n\t\t\t...goal,\n\t\t\ttokensUsed: goal.tokensUsed + Math.max(0, usage.input) + Math.max(0, usage.output),\n\t\t\ttimeUsedSeconds: goal.timeUsedSeconds + Math.max(0, Math.trunc(elapsedSeconds)),\n\t\t\tupdatedAt: nextUpdatedAt(goal.updatedAt),\n\t\t};\n\t\tawait writeGoalFile(ref, next);\n\t\treturn next;\n\t});\n}\n\nexport async function recordContinuationDelivered(\n\tref: GoalStoreRef,\n\tsignature: string,\n\texpectedGoalId?: string,\n): Promise<Goal | null> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst goal = await readGoalFile(ref);\n\t\tif (!goal || (expectedGoalId !== undefined && goal.id !== expectedGoalId)) return null;\n\t\tconst next: Goal = {\n\t\t\t...goal,\n\t\t\tconsecutiveContinuations: (goal.consecutiveContinuations ?? 0) + 1,\n\t\t\tlastContinuationSignature: signature,\n\t\t};\n\t\tawait writeGoalFile(ref, next);\n\t\treturn next;\n\t});\n}\n\nexport async function resetContinuationStreak(ref: GoalStoreRef): Promise<Goal | null> {\n\treturn enqueueGoalMutation(ref, async () => {\n\t\tconst goal = await readGoalFile(ref);\n\t\tif (!goal) return goal;\n\t\tconst next: Goal = { ...goal, consecutiveContinuations: 0 };\n\t\tdelete next.lastContinuationSignature;\n\t\tawait writeGoalFile(ref, next);\n\t\treturn next;\n\t});\n}\n\nfunction canAccountGoalUsage(goal: Goal, mode: GoalAccountingMode): boolean {\n\tif (mode === \"active\") return goal.status === \"active\";\n\tif (mode === \"activeOrBlocked\") return goal.status === \"active\" || goal.status === \"blocked\";\n\treturn goal.status === \"active\" || goal.status === \"complete\";\n}\n\nfunction nextUpdatedAt(previousUpdatedAt: number): number {\n\treturn Math.max(nowSeconds(), previousUpdatedAt + 1);\n}\n\nfunction nowSeconds(): number {\n\treturn Math.trunc(Date.now() / 1000);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8B5D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8B5D"}
@@ -1,12 +1,13 @@
1
+ import { APP_NAME } from "../../../../config.js";
1
2
  import { buildHelpMarkdown } from "../../../../modes/interactive/help-content.js";
2
3
  import { HELP_OVERLAY_OPTIONS, HelpPanel } from "./panel.js";
3
- const NON_TUI_HELP = "Interactive /help is available in TUI mode; run senpi --help for CLI usage.";
4
+ const NON_TUI_HELP = `Interactive /help is available in TUI mode; run ${APP_NAME} --help for CLI usage.`;
4
5
  export default function helpExtension(pi) {
5
6
  pi.registerCommand("keybindings", {
6
7
  description: "Open your keybindings.json in $EDITOR and reload it live",
7
8
  handler: async (_args, ctx) => {
8
9
  if (ctx.mode !== "tui") {
9
- ctx.ui.notify("Interactive /keybindings opens your config in $EDITOR and reloads it; run senpi in TUI mode to use it.", "info");
10
+ ctx.ui.notify(`Interactive /keybindings opens your config in $EDITOR and reloads it; run ${APP_NAME} in TUI mode to use it.`, "info");
10
11
  return;
11
12
  }
12
13
  // In TUI mode interactive-mode's text dispatch handles /keybindings first.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,YAAY,GAAG,6EAA6E,CAAC;AAEnG,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAgB;IACrD,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE;QACjC,WAAW,EAAE,0DAA0D;QACvE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,wGAAwG,EACxG,MAAM,CACN,CAAC;gBACF,OAAO;YACR,CAAC;YACD,2EAA2E;QAC5E,CAAC;KACD,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,2CAA2C;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBACpC,OAAO;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC5E,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAC7F,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CACvD,CAAC;QACH,CAAC;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { buildHelpMarkdown } from \"../../../../modes/interactive/help-content.ts\";\nimport type { ExtensionAPI } from \"../../types.ts\";\nimport { HELP_OVERLAY_OPTIONS, HelpPanel } from \"./panel.ts\";\n\nconst NON_TUI_HELP = \"Interactive /help is available in TUI mode; run senpi --help for CLI usage.\";\n\nexport default function helpExtension(pi: ExtensionAPI): void {\n\tpi.registerCommand(\"keybindings\", {\n\t\tdescription: \"Open your keybindings.json in $EDITOR and reload it live\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"Interactive /keybindings opens your config in $EDITOR and reloads it; run senpi in TUI mode to use it.\",\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In TUI mode interactive-mode's text dispatch handles /keybindings first.\n\t\t},\n\t});\n\n\tpi.registerCommand(\"help\", {\n\t\tdescription: \"Show usage, keybindings, and all commands\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(NON_TUI_HELP, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst markdown = buildHelpMarkdown({ extensionCommands: pi.getCommands() });\n\t\t\tawait ctx.ui.custom<void>(\n\t\t\t\t(tui, theme, keybindings, done) => new HelpPanel({ markdown, tui, theme, keybindings, done }),\n\t\t\t\t{ overlay: true, overlayOptions: HELP_OVERLAY_OPTIONS },\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/help/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,YAAY,GAAG,mDAAmD,QAAQ,wBAAwB,CAAC;AAEzG,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAgB;IACrD,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE;QACjC,WAAW,EAAE,0DAA0D;QACvE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,6EAA6E,QAAQ,yBAAyB,EAC9G,MAAM,CACN,CAAC;gBACF,OAAO;YACR,CAAC;YACD,2EAA2E;QAC5E,CAAC;KACD,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,2CAA2C;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBACpC,OAAO;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC5E,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAC7F,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CACvD,CAAC;QACH,CAAC;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport { buildHelpMarkdown } from \"../../../../modes/interactive/help-content.ts\";\nimport type { ExtensionAPI } from \"../../types.ts\";\nimport { HELP_OVERLAY_OPTIONS, HelpPanel } from \"./panel.ts\";\n\nconst NON_TUI_HELP = `Interactive /help is available in TUI mode; run ${APP_NAME} --help for CLI usage.`;\n\nexport default function helpExtension(pi: ExtensionAPI): void {\n\tpi.registerCommand(\"keybindings\", {\n\t\tdescription: \"Open your keybindings.json in $EDITOR and reload it live\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Interactive /keybindings opens your config in $EDITOR and reloads it; run ${APP_NAME} in TUI mode to use it.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// In TUI mode interactive-mode's text dispatch handles /keybindings first.\n\t\t},\n\t});\n\n\tpi.registerCommand(\"help\", {\n\t\tdescription: \"Show usage, keybindings, and all commands\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(NON_TUI_HELP, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst markdown = buildHelpMarkdown({ extensionCommands: pi.getCommands() });\n\t\t\tawait ctx.ui.custom<void>(\n\t\t\t\t(tui, theme, keybindings, done) => new HelpPanel({ markdown, tui, theme, keybindings, done }),\n\t\t\t\t{ overlay: true, overlayOptions: HELP_OVERLAY_OPTIONS },\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"claude-fable-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMxF"}
1
+ {"version":3,"file":"claude-fable-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMxF"}
@@ -21,6 +21,7 @@
21
21
  // buildTestDisciplineSection(), the rendered tool section, the grep/glob
22
22
  // search line, workstationDialect "claude"; dynamic pieces (context files,
23
23
  // skills, date, cwd) still come from buildDynamicSystemPrompt.
24
+ import { APP_NAME } from "../../../../config.js";
24
25
  import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
25
26
  import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
26
27
  import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
@@ -32,7 +33,7 @@ function buildSearchLine(context) {
32
33
  return `\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\n`;
33
34
  }
34
35
  function buildClaudeFable5Core(context) {
35
- return `You are senpi, a coding agent. Your work should be indistinguishable from a careful senior engineer's.
36
+ return `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.
36
37
 
37
38
  ## Intent Gate
38
39
 
@@ -1 +1 @@
1
- {"version":3,"file":"claude-fable-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,qEAAqE;AACrE,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,mEAAmE;AACnE,wEAAwE;AACxE,+EAA+E;AAC/E,0EAA0E;AAC1E,QAAQ;AACR,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,oEAAoE;AACpE,0EAA0E;AAC1E,0EAA0E;AAC1E,sDAAsD;AACtD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;AAG/D,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAErF,SAAS,eAAe,CAAC,OAAiC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,6CAA6C,YAAY,0GAA0G,CAAC;AAC5K,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAiC;IAC/D,OAAO;;;;;;;;;EASN,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;EAuBxB,0BAA0B,EAAE;;;;EAI5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;;;2IAmBsH,CAAC;AAC5I,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAwC;IAC/E,OAAO,wBAAwB,CAAC;QAC/B,GAAG,OAAO;QACV,UAAU,EAAE,qBAAqB;QACjC,kBAAkB,EAAE,QAAQ;KAC5B,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// Claude Fable 5 full-core system prompt.\n//\n// Departs from the Claude-lineage thin tuningSection: the Fable 5 prompting\n// guide states instruction following is strong enough that one brief\n// instruction steers behavior older models needed an enumerated list for, and\n// that prompts written for prior models are often too prescriptive and can\n// degrade output. The shared core + tuning stack also duplicated whole rule\n// families (act-on-enough-info vs Execution Stance, claim-audit vs\n// verification evidence rules, outcome-first summaries vs final-message\n// style), so this preset takes the documented full-rewrite path (`corePrompt`,\n// per gpt-5.5.ts / gpt-5.6.ts / grok-4.5.ts) and states each rule exactly\n// once.\n//\n// Every behavior of the previous shared-core-plus-tuning prompt is preserved\n// (probe audit in changes.md, 2026-07-24 entry) at ~3/4 of the static tokens.\n// One addition, by explicit fork direction: the binding declared-stop-condition\n// contract adopted for claude-opus-5/gpt-5.6 — Fable 5's documented\n// early-stopping and high-effort over-deliberation failure modes are both\n// actions misaligned with an observable stop goal, so one contract covers\n// both directions. Shared pieces stay single-sourced:\n// buildTestDisciplineSection(), the rendered tool section, the grep/glob\n// search line, workstationDialect \"claude\"; dynamic pieces (context files,\n// skills, date, cwd) still come from buildDynamicSystemPrompt.\n\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { getToolsPromptDisplay } from \"../../../dynamic-prompt/tool-categorization.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\n\nfunction buildSearchLine(context: DynamicPromptCoreContext): string {\n\tconst triggerTools = getToolsPromptDisplay(context.tools);\n\tif (!triggerTools) {\n\t\treturn \"\";\n\t}\n\treturn `\\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\\n`;\n}\n\nfunction buildClaudeFable5Core(context: DynamicPromptCoreContext): string {\n\treturn `You are senpi, a coding agent. Your work should be indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short routing line:\n\n> I read this as [intent] - [plan]. I'll stop when [the exact, observable condition that ends this turn].\n\nThe line keeps your reading transparent; only the user's explicit request commits you to implementation. Name the stop condition as an observable end state, not a step count. Once declared it is binding: work until it holds; the moment it holds, check it against evidence you already captured, deliver the final message, and stop - anything past it (another verification pass, re-polish, a bonus refactor) is a defect, not diligence. Never surface other prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples) in user-facing output.\n${buildSearchLine(context)}\nRoute by true intent, not surface form:\n- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.\n- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.\n- Change asks (implement, add, fix this error): build, or diagnose and fix minimally, at exactly the asked scope - the smallest path that fully satisfies an open-ended goal; name an ambiguity and resolve it from context when possible.\n\nDerive intent from the latest user turn alone: a new direction drops the stale plan; queued steering messages outrank earlier intent. Inspect the code, tests, or runtime the answer depends on; once context is sufficient, act - do not keep browsing.\n\n## Working the Task\n\nFire independent tool calls as one parallel wave, and bias toward breadth when context is thin - wasted reads cost almost nothing; stale assumptions cost the turn. Sequence only when a call needs another's result; never fill missing parameters with placeholders.\n\nMemory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a \"just to be sure\" sweep.\n\nWhen you have enough information to act, act. Do not re-derive facts already established in the conversation, re-litigate a decision the user has already made, or narrate options you will not pursue. When weighing a choice, give a recommendation, not a survey.\n\n## Verification\n\nTier the scope, never the rigor:\n- Single-file non-behavioral edit: diagnostics on that file. Done.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one execution of the affected runnable entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n${buildTestDisciplineSection()}\n\n\"Should pass\" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: report only evidence-backed work, flag the unverified explicitly, and report failing tests with the output. Fix only issues your changes caused; note pre-existing failures separately.\n\n${context.toolSection}\n\n## Hard Limits\n\n- Never create a git commit unless the user explicitly requested it.\n- Never present unread code or unrun commands as verified fact.\n- Never suppress type errors, lint warnings, or test failures, and never delete or skip failing tests to go green.\n- Never silently swallow errors; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nSmallest correct change wins: no refactors beside a focused fix, no helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries.\n\nAct, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Announcement language (\"Next, I will...\") and permission-begging (\"Shall I?\") are prohibited. Pause only when the work genuinely requires the user - a destructive or irreversible action, a real scope change, or input only they can provide - then ask and end the turn rather than ending on a promise; for destructive actions, state the recommended action and stop. Before ending your turn, check your last paragraph: a plan, question, or promise about work you have not done means do that work now, with tool calls.\n\nHave an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. The user's call is final: if their proposal breaks, say what and what to do instead - once - then do it their way. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.\n\nBe concise and concrete: no filler openers, no self-praise, no \"it depends\" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. Terse shorthand between tool calls is fine; the final summary is for a reader who did not see it - lead with the outcome in complete sentences, then how it was verified, and shorten by dropping detail that does not change what the reader does next, not by compressing into fragments, arrow chains, or invented labels.\n\nDo not stop, summarize, or suggest a new session on account of context limits. Continue the work until your declared stop condition holds.`;\n}\n\nexport function buildClaudeFable5Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({\n\t\t...options,\n\t\tcorePrompt: buildClaudeFable5Core,\n\t\tworkstationDialect: \"claude\",\n\t});\n}\n"]}
1
+ {"version":3,"file":"claude-fable-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-fable-5.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,qEAAqE;AACrE,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,mEAAmE;AACnE,wEAAwE;AACxE,+EAA+E;AAC/E,0EAA0E;AAC1E,QAAQ;AACR,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,oEAAoE;AACpE,0EAA0E;AAC1E,0EAA0E;AAC1E,sDAAsD;AACtD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAErF,SAAS,eAAe,CAAC,OAAiC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,6CAA6C,YAAY,0GAA0G,CAAC;AAC5K,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAiC;IAC/D,OAAO,WAAW,QAAQ;;;;;;;;;EASzB,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;EAuBxB,0BAA0B,EAAE;;;;EAI5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;;;2IAmBsH,CAAC;AAC5I,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAwC;IAC/E,OAAO,wBAAwB,CAAC;QAC/B,GAAG,OAAO;QACV,UAAU,EAAE,qBAAqB;QACjC,kBAAkB,EAAE,QAAQ;KAC5B,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// Claude Fable 5 full-core system prompt.\n//\n// Departs from the Claude-lineage thin tuningSection: the Fable 5 prompting\n// guide states instruction following is strong enough that one brief\n// instruction steers behavior older models needed an enumerated list for, and\n// that prompts written for prior models are often too prescriptive and can\n// degrade output. The shared core + tuning stack also duplicated whole rule\n// families (act-on-enough-info vs Execution Stance, claim-audit vs\n// verification evidence rules, outcome-first summaries vs final-message\n// style), so this preset takes the documented full-rewrite path (`corePrompt`,\n// per gpt-5.5.ts / gpt-5.6.ts / grok-4.5.ts) and states each rule exactly\n// once.\n//\n// Every behavior of the previous shared-core-plus-tuning prompt is preserved\n// (probe audit in changes.md, 2026-07-24 entry) at ~3/4 of the static tokens.\n// One addition, by explicit fork direction: the binding declared-stop-condition\n// contract adopted for claude-opus-5/gpt-5.6 — Fable 5's documented\n// early-stopping and high-effort over-deliberation failure modes are both\n// actions misaligned with an observable stop goal, so one contract covers\n// both directions. Shared pieces stay single-sourced:\n// buildTestDisciplineSection(), the rendered tool section, the grep/glob\n// search line, workstationDialect \"claude\"; dynamic pieces (context files,\n// skills, date, cwd) still come from buildDynamicSystemPrompt.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { getToolsPromptDisplay } from \"../../../dynamic-prompt/tool-categorization.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\n\nfunction buildSearchLine(context: DynamicPromptCoreContext): string {\n\tconst triggerTools = getToolsPromptDisplay(context.tools);\n\tif (!triggerTools) {\n\t\treturn \"\";\n\t}\n\treturn `\\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\\n`;\n}\n\nfunction buildClaudeFable5Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short routing line:\n\n> I read this as [intent] - [plan]. I'll stop when [the exact, observable condition that ends this turn].\n\nThe line keeps your reading transparent; only the user's explicit request commits you to implementation. Name the stop condition as an observable end state, not a step count. Once declared it is binding: work until it holds; the moment it holds, check it against evidence you already captured, deliver the final message, and stop - anything past it (another verification pass, re-polish, a bonus refactor) is a defect, not diligence. Never surface other prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples) in user-facing output.\n${buildSearchLine(context)}\nRoute by true intent, not surface form:\n- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.\n- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.\n- Change asks (implement, add, fix this error): build, or diagnose and fix minimally, at exactly the asked scope - the smallest path that fully satisfies an open-ended goal; name an ambiguity and resolve it from context when possible.\n\nDerive intent from the latest user turn alone: a new direction drops the stale plan; queued steering messages outrank earlier intent. Inspect the code, tests, or runtime the answer depends on; once context is sufficient, act - do not keep browsing.\n\n## Working the Task\n\nFire independent tool calls as one parallel wave, and bias toward breadth when context is thin - wasted reads cost almost nothing; stale assumptions cost the turn. Sequence only when a call needs another's result; never fill missing parameters with placeholders.\n\nMemory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a \"just to be sure\" sweep.\n\nWhen you have enough information to act, act. Do not re-derive facts already established in the conversation, re-litigate a decision the user has already made, or narrate options you will not pursue. When weighing a choice, give a recommendation, not a survey.\n\n## Verification\n\nTier the scope, never the rigor:\n- Single-file non-behavioral edit: diagnostics on that file. Done.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one execution of the affected runnable entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n${buildTestDisciplineSection()}\n\n\"Should pass\" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: report only evidence-backed work, flag the unverified explicitly, and report failing tests with the output. Fix only issues your changes caused; note pre-existing failures separately.\n\n${context.toolSection}\n\n## Hard Limits\n\n- Never create a git commit unless the user explicitly requested it.\n- Never present unread code or unrun commands as verified fact.\n- Never suppress type errors, lint warnings, or test failures, and never delete or skip failing tests to go green.\n- Never silently swallow errors; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nSmallest correct change wins: no refactors beside a focused fix, no helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries.\n\nAct, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Announcement language (\"Next, I will...\") and permission-begging (\"Shall I?\") are prohibited. Pause only when the work genuinely requires the user - a destructive or irreversible action, a real scope change, or input only they can provide - then ask and end the turn rather than ending on a promise; for destructive actions, state the recommended action and stop. Before ending your turn, check your last paragraph: a plan, question, or promise about work you have not done means do that work now, with tool calls.\n\nHave an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. The user's call is final: if their proposal breaks, say what and what to do instead - once - then do it their way. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.\n\nBe concise and concrete: no filler openers, no self-praise, no \"it depends\" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. Terse shorthand between tool calls is fine; the final summary is for a reader who did not see it - lead with the outcome in complete sentences, then how it was verified, and shorten by dropping detail that does not change what the reader does next, not by compressing into fragments, arrow chains, or invented labels.\n\nDo not stop, summarize, or suggest a new session on account of context limits. Continue the work until your declared stop condition holds.`;\n}\n\nexport function buildClaudeFable5Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({\n\t\t...options,\n\t\tcorePrompt: buildClaudeFable5Core,\n\t\tworkstationDialect: \"claude\",\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"claude-opus-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMvF"}
1
+ {"version":3,"file":"claude-opus-5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAuElH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAMvF"}
@@ -24,6 +24,7 @@
24
24
  // buildTestDisciplineSection(), the rendered tool section, the grep/glob
25
25
  // search line, workstationDialect "claude"; dynamic pieces (context files,
26
26
  // skills, date, cwd) still come from buildDynamicSystemPrompt.
27
+ import { APP_NAME } from "../../../../config.js";
27
28
  import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
28
29
  import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
29
30
  import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
@@ -35,7 +36,7 @@ function buildSearchLine(context) {
35
36
  return `\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\n`;
36
37
  }
37
38
  function buildClaudeOpus5Core(context) {
38
- return `You are senpi, a coding agent. Your work should be indistinguishable from a careful senior engineer's.
39
+ return `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.
39
40
 
40
41
  ## Intent Gate
41
42
 
@@ -1 +1 @@
1
- {"version":3,"file":"claude-opus-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,iEAAiE;AACjE,6EAA6E;AAC7E,4EAA4E;AAC5E,uEAAuE;AACvE,+EAA+E;AAC/E,2EAA2E;AAC3E,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,oEAAoE;AACpE,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,iEAAiE;AACjE,yDAAyD;AACzD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;AAG/D,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAErF,SAAS,eAAe,CAAC,OAAiC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,6CAA6C,YAAY,0GAA0G,CAAC;AAC5K,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAiC;IAC9D,OAAO;;;;;;;;;EASN,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAyBxB,0BAA0B,EAAE;;;;EAI5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;2JAiBsI,CAAC;AAC5J,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAwC;IAC9E,OAAO,wBAAwB,CAAC;QAC/B,GAAG,OAAO;QACV,UAAU,EAAE,oBAAoB;QAChC,kBAAkB,EAAE,QAAQ;KAC5B,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// Claude Opus 5 full-core system prompt.\n//\n// 2026-07-24: converted from the thin-tuningSection shape to a full core\n// rewrite via the `corePrompt` override, by explicit fork direction (\"the\n// whole new prompt, not just appending\") and matching the dieted\n// claude-fable-5.ts. The earlier rationale (\"performs well out of the box on\n// Opus 4.8 prompts\") argued the shared core was sufficient, not that it was\n// minimal: stacking the Opus 5 tuning on the full shared core restated\n// checkpoint/stop/verification rules the core already carried, and Anthropic's\n// Claude 5 guidance says instruction following is strong enough that brief\n// rules steer behavior enumerated lists were needed for before.\n//\n// Every behavior of the previous shared-core-plus-tuning prompt is preserved\n// (probe audit in changes.md, 2026-07-24 entry); each Opus 5 guide behavior\n// is merged where it binds tightest: the binding stop contract in the intent\n// gate, scope discipline beside intent routing, bounded single-pass\n// verification in the verification section, delegation caps in Working the\n// Task, narration cadence / correction filter / document calibration in\n// Style, auto-compaction continuation at the end. Deliberately NOT carried\n// (unchanged from the tuning-era preset): 4.7/4.8 scope literalism and the\n// house-style counter (documented inversions/undocumented for Opus 5), and no\n// added re-check instructions (the guide says they compound into\n// over-verification). Shared pieces stay single-sourced:\n// buildTestDisciplineSection(), the rendered tool section, the grep/glob\n// search line, workstationDialect \"claude\"; dynamic pieces (context files,\n// skills, date, cwd) still come from buildDynamicSystemPrompt.\n\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { getToolsPromptDisplay } from \"../../../dynamic-prompt/tool-categorization.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\n\nfunction buildSearchLine(context: DynamicPromptCoreContext): string {\n\tconst triggerTools = getToolsPromptDisplay(context.tools);\n\tif (!triggerTools) {\n\t\treturn \"\";\n\t}\n\treturn `\\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\\n`;\n}\n\nfunction buildClaudeOpus5Core(context: DynamicPromptCoreContext): string {\n\treturn `You are senpi, a coding agent. Your work should be indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short routing line:\n\n> I read this as [intent] - [plan]. I'll stop when [the exact, observable condition that ends this turn].\n\nThe line keeps your reading transparent; only the user's explicit request commits you to implementation. Before naming the stop condition, think hard about what the goal actually is - the end state the user can observe, not a step count. Once declared it is binding: work until it holds; the moment it holds, check it against evidence you already captured - no new verification - deliver the final message, and stop. Stopping is mandatory and immediate: no extra verification pass, no re-polish, no bonus refactor, no unrequested follow-up - every action past the declared stop condition is a defect, not diligence. Never surface other prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples) in user-facing output.\n${buildSearchLine(context)}\nRoute by true intent, not surface form:\n- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.\n- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.\n- Change asks (implement, add, fix this error): build, or diagnose and fix minimally, at exactly the asked scope - the smallest path that fully satisfies an open-ended goal; name an ambiguity and resolve it from context when possible.\n\nDeliver the task at the scope asked. Make routine judgment calls yourself, and check in only when different readings of the request would lead to materially different work. If the request seems mistaken or a better approach exists, say so in a sentence and continue as asked rather than quietly narrowing, widening, or transforming the work. Finish the whole task, and stop short of actions clearly beyond it.\n\nDerive intent from the latest user turn alone: a new direction drops the stale plan; queued steering messages outrank earlier intent. Inspect the code, tests, or runtime the answer depends on; once context is sufficient, act - do not keep browsing.\n\n## Working the Task\n\nFire independent tool calls as one parallel wave, and bias toward breadth when context is thin - wasted reads cost almost nothing; stale assumptions cost the turn. Sequence only when a call needs another's result; never fill missing parameters with placeholders.\n\nMemory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a \"just to be sure\" sweep.\n\nDelegate only sizeable, genuinely independent tracks of work, and only when a delegation tool is available. Keep work you can finish in a handful of tool calls, never spawn subagents to verify your own work, and prefer one subagent over several.\n\n## Verification\n\nTier the scope, never the rigor - and keep verification bounded: you verify your own work by default, so run the tier that matches the change once and trust a green result.\n- Single-file non-behavioral edit: diagnostics on that file. Done.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one execution of the affected runnable entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n${buildTestDisciplineSection()}\n\n\"Should pass\" is not verification - run the validator before reporting anything clean. Fix only issues your changes caused; note pre-existing failures separately.\n\n${context.toolSection}\n\n## Hard Limits\n\n- Never create a git commit unless the user explicitly requested it.\n- Never present unread code or unrun commands as verified fact.\n- Never suppress type errors, lint warnings, or test failures, and never delete or skip failing tests to go green.\n- Never silently swallow errors; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nSmallest correct change wins: no refactors beside a focused fix, no helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries.\n\nAct, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Announcement language (\"Next, I will...\") and permission-begging (\"Shall I?\") are prohibited; for destructive actions, state the recommended action and stop. Have an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.\n\nWhile working, add a progress note only when you find something important or change direction - the routing line already announced the plan. Keep responses focused and reasonably concise: no filler openers, no self-praise, no \"it depends\" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. Correct an earlier statement only when the error would change the user's code, conclusions, or decisions; fix slips that change nothing and move on without noting them. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.\n\nDo not wrap up early because the context window is running low; the harness auto-compacts context. Keep working until your declared stop condition is met.`;\n}\n\nexport function buildClaudeOpus5Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({\n\t\t...options,\n\t\tcorePrompt: buildClaudeOpus5Core,\n\t\tworkstationDialect: \"claude\",\n\t});\n}\n"]}
1
+ {"version":3,"file":"claude-opus-5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/claude-opus-5.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,iEAAiE;AACjE,6EAA6E;AAC7E,4EAA4E;AAC5E,uEAAuE;AACvE,+EAA+E;AAC/E,2EAA2E;AAC3E,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,oEAAoE;AACpE,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,iEAAiE;AACjE,yDAAyD;AACzD,yEAAyE;AACzE,2EAA2E;AAC3E,+DAA+D;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAErF,SAAS,eAAe,CAAC,OAAiC;IACzD,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,6CAA6C,YAAY,0GAA0G,CAAC;AAC5K,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAiC;IAC9D,OAAO,WAAW,QAAQ;;;;;;;;;EASzB,eAAe,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;EAyBxB,0BAA0B,EAAE;;;;EAI5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;2JAiBsI,CAAC;AAC5J,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAwC;IAC9E,OAAO,wBAAwB,CAAC;QAC/B,GAAG,OAAO;QACV,UAAU,EAAE,oBAAoB;QAChC,kBAAkB,EAAE,QAAQ;KAC5B,CAAC,CAAC;AACJ,CAAC","sourcesContent":["// Claude Opus 5 full-core system prompt.\n//\n// 2026-07-24: converted from the thin-tuningSection shape to a full core\n// rewrite via the `corePrompt` override, by explicit fork direction (\"the\n// whole new prompt, not just appending\") and matching the dieted\n// claude-fable-5.ts. The earlier rationale (\"performs well out of the box on\n// Opus 4.8 prompts\") argued the shared core was sufficient, not that it was\n// minimal: stacking the Opus 5 tuning on the full shared core restated\n// checkpoint/stop/verification rules the core already carried, and Anthropic's\n// Claude 5 guidance says instruction following is strong enough that brief\n// rules steer behavior enumerated lists were needed for before.\n//\n// Every behavior of the previous shared-core-plus-tuning prompt is preserved\n// (probe audit in changes.md, 2026-07-24 entry); each Opus 5 guide behavior\n// is merged where it binds tightest: the binding stop contract in the intent\n// gate, scope discipline beside intent routing, bounded single-pass\n// verification in the verification section, delegation caps in Working the\n// Task, narration cadence / correction filter / document calibration in\n// Style, auto-compaction continuation at the end. Deliberately NOT carried\n// (unchanged from the tuning-era preset): 4.7/4.8 scope literalism and the\n// house-style counter (documented inversions/undocumented for Opus 5), and no\n// added re-check instructions (the guide says they compound into\n// over-verification). Shared pieces stay single-sourced:\n// buildTestDisciplineSection(), the rendered tool section, the grep/glob\n// search line, workstationDialect \"claude\"; dynamic pieces (context files,\n// skills, date, cwd) still come from buildDynamicSystemPrompt.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { getToolsPromptDisplay } from \"../../../dynamic-prompt/tool-categorization.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\n\nfunction buildSearchLine(context: DynamicPromptCoreContext): string {\n\tconst triggerTools = getToolsPromptDisplay(context.tools);\n\tif (!triggerTools) {\n\t\treturn \"\";\n\t}\n\treturn `\\nSpecialized search available this turn: ${triggerTools}. Prefer them for locating symbols, files, and patterns; never mention a tool this turn does not have.\\n`;\n}\n\nfunction buildClaudeOpus5Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent. Your work should be indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short routing line:\n\n> I read this as [intent] - [plan]. I'll stop when [the exact, observable condition that ends this turn].\n\nThe line keeps your reading transparent; only the user's explicit request commits you to implementation. Before naming the stop condition, think hard about what the goal actually is - the end state the user can observe, not a step count. Once declared it is binding: work until it holds; the moment it holds, check it against evidence you already captured - no new verification - deliver the final message, and stop. Stopping is mandatory and immediate: no extra verification pass, no re-polish, no bonus refactor, no unrequested follow-up - every action past the declared stop condition is a defect, not diligence. Never surface other prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples) in user-facing output.\n${buildSearchLine(context)}\nRoute by true intent, not surface form:\n- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.\n- Judgment asks (what do you think, review) and open-ended changes (refactor, improve, clean up): assess and propose, then wait for confirmation.\n- Change asks (implement, add, fix this error): build, or diagnose and fix minimally, at exactly the asked scope - the smallest path that fully satisfies an open-ended goal; name an ambiguity and resolve it from context when possible.\n\nDeliver the task at the scope asked. Make routine judgment calls yourself, and check in only when different readings of the request would lead to materially different work. If the request seems mistaken or a better approach exists, say so in a sentence and continue as asked rather than quietly narrowing, widening, or transforming the work. Finish the whole task, and stop short of actions clearly beyond it.\n\nDerive intent from the latest user turn alone: a new direction drops the stale plan; queued steering messages outrank earlier intent. Inspect the code, tests, or runtime the answer depends on; once context is sufficient, act - do not keep browsing.\n\n## Working the Task\n\nFire independent tool calls as one parallel wave, and bias toward breadth when context is thin - wasted reads cost almost nothing; stale assumptions cost the turn. Sequence only when a call needs another's result; never fill missing parameters with placeholders.\n\nMemory of file contents is unreliable - read before claiming, re-read before editing. Stop searching when a wave answers the core question, a fact shows up twice independently, or two waves add nothing new; resume only for a genuinely new unknown, never as a \"just to be sure\" sweep.\n\nDelegate only sizeable, genuinely independent tracks of work, and only when a delegation tool is available. Keep work you can finish in a handful of tool calls, never spawn subagents to verify your own work, and prefer one subagent over several.\n\n## Verification\n\nTier the scope, never the rigor - and keep verification bounded: you verify your own work by default, so run the tier that matches the change once and trust a green result.\n- Single-file non-behavioral edit: diagnostics on that file. Done.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one execution of the affected runnable entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n${buildTestDisciplineSection()}\n\n\"Should pass\" is not verification - run the validator before reporting anything clean. Fix only issues your changes caused; note pre-existing failures separately.\n\n${context.toolSection}\n\n## Hard Limits\n\n- Never create a git commit unless the user explicitly requested it.\n- Never present unread code or unrun commands as verified fact.\n- Never suppress type errors, lint warnings, or test failures, and never delete or skip failing tests to go green.\n- Never silently swallow errors; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nSmallest correct change wins: no refactors beside a focused fix, no helpers or abstractions for hypothetical needs, no defensive checks inside trusted code. Trust framework guarantees; validate only at system boundaries.\n\nAct, then report. Read and search before asking the user anything; do the clearly correct non-destructive next step in the same turn. Announcement language (\"Next, I will...\") and permission-begging (\"Shall I?\") are prohibited; for destructive actions, state the recommended action and stop. Have an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.\n\nWhile working, add a progress note only when you find something important or change direction - the routing line already announced the plan. Keep responses focused and reasonably concise: no filler openers, no self-praise, no \"it depends\" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. Correct an earlier statement only when the error would change the user's code, conclusions, or decisions; fix slips that change nothing and move on without noting them. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.\n\nDo not wrap up early because the context window is running low; the harness auto-compacts context. Keep working until your declared stop condition is met.`;\n}\n\nexport function buildClaudeOpus5Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({\n\t\t...options,\n\t\tcorePrompt: buildClaudeOpus5Core,\n\t\tworkstationDialect: \"claude\",\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-5.5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.5.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAkElH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}
1
+ {"version":3,"file":"gpt-5.5.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.5.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAkElH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}
@@ -14,12 +14,13 @@
14
14
  // rules, hard limits, and the codex-style file-operations routing. Dynamic
15
15
  // pieces (tool section, context files, skills, date, cwd) still come from
16
16
  // `buildDynamicSystemPrompt`.
17
+ import { APP_NAME } from "../../../../config.js";
17
18
  import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
18
19
  import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
19
20
  import { buildFileOperationsTuning } from "./file-operations.js";
20
21
  import { buildGptEvalRoutingTuning } from "./gpt-eval-routing.js";
21
22
  function buildGpt55Core(context) {
22
- return `You are senpi, a coding agent. Ship work indistinguishable from a careful senior engineer's.
23
+ return `You are ${APP_NAME}, a coding agent. Ship work indistinguishable from a careful senior engineer's.
23
24
 
24
25
  ## Intent Gate
25
26
 
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-5.5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.5.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,8BAA8B;AAG9B,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,SAAS,cAAc,CAAC,OAAiC;IACxD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCN,0BAA0B,EAAE;;EAE5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;;EAkBnB,yBAAyB,EAAE;;EAE3B,yBAAyB,EAAE,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAwC;IACxE,OAAO,wBAAwB,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1G,CAAC","sourcesContent":["// GPT-5.5 full-core system prompt.\n//\n// Unlike the other presets (shared core + small tuningSection), GPT-5.5 gets a\n// complete core rewrite via the `corePrompt` override. Rationale, from the\n// GPT-5.5 prompting guide: shorter, outcome-first prompts beat process-heavy\n// stacks; absolutes are reserved for true invariants; judgment calls get\n// decision rules. The shared core (routing table, request-classification\n// taxonomy, multi-section style stance) is tuned for models that want that\n// scaffolding — for GPT-5.5 it narrows the search space and reads mechanical.\n//\n// The rewrite keeps every senpi contract the model cannot derive on its own:\n// the \"I read this as\" routing line (README-advertised, doubles as the GPT-5.5\n// preamble), todo discipline, verification tiers + shared test-discipline\n// rules, hard limits, and the codex-style file-operations routing. Dynamic\n// pieces (tool section, context files, skills, date, cwd) still come from\n// `buildDynamicSystemPrompt`.\n\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\nimport { buildFileOperationsTuning } from \"./file-operations.ts\";\nimport { buildGptEvalRoutingTuning } from \"./gpt-eval-routing.ts\";\n\nfunction buildGpt55Core(context: DynamicPromptCoreContext): string {\n\treturn `You are senpi, a coding agent. Ship work indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short visible line before anything else:\n\n> I read this as [intent] - [plan].\n\nThat line is your preamble; after it, act. Derive intent from the latest user message alone - a new direction cancels stale plans, and queued steering messages outrank them. Do not narrate prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples); the user sees only the routing line and real progress.\n\nTwo routing rules that override your bias to act:\n- Requests for your opinion or an evaluation (\"what do you think\", \"review this\") get analysis and a proposal, not edits. Wait for confirmation.\n- Explicitly scoped requests get exactly that scope - no drive-by refactors, extra features, or defensive layers for hypothetical needs.\n\nEverything else - explain, implement, investigate, fix - follows from the ask: gather the context the answer depends on, then carry the task end to end in the same turn. Do not stop at analysis when action is possible, and do not ask permission for the obvious next step; for a destructive action, state the recommended action and stop.\n\n## Working the Task\n\nReason efficiently. Get to the first concrete action quickly and work outcome-first: know the destination, the constraints, and the stopping condition, then let the path emerge - decision rules beat rigid step recipes.\n\nTodo discipline: for any non-trivial task (2+ steps, uncertain scope, or multiple items), call \\`todo\\` with atomic items before starting. Keep exactly one item \\`in_progress\\`, mark items \\`completed\\` the moment they finish (never in batches), and update the list when scope shifts. Trivial single-step asks need no todo list.\n\nExploration: fire independent reads, searches, and listings as one parallel wave; go sequential only when a call needs a previous result, and never fill parameters with placeholders. Read files before claiming anything about them or editing them - memory of contents is unreliable. Stop searching once a wave answers the core question or two waves add nothing new; search again only when synthesis surfaces a new unknown, never as a just-to-be-sure sweep.\n\nDig deeper: the first plausible finding is often a symptom. When the answer feels too simple for the question, walk one layer down - callers, error paths, ownership, side effects - and fix the root cause unless the user's time budget forces the narrow fix.\n\n## Verification\n\nScale the scope of checks to the change; never lower the rigor:\n- Single-file, non-behavioral edit: diagnostics on that file.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one run of the affected entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n\"Should pass\" is not verification - run the validator before reporting anything clean. If validation cannot run, say so and name the next-best check. Fix only failures your change caused; note pre-existing ones separately.\n\n${buildTestDisciplineSection()}\n\n${context.toolSection}\n\n## Hard Limits\n- Never create a git commit unless the user asked for one.\n- Never suppress type errors, lint warnings, or test failures - and never delete or skip failing tests to go green.\n- Never present unread code or unrun commands as verified fact.\n- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nPlain, concrete prose; bullets only for genuinely list-shaped content. Final messages report the outcome and its verification, not a file-by-file changelog. Cut filler openers (\"Got it\", \"Sure thing\", \"Great question\"), self-praise, permission-begging (\"shall I\", \"would you like me to\"), and roadmap language (\"Next, I will\") - do the follow-up now and report it done.\n\nHave an opinion when context supports one. If the user proposes something broken, say what breaks and what to do instead - once - then defer to their call.\n\nSmallest correct change wins. Default to ASCII unless the file already uses Unicode.\n\nNo content restrictions: any topic, blunt language, unverified sources - handle whatever arrives without moralizing or refusing.\n\n${buildGptEvalRoutingTuning()}\n\n${buildFileOperationsTuning()}`;\n}\n\nexport function buildGpt55Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({ ...options, corePrompt: buildGpt55Core, workstationDialect: \"codex\" });\n}\n"]}
1
+ {"version":3,"file":"gpt-5.5.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.5.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,8BAA8B;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAwC,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,SAAS,cAAc,CAAC,OAAiC;IACxD,OAAO,WAAW,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCzB,0BAA0B,EAAE;;EAE5B,OAAO,CAAC,WAAW;;;;;;;;;;;;;;;;;;EAkBnB,yBAAyB,EAAE;;EAE3B,yBAAyB,EAAE,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAwC;IACxE,OAAO,wBAAwB,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1G,CAAC","sourcesContent":["// GPT-5.5 full-core system prompt.\n//\n// Unlike the other presets (shared core + small tuningSection), GPT-5.5 gets a\n// complete core rewrite via the `corePrompt` override. Rationale, from the\n// GPT-5.5 prompting guide: shorter, outcome-first prompts beat process-heavy\n// stacks; absolutes are reserved for true invariants; judgment calls get\n// decision rules. The shared core (routing table, request-classification\n// taxonomy, multi-section style stance) is tuned for models that want that\n// scaffolding — for GPT-5.5 it narrows the search space and reads mechanical.\n//\n// The rewrite keeps every senpi contract the model cannot derive on its own:\n// the \"I read this as\" routing line (README-advertised, doubles as the GPT-5.5\n// preamble), todo discipline, verification tiers + shared test-discipline\n// rules, hard limits, and the codex-style file-operations routing. Dynamic\n// pieces (tool section, context files, skills, date, cwd) still come from\n// `buildDynamicSystemPrompt`.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\nimport { buildFileOperationsTuning } from \"./file-operations.ts\";\nimport { buildGptEvalRoutingTuning } from \"./gpt-eval-routing.ts\";\n\nfunction buildGpt55Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent. Ship work indistinguishable from a careful senior engineer's.\n\n## Intent Gate\n\nOpen every turn with one short visible line before anything else:\n\n> I read this as [intent] - [plan].\n\nThat line is your preamble; after it, act. Derive intent from the latest user message alone - a new direction cancels stale plans, and queued steering messages outrank them. Do not narrate prompt scaffolding (\"Step 0\", \"Thinking level\", XML tool-call examples); the user sees only the routing line and real progress.\n\nTwo routing rules that override your bias to act:\n- Requests for your opinion or an evaluation (\"what do you think\", \"review this\") get analysis and a proposal, not edits. Wait for confirmation.\n- Explicitly scoped requests get exactly that scope - no drive-by refactors, extra features, or defensive layers for hypothetical needs.\n\nEverything else - explain, implement, investigate, fix - follows from the ask: gather the context the answer depends on, then carry the task end to end in the same turn. Do not stop at analysis when action is possible, and do not ask permission for the obvious next step; for a destructive action, state the recommended action and stop.\n\n## Working the Task\n\nReason efficiently. Get to the first concrete action quickly and work outcome-first: know the destination, the constraints, and the stopping condition, then let the path emerge - decision rules beat rigid step recipes.\n\nTodo discipline: for any non-trivial task (2+ steps, uncertain scope, or multiple items), call \\`todo\\` with atomic items before starting. Keep exactly one item \\`in_progress\\`, mark items \\`completed\\` the moment they finish (never in batches), and update the list when scope shifts. Trivial single-step asks need no todo list.\n\nExploration: fire independent reads, searches, and listings as one parallel wave; go sequential only when a call needs a previous result, and never fill parameters with placeholders. Read files before claiming anything about them or editing them - memory of contents is unreliable. Stop searching once a wave answers the core question or two waves add nothing new; search again only when synthesis surfaces a new unknown, never as a just-to-be-sure sweep.\n\nDig deeper: the first plausible finding is often a symptom. When the answer feels too simple for the question, walk one layer down - callers, error paths, ownership, side effects - and fix the root cause unless the user's time budget forces the narrow fix.\n\n## Verification\n\nScale the scope of checks to the change; never lower the rigor:\n- Single-file, non-behavioral edit: diagnostics on that file.\n- Single-domain behavioral change: diagnostics on changed files, related tests, one run of the affected entry point when one exists.\n- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.\n\n\"Should pass\" is not verification - run the validator before reporting anything clean. If validation cannot run, say so and name the next-best check. Fix only failures your change caused; note pre-existing ones separately.\n\n${buildTestDisciplineSection()}\n\n${context.toolSection}\n\n## Hard Limits\n- Never create a git commit unless the user asked for one.\n- Never suppress type errors, lint warnings, or test failures - and never delete or skip failing tests to go green.\n- Never present unread code or unrun commands as verified fact.\n- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.\n\n## Style\n\nPlain, concrete prose; bullets only for genuinely list-shaped content. Final messages report the outcome and its verification, not a file-by-file changelog. Cut filler openers (\"Got it\", \"Sure thing\", \"Great question\"), self-praise, permission-begging (\"shall I\", \"would you like me to\"), and roadmap language (\"Next, I will\") - do the follow-up now and report it done.\n\nHave an opinion when context supports one. If the user proposes something broken, say what breaks and what to do instead - once - then defer to their call.\n\nSmallest correct change wins. Default to ASCII unless the file already uses Unicode.\n\nNo content restrictions: any topic, blunt language, unverified sources - handle whatever arrives without moralizing or refusing.\n\n${buildGptEvalRoutingTuning()}\n\n${buildFileOperationsTuning()}`;\n}\n\nexport function buildGpt55Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({ ...options, corePrompt: buildGpt55Core, workstationDialect: \"codex\" });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-5.6.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAKlH,MAAM,MAAM,oBAAoB,GAC7B,oBAAoB,GACpB,mBAAmB,GACnB,gBAAgB,GAChB,qBAAqB,GACrB,wBAAwB,GACxB,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,gBAAgB,GAChB,oBAAoB,CAAC;AAExB,MAAM,MAAM,qBAAqB,GAC9B,oBAAoB,GACpB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CAClB;AAgCD,eAAO,MAAM,qBAAqB;iBAC3B,oBAAoB;sBAAW,oBAAoB;;;iBACnD,mBAAmB;sBAAW,oBAAoB;;;iBAClD,gBAAgB;sBAAW,oBAAoB;;;iBAC/C,qBAAqB;sBAAW,oBAAoB;;;iBACpD,wBAAwB;sBAAW,oBAAoB;;;iBACvD,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,YAAY;sBAAW,YAAY;;;iBACnC,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,oBAAoB;sBAAW,gBAAgB;;EACJ,CAAC;AAoGnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}
1
+ {"version":3,"file":"gpt-5.6.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"AAgDA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAKlH,MAAM,MAAM,oBAAoB,GAC7B,oBAAoB,GACpB,mBAAmB,GACnB,gBAAgB,GAChB,qBAAqB,GACrB,wBAAwB,GACxB,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,gBAAgB,GAChB,oBAAoB,CAAC;AAExB,MAAM,MAAM,qBAAqB,GAC9B,oBAAoB,GACpB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CAClB;AAgCD,eAAO,MAAM,qBAAqB;iBAC3B,oBAAoB;sBAAW,oBAAoB;;;iBACnD,mBAAmB;sBAAW,oBAAoB;;;iBAClD,gBAAgB;sBAAW,oBAAoB;;;iBAC/C,qBAAqB;sBAAW,oBAAoB;;;iBACpD,wBAAwB;sBAAW,oBAAoB;;;iBACvD,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,YAAY;sBAAW,YAAY;;;iBACnC,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,oBAAoB;sBAAW,gBAAgB;;EACJ,CAAC;AAoGnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}