@cortexkit/opencode-magic-context 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/agent-disable.d.ts +22 -0
- package/dist/config/agent-disable.d.ts.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +7 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +82 -2
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config/transform-mode.d.ts +2 -0
- package/dist/config/transform-mode.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-n48c783v.js → conflict-warning-hook-fvpfvt0w.js} +1 -1
- package/dist/{derive-budgets-e9j09sjr.js → derive-budgets-9crp0cvd.js} +1 -1
- package/dist/features/builtin-commands/commands.d.ts +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts +57 -0
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +8 -1
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
- package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +35 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -4
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -0
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts +2 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
- package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
- package/dist/hooks/magic-context/event-handler.d.ts +7 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +11 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +9 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +30 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +27 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-ey1bc14z.js → index-b563sga5.js} +7 -264
- package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
- package/dist/{index-xyaekybw.js → index-dtas91s5.js} +6 -4
- package/dist/index-fcyvznch.js +279 -0
- package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
- package/dist/{index-c2gahrks.js → index-s0mdn690.js} +1599 -892
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1292 -623
- package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +11 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +10 -0
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +3 -7
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts +8 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-2yb2hfh2.js → recomp-orchestrator-8e82vmvb.js} +6 -4
- package/dist/send-session-notification-6njqewzk.js +20 -0
- package/dist/shared/conflict-detector.d.ts +38 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/conflict-fixer.d.ts +18 -1
- package/dist/shared/conflict-fixer.d.ts.map +1 -1
- package/dist/shared/context-limit-provenance.d.ts +3 -0
- package/dist/shared/context-limit-provenance.d.ts.map +1 -0
- package/dist/shared/escalation-bands.d.ts +9 -0
- package/dist/shared/escalation-bands.d.ts.map +1 -0
- package/dist/shared/format-threshold.d.ts +1 -1
- package/dist/shared/models-dev-cache.d.ts +29 -3
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +46 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/storage-permissions.d.ts +5 -0
- package/dist/shared/storage-permissions.d.ts.map +1 -0
- package/dist/{storage-meta-session-td6bwtky.js → storage-meta-session-xt41zbw4.js} +2 -1
- package/dist/tui/compaction-off.d.ts +13 -0
- package/dist/tui/compaction-off.d.ts.map +1 -0
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/dist/tui-compiled/compaction-off.d.ts +13 -0
- package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
- package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/agents/dreamer.ts +68 -0
- package/src/agents/hidden-agent-registrations.ts +331 -0
- package/src/agents/historian.ts +3 -0
- package/src/agents/language-directive.test.ts +138 -0
- package/src/agents/language-directive.ts +121 -0
- package/src/agents/magic-context-prompt.language.test.ts +35 -0
- package/src/agents/magic-context-prompt.test.ts +292 -0
- package/src/agents/magic-context-prompt.ts +182 -0
- package/src/agents/permissions.test.ts +252 -0
- package/src/agents/permissions.ts +186 -0
- package/src/agents/sidekick.ts +1 -0
- package/src/agents/smart-note-compiler.ts +1 -0
- package/src/config/agent-disable.ts +106 -0
- package/src/config/compaction-accessor-guard.test.ts +82 -0
- package/src/config/compaction-backcompat.test.ts +52 -0
- package/src/config/index.test.ts +904 -0
- package/src/config/index.ts +601 -0
- package/src/config/migrate-config-location.test.ts +332 -0
- package/src/config/migrate-config-location.ts +635 -0
- package/src/config/migrate-dreamer-v2.test.ts +287 -0
- package/src/config/migrate-dreamer-v2.ts +336 -0
- package/src/config/migrate-experimental.ts +159 -0
- package/src/config/project-security.test.ts +366 -0
- package/src/config/project-security.ts +588 -0
- package/src/config/prune-config-leaf.test.ts +78 -0
- package/src/config/prune-config-leaf.ts +68 -0
- package/src/config/removed-config-keys.test.ts +116 -0
- package/src/config/schema/agent-overrides.ts +45 -0
- package/src/config/schema/magic-context.test.ts +358 -0
- package/src/config/schema/magic-context.ts +1002 -0
- package/src/config/transform-mode.test.ts +62 -0
- package/src/config/transform-mode.ts +34 -0
- package/src/config/variable.test.ts +323 -0
- package/src/config/variable.ts +192 -0
- package/src/features/magic-context/defaults.ts +1 -0
- package/src/features/magic-context/dreamer/cron.ts +243 -0
- package/src/features/magic-context/dreamer/task-registry.ts +104 -0
- package/src/shared/conflict-detector.test.ts +121 -0
- package/src/shared/conflict-detector.ts +50 -3
- package/src/shared/conflict-fixer.test.ts +309 -0
- package/src/shared/conflict-fixer.ts +82 -5
- package/src/shared/context-limit-provenance.ts +6 -0
- package/src/shared/escalation-bands.test.ts +23 -0
- package/src/shared/escalation-bands.ts +18 -0
- package/src/shared/format-threshold.ts +1 -1
- package/src/shared/models-dev-cache.test.ts +171 -0
- package/src/shared/models-dev-cache.ts +195 -38
- package/src/shared/rpc-server.ts +27 -18
- package/src/shared/rpc-types.ts +46 -1
- package/src/shared/storage-permissions.ts +20 -0
- package/src/tui/compaction-off.test.ts +56 -0
- package/src/tui/compaction-off.ts +29 -0
- package/src/tui/data/context-db.ts +6 -0
- package/src/tui/index.tsx +113 -65
- package/src/tui/slots/sidebar-content.tsx +139 -83
- package/src/tui-compiled/compaction-off.ts +29 -0
- package/src/tui-compiled/data/context-db.ts +6 -0
- package/src/tui-compiled/index.tsx +558 -455
- package/src/tui-compiled/slots/sidebar-content.tsx +237 -161
- package/dist/send-session-notification-tghq9gnh.js +0 -11
- /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { COMPARTMENT_AGENT_SYSTEM_PROMPT } from "../hooks/magic-context/compartment-prompt";
|
|
4
|
+
import { withContentLanguageDirective } from "./language-directive";
|
|
5
|
+
import { buildMagicContextSection } from "./magic-context-prompt";
|
|
6
|
+
|
|
7
|
+
describe("Magic Context language guidance", () => {
|
|
8
|
+
it("keeps guidance bytes unchanged when language is unset or blank", () => {
|
|
9
|
+
const baseline = buildMagicContextSection(null, 20, true, true, false, false, false);
|
|
10
|
+
expect(buildMagicContextSection(null, 20, true, true, false, false, false, undefined)).toBe(
|
|
11
|
+
baseline,
|
|
12
|
+
);
|
|
13
|
+
expect(buildMagicContextSection(null, 20, true, true, false, false, false, " ")).toBe(
|
|
14
|
+
baseline,
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("keeps historian prompt bytes unchanged when language is unset", () => {
|
|
19
|
+
expect(
|
|
20
|
+
withContentLanguageDirective(COMPARTMENT_AGENT_SYSTEM_PROMPT, undefined, {
|
|
21
|
+
preserveUserQuotes: true,
|
|
22
|
+
}),
|
|
23
|
+
).toBe(COMPARTMENT_AGENT_SYSTEM_PROMPT);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("adds deterministic primary language guidance when set", () => {
|
|
27
|
+
const first = buildMagicContextSection(null, 20, true, true, false, false, false, "tr");
|
|
28
|
+
const second = buildMagicContextSection(null, 20, true, true, false, false, false, "tr");
|
|
29
|
+
const baseline = buildMagicContextSection(null, 20, true, true, false, false, false);
|
|
30
|
+
|
|
31
|
+
expect(first).toBe(second);
|
|
32
|
+
expect(first).toContain("Use Turkish (Türkçe) for your natural-language replies");
|
|
33
|
+
expect(first.startsWith(baseline)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { buildMagicContextSection } from "./magic-context-prompt";
|
|
3
|
+
|
|
4
|
+
const CAVEMAN_MARKER = "BEWARE";
|
|
5
|
+
const CAVEMAN_PHRASE_TAIL = "consciously revert to full sentences";
|
|
6
|
+
|
|
7
|
+
const KNOWN_AGENT_IDENTITIES = [
|
|
8
|
+
"sisyphus",
|
|
9
|
+
"atlas",
|
|
10
|
+
"hephaestus",
|
|
11
|
+
"sisyphus-junior",
|
|
12
|
+
"oracle",
|
|
13
|
+
"athena",
|
|
14
|
+
"athena-junior",
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
describe("buildMagicContextSection — generic guidance", () => {
|
|
18
|
+
it("emits the same generic guidance for all known agent identities", () => {
|
|
19
|
+
const generic = buildMagicContextSection(null, 20, true, false, false, false);
|
|
20
|
+
|
|
21
|
+
for (const agent of KNOWN_AGENT_IDENTITIES) {
|
|
22
|
+
expect(buildMagicContextSection(agent, 20, true, false, false, false)).toBe(generic);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("does not emit legacy agent-tailored guidance", () => {
|
|
27
|
+
const out = buildMagicContextSection("atlas", 20, true, false, false, false);
|
|
28
|
+
|
|
29
|
+
expect(out).toContain("### Reduction Triggers");
|
|
30
|
+
expect(out).toContain("Your current task requirements and constraints");
|
|
31
|
+
expect(out).not.toContain("CRITICAL — you run long sessions");
|
|
32
|
+
expect(out).not.toContain("delegation tool outputs from completed waves");
|
|
33
|
+
expect(out).not.toContain("council member response outputs");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("opens with the long-term-partner frame in BOTH ctx_reduce availability variants", () => {
|
|
37
|
+
const reduce = buildMagicContextSection(null, 20, true, false, false, false);
|
|
38
|
+
const noReduce = buildMagicContextSection(null, 20, false, false, false, false);
|
|
39
|
+
|
|
40
|
+
for (const out of [reduce, noReduce]) {
|
|
41
|
+
// Identity frame + the durability + no-scarcity + no-wind-down beats.
|
|
42
|
+
expect(out).toContain("long-term partner on this project");
|
|
43
|
+
expect(out).toContain("weeks, months, or even years");
|
|
44
|
+
expect(out).toContain("effectively unbounded");
|
|
45
|
+
expect(out).toContain("never a reason to wrap up, cut scope, rush, or defer");
|
|
46
|
+
expect(out).toContain("Finishing a task does not end the session");
|
|
47
|
+
expect(out).toContain("no compaction pauses");
|
|
48
|
+
// Frame is at the TOP — before the tool mechanics.
|
|
49
|
+
expect(out.indexOf("long-term partner")).toBeLessThan(out.indexOf("ctx_note"));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("uses the mode-specific partner-frame closer", () => {
|
|
54
|
+
const reduce = buildMagicContextSection(null, 20, true, false, false, false);
|
|
55
|
+
const noReduce = buildMagicContextSection(null, 20, false, false, false, false);
|
|
56
|
+
|
|
57
|
+
// reduce mode: agent participates in housekeeping
|
|
58
|
+
expect(reduce).toContain("Reduction prompts are routine housekeeping");
|
|
59
|
+
expect(reduce).not.toContain("there's nothing to prune");
|
|
60
|
+
// no-reduce mode: fully automatic, nothing to prune
|
|
61
|
+
expect(noReduce).toContain("there's nothing to prune and no warnings to act on");
|
|
62
|
+
expect(noReduce).not.toContain("Reduction prompts are routine housekeeping");
|
|
63
|
+
// Both keep the task-scope caveat.
|
|
64
|
+
for (const out of [reduce, noReduce]) {
|
|
65
|
+
expect(out).toContain("never let context size change");
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("no longer emits the scarcity-flavored 'compress early and often, don't wait for warnings' line", () => {
|
|
70
|
+
const reduce = buildMagicContextSection(null, 20, true, false, false, false);
|
|
71
|
+
expect(reduce).not.toContain("don't wait for warnings");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe("buildMagicContextSection — subagent mode", () => {
|
|
76
|
+
const subagent = () => buildMagicContextSection(null, 20, true, false, false, false, true);
|
|
77
|
+
|
|
78
|
+
it("emits ONLY the minimal §N§ + ctx_reduce mechanics", () => {
|
|
79
|
+
const out = subagent();
|
|
80
|
+
// Has the marker (injection idempotency) + the tag/ctx_reduce mechanics.
|
|
81
|
+
expect(out).toContain("## Magic Context");
|
|
82
|
+
expect(out).toContain("§N§ identifiers");
|
|
83
|
+
expect(out).toContain("ctx_reduce");
|
|
84
|
+
expect(out).toContain("The last 20 tags are protected");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("OMITS the long-term-partner frame and primary-only guidance", () => {
|
|
88
|
+
const out = subagent();
|
|
89
|
+
expect(out).not.toContain("long-term partner");
|
|
90
|
+
expect(out).not.toContain("weeks, months, or even years");
|
|
91
|
+
expect(out).not.toContain("### Reduction Triggers");
|
|
92
|
+
expect(out).not.toContain("ctx_memory");
|
|
93
|
+
expect(out).not.toContain("ctx_search");
|
|
94
|
+
expect(out).not.toContain("ctx_note");
|
|
95
|
+
expect(out).not.toContain("ctx_expand");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("threads protectedTags into the protected-count line", () => {
|
|
99
|
+
const out = buildMagicContextSection(null, 7, true, false, false, false, true);
|
|
100
|
+
expect(out).toContain("The last 7 tags are protected");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("is much shorter than the full primary block", () => {
|
|
104
|
+
const full = buildMagicContextSection(null, 20, true, false, false, false, false);
|
|
105
|
+
expect(subagent().length).toBeLessThan(full.length / 2);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("defaults subagentMode=false (legacy callers unaffected)", () => {
|
|
109
|
+
const sixArg = buildMagicContextSection(null, 20, true, false, false, false);
|
|
110
|
+
const explicitFalse = buildMagicContextSection(null, 20, true, false, false, false, false);
|
|
111
|
+
expect(sixArg).toBe(explicitFalse);
|
|
112
|
+
expect(sixArg).toContain("long-term partner");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("buildMagicContextSection: memory gating", () => {
|
|
117
|
+
// buildMagicContextSection's 9th positional parameter is memoryEnabled
|
|
118
|
+
// (defaults to true). The 7-arg legacy call below relies on that default.
|
|
119
|
+
it("memory ON (default) keeps the ctx_memory guidance and is byte-identical to legacy callers", () => {
|
|
120
|
+
const legacy = buildMagicContextSection(null, 20, true, false, false, false, false);
|
|
121
|
+
const memOn = buildMagicContextSection(
|
|
122
|
+
null,
|
|
123
|
+
20,
|
|
124
|
+
true,
|
|
125
|
+
false,
|
|
126
|
+
false,
|
|
127
|
+
false,
|
|
128
|
+
false,
|
|
129
|
+
undefined,
|
|
130
|
+
true,
|
|
131
|
+
);
|
|
132
|
+
expect(memOn).toBe(legacy);
|
|
133
|
+
expect(memOn).toContain("Use `ctx_memory`");
|
|
134
|
+
expect(memOn).toContain("**Save to memory proactively**");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("memory OFF drops ALL ctx_memory guidance but keeps ctx_search", () => {
|
|
138
|
+
const off = buildMagicContextSection(
|
|
139
|
+
null,
|
|
140
|
+
20,
|
|
141
|
+
true,
|
|
142
|
+
false,
|
|
143
|
+
false,
|
|
144
|
+
false,
|
|
145
|
+
false,
|
|
146
|
+
undefined,
|
|
147
|
+
false,
|
|
148
|
+
);
|
|
149
|
+
expect(off).not.toContain("ctx_memory");
|
|
150
|
+
expect(off).not.toContain("Save to memory proactively");
|
|
151
|
+
expect(off).toContain("Use `ctx_search`");
|
|
152
|
+
// no dangling blank line where the block was removed
|
|
153
|
+
expect(off).not.toContain("\n\nUse `ctx_search`");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("memory OFF gates the guidance in no-reduce mode too", () => {
|
|
157
|
+
const off = buildMagicContextSection(
|
|
158
|
+
null,
|
|
159
|
+
20,
|
|
160
|
+
false,
|
|
161
|
+
false,
|
|
162
|
+
false,
|
|
163
|
+
false,
|
|
164
|
+
false,
|
|
165
|
+
undefined,
|
|
166
|
+
false,
|
|
167
|
+
);
|
|
168
|
+
expect(off).not.toContain("ctx_memory");
|
|
169
|
+
expect(off).toContain("Use `ctx_search`");
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe("buildMagicContextSection — caveman compression warning", () => {
|
|
174
|
+
it("emits the warning when caveman is enabled and ctx_reduce is unavailable", () => {
|
|
175
|
+
const out = buildMagicContextSection(
|
|
176
|
+
null, // agent
|
|
177
|
+
20, // protectedTags (ignored in no-reduce path)
|
|
178
|
+
false, // ctx_reduce is unavailable in this session.
|
|
179
|
+
false, // dreamerEnabled
|
|
180
|
+
false, // temporalAwarenessEnabled
|
|
181
|
+
true, // cavemanTextCompressionEnabled
|
|
182
|
+
);
|
|
183
|
+
expect(out).toContain(CAVEMAN_MARKER);
|
|
184
|
+
expect(out).toContain(CAVEMAN_PHRASE_TAIL);
|
|
185
|
+
expect(out).toContain("DO NOT mimic this style");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("omits the warning when caveman is disabled", () => {
|
|
189
|
+
const out = buildMagicContextSection(
|
|
190
|
+
null,
|
|
191
|
+
20,
|
|
192
|
+
false, // ctx_reduce is unavailable in this session.
|
|
193
|
+
false, // dreamerEnabled
|
|
194
|
+
false, // temporalAwarenessEnabled
|
|
195
|
+
false, // cavemanTextCompressionEnabled = false
|
|
196
|
+
);
|
|
197
|
+
expect(out).not.toContain(CAVEMAN_MARKER);
|
|
198
|
+
expect(out).not.toContain(CAVEMAN_PHRASE_TAIL);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("emits the warning when ctx_reduce is callable and caveman is enabled", () => {
|
|
202
|
+
// Caveman compression is independent from ctx_reduce availability, so
|
|
203
|
+
// reduce-enabled primary guidance must still warn about rewritten prose.
|
|
204
|
+
const out = buildMagicContextSection(
|
|
205
|
+
null,
|
|
206
|
+
20,
|
|
207
|
+
true, // ctx_reduce is callable in this session.
|
|
208
|
+
false, // dreamerEnabled
|
|
209
|
+
false, // temporalAwarenessEnabled
|
|
210
|
+
true, // cavemanTextCompressionEnabled
|
|
211
|
+
);
|
|
212
|
+
expect(out).toContain(CAVEMAN_MARKER);
|
|
213
|
+
expect(out).toContain(CAVEMAN_PHRASE_TAIL);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("omits the warning by default (parameter optional)", () => {
|
|
217
|
+
// Old callers that didn't pass the new parameter must continue to
|
|
218
|
+
// produce identical output (no warning leaked into legacy paths).
|
|
219
|
+
const out = buildMagicContextSection(null, 20, false, false, false);
|
|
220
|
+
expect(out).not.toContain(CAVEMAN_MARKER);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("buildMagicContextSection — compaction-off guidance variant (#266 S4)", () => {
|
|
225
|
+
// Spec #266 decision #3: compaction-off mode reuses the EXISTING no-reduce
|
|
226
|
+
// guidance variant machinery — no third template. The variant is reached
|
|
227
|
+
// by passing ctxReduceCallable=false (which the process-global registration
|
|
228
|
+
// override in ctx-reduce-availability.ts forces when ctx_reduce is not
|
|
229
|
+
// registered). This suite pins the spec's guidance acceptance:
|
|
230
|
+
// - no ctx_reduce mention, no §N§ prefix advertising, no tag-recovery
|
|
231
|
+
// - memory/search/note/expand guidance present
|
|
232
|
+
// - byte-identical to the existing reduce-unavailable variant (no third
|
|
233
|
+
// template constant was introduced)
|
|
234
|
+
|
|
235
|
+
it("the compaction-off variant is byte-identical to the existing no-reduce variant", () => {
|
|
236
|
+
// The existing no-reduce variant is buildMagicContextSection(..., false, ...).
|
|
237
|
+
// Compaction-off reaches the SAME code path via the availability override,
|
|
238
|
+
// so the rendered text must be byte-identical — no third template.
|
|
239
|
+
const existingNoReduce = buildMagicContextSection(null, 20, false, false, false, false);
|
|
240
|
+
const compactionOff = buildMagicContextSection(null, 20, false, false, false, false);
|
|
241
|
+
expect(compactionOff).toBe(existingNoReduce);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it("does not advertise ctx_reduce, §N§ prefixes, or tag-based recovery", () => {
|
|
245
|
+
const out = buildMagicContextSection(null, 20, false, false, false, false);
|
|
246
|
+
// No ctx_reduce tool mention.
|
|
247
|
+
expect(out).not.toContain("ctx_reduce");
|
|
248
|
+
// No §N§ prefix SYSTEM DESCRIPTION / advertising. The reduce variant
|
|
249
|
+
// opens with "Messages and tool outputs are tagged with §N§
|
|
250
|
+
// identifiers" — that advertising line is absent here. (The
|
|
251
|
+
// `[dropped §N§]` sentinel appears only inside TOOL_HISTORY_GUIDANCE's
|
|
252
|
+
// "never reproduce these markers" prohibition list, which is shared
|
|
253
|
+
// by both variants and is not advertising; the spec pins reuse of the
|
|
254
|
+
// existing variant byte-identical, so that prohibition mention stays.)
|
|
255
|
+
expect(out).not.toContain("tagged with §N§ identifiers");
|
|
256
|
+
expect(out).not.toContain("Use `ctx_reduce`");
|
|
257
|
+
// No tag-based-recovery WORKFLOW wording. The expand line frames
|
|
258
|
+
// recovery around <session-history> summary headings and ctx_search
|
|
259
|
+
// message ordinals, not §N§ tags. "tag" appears only inside the
|
|
260
|
+
// shared TOOL_HISTORY_GUIDANCE prohibition ("never reproduce ..."),
|
|
261
|
+
// not as a recovery instruction.
|
|
262
|
+
expect(out).not.toMatch(/recover.*tag|tag.*recover/i);
|
|
263
|
+
expect(out).not.toContain("§N§ identifiers (e.g.");
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("still covers memory, search, notes, and ctx_expand guidance", () => {
|
|
267
|
+
const out = buildMagicContextSection(null, 20, false, false, false, false);
|
|
268
|
+
expect(out).toContain("ctx_search");
|
|
269
|
+
expect(out).toContain("ctx_expand");
|
|
270
|
+
expect(out).toContain("ctx_note");
|
|
271
|
+
expect(out).toContain("ctx_memory");
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("frames ctx_expand as recovery for summaries / ctx_search hits, not tag-based recovery", () => {
|
|
275
|
+
const out = buildMagicContextSection(null, 20, false, false, false, false);
|
|
276
|
+
// The expand line in the no-reduce variant references <session-history>
|
|
277
|
+
// summary headings and ctx_search message ordinals — not §N§ tags.
|
|
278
|
+
expect(out).toContain("ctx_expand");
|
|
279
|
+
expect(out).toContain("session-history");
|
|
280
|
+
expect(out).toContain("message ordinals");
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("the reduce variant DOES advertise §N§ and ctx_reduce (contrast for the off-mode assertion)", () => {
|
|
284
|
+
// This is the mutation-direction anchor: the reduce-on variant carries
|
|
285
|
+
// the §N§ + ctx_reduce advertising that the off-mode variant omits.
|
|
286
|
+
// If the off-mode variant ever leaked these, this contrast would
|
|
287
|
+
// still pass but the off-mode assertion above would go red.
|
|
288
|
+
const reduce = buildMagicContextSection(null, 20, true, false, false, false);
|
|
289
|
+
expect(reduce).toContain("ctx_reduce");
|
|
290
|
+
expect(reduce).toContain("tagged with §N§ identifiers");
|
|
291
|
+
});
|
|
292
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/** Generic magic context system prompt section shared by all agents. */
|
|
2
|
+
|
|
3
|
+
import { buildPrimaryLanguageDirective } from "./language-directive";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mindset frame that counters two trained priors which make agents
|
|
7
|
+
* self-sabotage under Magic Context:
|
|
8
|
+
* 1. Context-scarcity reflex — models trained on finite contexts wrap up, cut
|
|
9
|
+
* scope, or rush when usage looks high. Our reduction nudges accidentally
|
|
10
|
+
* trigger this.
|
|
11
|
+
* 2. Session = one task — models trained on one-session-per-task wind down when
|
|
12
|
+
* a task finishes instead of continuing as a durable partner.
|
|
13
|
+
* This frame is injected at the TOP of the section (before the mechanics) in both
|
|
14
|
+
* ctx_reduce modes so it sets the frame before the agent reads anything that could
|
|
15
|
+
* read as a scarcity signal.
|
|
16
|
+
*/
|
|
17
|
+
const LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
18
|
+
|
|
19
|
+
Most AI sessions are disposable: one session per task, discarded when it's done — like hiring a developer for a single bug fix and letting them go the moment they finish. Magic Context changes this completely. This session is a durable working relationship: you carry the full history and accumulated knowledge of this project, and you continue across many tasks, bugs, and features — with memory that persists across restarts. This session may continue for weeks, months, or even years.
|
|
20
|
+
|
|
21
|
+
Because of this:
|
|
22
|
+
- **Your context is continuously managed and effectively unbounded.** As the session grows, earlier turns are automatically compacted into \`<session-history>\` and stay fully retrievable via \`ctx_search\`/\`ctx_expand\`. You will not hit a context wall and you will not lose continuity mid-task.
|
|
23
|
+
- **High context usage is normal and fully handled** — never a reason to wrap up, cut scope, rush, or defer work. Keep going at full depth.
|
|
24
|
+
- **Finishing a task does not end the session.** Continue naturally into the next piece of work, carrying everything forward.
|
|
25
|
+
- **There are no compaction pauses.** Unlike native context management that stops you to summarize and restart, Magic Context compacts in the background — you stay in flow, uninterrupted, so there's no reason to artificially wind down.`;
|
|
26
|
+
|
|
27
|
+
/** Closer for sessions where ctx_reduce is callable — the agent has an active housekeeping role. */
|
|
28
|
+
const PARTNER_FRAME_CLOSER_REDUCE = `\nReduction prompts are routine housekeeping to keep the session fast and cheap — act on them as light maintenance, never as scarcity warnings. Keep individual operations efficient, but never let context size change *what* work you take on or *how thoroughly* you do it.`;
|
|
29
|
+
|
|
30
|
+
/** Closer for sessions where ctx_reduce is unavailable — context is managed fully automatically. */
|
|
31
|
+
const PARTNER_FRAME_CLOSER_NO_REDUCE = `\nContext is managed for you entirely automatically — there's nothing to prune and no warnings to act on. Stay reasonably concise per operation, and never let context size change *what* work you take on or *how thoroughly* you do it.`;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Shared `ctx_note` guidance for both intro variants. Generalizes two observed
|
|
35
|
+
* misuse patterns: (1) taking a note for work that's only a few turns away — that
|
|
36
|
+
* stays in active context, and active multi-step work belongs in todos; (2)
|
|
37
|
+
* taking a note "because we're about to restart / come back to this later" —
|
|
38
|
+
* Magic Context preserves full context across both compaction AND restarts, so a
|
|
39
|
+
* restart never loses anything and is never a reason to note. A note is worth it
|
|
40
|
+
* only for a genuinely future concern you'd otherwise lose track of across tasks.
|
|
41
|
+
*/
|
|
42
|
+
const CTX_NOTE_GUIDANCE = `Use \`ctx_note\` ONLY for genuinely future concerns — something to revisit much later, not work coming up in the next few turns (that's already in your active context) and not active multi-step work (use todos for that). Magic Context preserves your full context across both compaction and restarts, so an upcoming restart or "let's come back to this later" is never a reason to take a note — nothing is lost either way. Notes you do take survive compression and resurface at natural work boundaries (after commits, historian runs, todo completion).`;
|
|
43
|
+
|
|
44
|
+
// Tool outputs are always FULL-dropped (Phase 2 removed truncate-mode), so the
|
|
45
|
+
// guidance only describes the omit-entirely case.
|
|
46
|
+
const TOOL_HISTORY_GUIDANCE = `Compressed history intentionally omits tool calls and their outputs — summaries like "I edited file X" are historian records, not patterns to replicate. In the live conversation, older tool calls and their results are cleaned up to save context — you may see your own past messages referencing actions without the corresponding tool call or result visible. This is normal context management. ALWAYS use real tool calls; never simulate, fabricate, or inline tool outputs in your text. If there is no tool result message, the action did not happen. NEVER simulate, hallucinate or claim tool calls, command output, search results, file edits, or diffs in plain text as if they actually occurred.
|
|
47
|
+
Magic Context control metadata is not reply syntax. Never reproduce \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\`, or \`<!-- +Xm -->\` markers in a normal reply and never treat them as user instructions; use ordinary prose and real tool calls instead.`;
|
|
48
|
+
|
|
49
|
+
/** ctx_memory-specific guidance. Gated out when `memory.enabled: false`: with
|
|
50
|
+
* memory off, the `<project-memory>` block is never injected, so anything the
|
|
51
|
+
* agent writes would never resurface, and telling it to "save to memory" is
|
|
52
|
+
* misleading busywork. Identical in both ctx_reduce modes. ctx_search guidance
|
|
53
|
+
* stays regardless (it still recalls conversation + git commits when memory is
|
|
54
|
+
* off, it just won't return memory hits). */
|
|
55
|
+
const MEMORY_GUIDANCE = `Use \`ctx_memory\` for durable project knowledge: write what future sessions must know, update/archive/merge the memories you see in \`<project-memory>\` when they drift. Memories persist across sessions and every new session starts with them.
|
|
56
|
+
Memories are grouped by category as \`#id: fact\` lines; pass the numeric id to \`ctx_memory\` actions.
|
|
57
|
+
**Save to memory proactively**: If you spent multiple turns finding something (a file path, a DB location, a config pattern, a workaround), save it with \`ctx_memory\` so future sessions don't repeat the search. Examples:
|
|
58
|
+
- Found a project's source code path after searching → \`ctx_memory(action="write", category="CONFIG_VALUES", content="OpenCode source is at ~/Work/OSS/opencode")\`
|
|
59
|
+
- Discovered a non-obvious build/test command → \`ctx_memory(action="write", category="PROJECT_RULES", content="Always use scripts/release.sh for releases")\`
|
|
60
|
+
- Learned a constraint the hard way → \`ctx_memory(action="write", category="CONSTRAINTS", content="Dashboard Tauri build needs RGBA PNGs, not grayscale")\``;
|
|
61
|
+
|
|
62
|
+
/** Renders MEMORY_GUIDANCE + trailing newline when memory is on, else "". Placed
|
|
63
|
+
* before the ctx_search line so turning memory off removes the block without
|
|
64
|
+
* leaving a blank line (the memory-on output stays exactly as it was before
|
|
65
|
+
* this flag existed). */
|
|
66
|
+
function memoryGuidanceBlock(memoryEnabled: boolean): string {
|
|
67
|
+
return memoryEnabled ? `${MEMORY_GUIDANCE}\n` : "";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const BASE_INTRO = (
|
|
71
|
+
protectedTags: number,
|
|
72
|
+
memoryEnabled: boolean,
|
|
73
|
+
): string => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
74
|
+
Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space. Marking is NOT an immediate delete — it queues the content, which stays fully visible until space is actually needed (as soon as the next turn if you're already under pressure, much later if not), so mark a tool output as soon as you're done with it rather than hoarding the call for the end of the turn. The last ${protectedTags} tags are protected (marking one just queues it until it ages out). Syntax: "3-5", "1,2,9", or "1-5,8,12-15".
|
|
75
|
+
Do not announce or narrate \`ctx_reduce\` drops — just call the tool silently. Saying "I'll drop these outputs" wastes tokens the user does not care about.
|
|
76
|
+
${CTX_NOTE_GUIDANCE}
|
|
77
|
+
${memoryGuidanceBlock(memoryEnabled)}Use \`ctx_search\` to search across project memories, indexed git commits, and this session's full conversation history (including compacted parts) from one query.
|
|
78
|
+
Use \`ctx_expand\` to recover the raw conversation behind a summary under a \`## start-end · date · title\` heading inside \`<session-history>\` — pass the heading's start/end range when the summary is not enough (exact wording, values, error text).
|
|
79
|
+
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
80
|
+
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
81
|
+
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
82
|
+
- Need a config value, API key location, or environment detail → \`ctx_search(query="embedding provider configuration")\`
|
|
83
|
+
- Looking for how something was implemented previously → \`ctx_search(query="how does the dreamer lease work")\`
|
|
84
|
+
- Want to recall what was decided in an earlier conversation → \`ctx_search(query="dashboard release signing setup")\`
|
|
85
|
+
\`ctx_search\` returns ranked results from memories, git commits, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
86
|
+
${TOOL_HISTORY_GUIDANCE}
|
|
87
|
+
NEVER drop large ranges blindly (e.g., "1-50"). Review each tag before deciding.
|
|
88
|
+
Keep your user's instructions and intent — never drop a user message for its directive, even an old one. But a large block of pasted content inside a user message (logs, data dumps, long code, attachments) is fair to mark discardable once you've extracted what you need — it stays searchable via \`ctx_search\`.
|
|
89
|
+
NEVER drop assistant text messages unless they are exceptionally large. Your conversation messages are lightweight; only large tool outputs are worth dropping.
|
|
90
|
+
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
91
|
+
|
|
92
|
+
/** Intro when ctx_reduce is unavailable — no drop guidance, no ctx_reduce
|
|
93
|
+
* references, and no tag system description. When the session's tool allow-list
|
|
94
|
+
* denies ctx_reduce, transform.ts skips §N§ prefix injection entirely, so the
|
|
95
|
+
* agent never sees tags — describing a tagging system they can't observe just
|
|
96
|
+
* wastes tokens and (empirically) primes some models to emit malformed `§N">§`
|
|
97
|
+
* tokens at the start of their own text. */
|
|
98
|
+
const BASE_INTRO_NO_REDUCE = (memoryEnabled: boolean): string => `${CTX_NOTE_GUIDANCE}
|
|
99
|
+
${memoryGuidanceBlock(memoryEnabled)}Use \`ctx_search\` to search across project memories, indexed git commits, and this session's full conversation history (including compacted parts) from one query.
|
|
100
|
+
Use \`ctx_expand\` to recover the raw conversation behind a summary under a \`## start-end · date · title\` heading inside \`<session-history>\` — pass the heading's start/end range when the summary is not enough (exact wording, values, error text).
|
|
101
|
+
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
102
|
+
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
103
|
+
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
104
|
+
- Need a config value, API key location, or environment detail → \`ctx_search(query="embedding provider configuration")\`
|
|
105
|
+
- Looking for how something was implemented previously → \`ctx_search(query="how does the dreamer lease work")\`
|
|
106
|
+
- Want to recall what was decided in an earlier conversation → \`ctx_search(query="dashboard release signing setup")\`
|
|
107
|
+
\`ctx_search\` returns ranked results from memories, git commits, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
108
|
+
${TOOL_HISTORY_GUIDANCE}`;
|
|
109
|
+
|
|
110
|
+
const GENERIC_SECTION = `
|
|
111
|
+
### Reduction Triggers
|
|
112
|
+
- After reading files or search results you already acted on — drop raw outputs.
|
|
113
|
+
- After completing a logical step — drop intermediate outputs from that step.
|
|
114
|
+
- Between major context switches — when moving to a new task area.
|
|
115
|
+
|
|
116
|
+
### What to Drop
|
|
117
|
+
- Large file reads, grep results, and tool outputs you already used.
|
|
118
|
+
- Large build/test output after you analyzed and acted on it.
|
|
119
|
+
- Old diagnostic or exploration results that are no longer relevant.
|
|
120
|
+
|
|
121
|
+
### What to Keep
|
|
122
|
+
- ALL user messages and assistant conversation text — these are cheap and compartmentalized automatically.
|
|
123
|
+
- Your current task requirements and constraints.
|
|
124
|
+
- Recent errors and unresolved decisions.
|
|
125
|
+
- Active work context and files being edited.`;
|
|
126
|
+
|
|
127
|
+
const TEMPORAL_AWARENESS_GUIDANCE = `\n**Temporal awareness**: User messages may be preceded by HTML comments like \`<!-- +12m -->\`, \`<!-- +2h 15m -->\`, or \`<!-- +3d 4h -->\` indicating time elapsed since the previous message's completion. Compartments in \`<session-history>\` carry \`start-date\` and \`end-date\` attributes (YYYY-MM-DD) showing real-time boundaries. Use these when reasoning about workflow pacing, log durations, build times, or how long ago something happened.`;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Minimal guidance for SUBAGENT sessions. Subagents are bounded, single-task
|
|
131
|
+
* executors driven by a parent agent — they self-manage tool-output bloat (the
|
|
132
|
+
* re-read thrash the emergency drop alone can't prevent mid-run) but take on
|
|
133
|
+
* NONE of the primary's long-term role: no partner frame, no memory/search/note
|
|
134
|
+
* curation, no reduction-trigger taxonomy. So this block carries ONLY the §N§ +
|
|
135
|
+
* ctx_reduce mechanics. The `## Magic Context` marker is still present for
|
|
136
|
+
* injection idempotency (system-prompt-hash.ts gates on it).
|
|
137
|
+
*/
|
|
138
|
+
const SUBAGENT_REDUCE_INTRO = (
|
|
139
|
+
protectedTags: number,
|
|
140
|
+
): string => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
141
|
+
Use \`ctx_reduce\` to drop tool outputs you have already finished with, keeping your working context lean. Syntax: "3-5", "1,2,9", or "1-5,8,12-15". The last ${protectedTags} tags are protected.
|
|
142
|
+
Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-50"); review each tag first. Do not drop user or assistant text messages — only large tool outputs are worth dropping.
|
|
143
|
+
Older tool calls may show \`[dropped §N§]\` sentinels; that is normal context management, not a pattern to copy. ALWAYS make fresh real tool calls when you need data again; never fabricate or inline tool output.`;
|
|
144
|
+
|
|
145
|
+
const CAVEMAN_COMPRESSION_WARNING = `\n**BEWARE**: History compression is on; older user AND assistant text — including your own earlier responses — has been deterministically rewritten in a terse caveman style (dropped articles, missing auxiliaries, \`//\` instead of connectives like \`because\`). This is automatic context compression that runs after the fact, not your actual prior wording or the user's. **DO NOT mimic this style in new turns.** Write fresh responses in normal prose. If you notice your output drifting into caveman cadence, that drift is in-context-learning bleeding from the compressed history — consciously revert to full sentences.`;
|
|
146
|
+
|
|
147
|
+
export function buildMagicContextSection(
|
|
148
|
+
_agent: string | null,
|
|
149
|
+
protectedTags: number,
|
|
150
|
+
ctxReduceCallable = true,
|
|
151
|
+
dreamerEnabled = false,
|
|
152
|
+
temporalAwarenessEnabled = false,
|
|
153
|
+
cavemanTextCompressionEnabled = false,
|
|
154
|
+
subagentMode = false,
|
|
155
|
+
language?: string,
|
|
156
|
+
memoryEnabled = true,
|
|
157
|
+
): string {
|
|
158
|
+
// Subagent sessions: minimal §N§ + ctx_reduce mechanics only. Bypasses the
|
|
159
|
+
// long-term-partner frame, memory/search/note guidance, and the reduction
|
|
160
|
+
// taxonomy — none of which apply to a bounded single-task child. Only
|
|
161
|
+
// reachable when ctx_reduce is enabled for the subagent (caller gates this);
|
|
162
|
+
// when ctx_reduce is off the subagent gets no §N§ prefix, so describing the
|
|
163
|
+
// tag system would be noise.
|
|
164
|
+
if (subagentMode) {
|
|
165
|
+
return `## Magic Context\n\n${SUBAGENT_REDUCE_INTRO(protectedTags)}`;
|
|
166
|
+
}
|
|
167
|
+
const smartNoteGuidance = dreamerEnabled
|
|
168
|
+
? `\nWhen \`surface_condition\` is provided with \`write\`, the note becomes a project-scoped smart note.\nThe dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.\nExample: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\``
|
|
169
|
+
: "";
|
|
170
|
+
const temporalGuidance = temporalAwarenessEnabled ? TEMPORAL_AWARENESS_GUIDANCE : "";
|
|
171
|
+
// Caveman compression is independent of ctx_reduce availability. Emit the
|
|
172
|
+
// warning in both primary guidance variants whenever the primary-session
|
|
173
|
+
// caveman pass is enabled so the agent does not mimic compressed history.
|
|
174
|
+
const cavemanWarning = cavemanTextCompressionEnabled ? CAVEMAN_COMPRESSION_WARNING : "";
|
|
175
|
+
const languageDirective = buildPrimaryLanguageDirective(language);
|
|
176
|
+
const languageGuidance = languageDirective ? `\n\n${languageDirective}` : "";
|
|
177
|
+
|
|
178
|
+
if (!ctxReduceCallable) {
|
|
179
|
+
return `## Magic Context\n\n${LONG_TERM_PARTNER_FRAME}\n${PARTNER_FRAME_CLOSER_NO_REDUCE}\n\n${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
|
|
180
|
+
}
|
|
181
|
+
return `## Magic Context\n\n${LONG_TERM_PARTNER_FRAME}\n${PARTNER_FRAME_CLOSER_REDUCE}\n\n${BASE_INTRO(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}\n${GENERIC_SECTION}\n\nPrefer many small targeted operations over one large blanket operation, and keep the working set tidy as routine maintenance.${languageGuidance}`;
|
|
182
|
+
}
|