@jstn-sdk/ma 0.1.11 → 0.1.13

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 (159) hide show
  1. package/.codex/agents/Architect.toml +0 -2
  2. package/.codex/agents/Auditor.toml +0 -2
  3. package/.codex/agents/Builder.toml +0 -2
  4. package/.codex/agents/Flow.toml +0 -2
  5. package/.codex/agents/Sage.toml +0 -2
  6. package/.codex/agents/Vibe.toml +0 -2
  7. package/.codex/hooks.json +14 -13
  8. package/.codex/prompts/enforcement.md +4 -0
  9. package/.codex/prompts/skill-contract.md +4 -0
  10. package/COVERAGE.md +211 -0
  11. package/DEMO.md +265 -0
  12. package/README.md +287 -37
  13. package/bin/ma.js +232 -71
  14. package/data/clone-data.ledger.json +41 -0
  15. package/data/clone-data.proof.json +50 -0
  16. package/data/clone-data.rvf +37 -0
  17. package/docs/README.md +7 -1
  18. package/docs/getting-started.md +108 -37
  19. package/docs/installed-sdk.md +23 -0
  20. package/docs/mcp-setup.md +65 -1
  21. package/docs/onboarding.md +18 -2
  22. package/docs/prompt-guidance-contract.md +17 -0
  23. package/docs/prompt-guidance-fragments/active-autonomy-core.md +7 -0
  24. package/docs/qa/release-issue-gates-0.1.13.json +644 -0
  25. package/docs/qa/release-readiness-0.1.13.md +116 -0
  26. package/docs/qa/release-readiness-0.1.5.md +1 -1
  27. package/docs/reference/native-engineering-patterns.md +35 -0
  28. package/docs/reference/native-security-playbooks.md +27 -0
  29. package/docs/reference/native-source-selection.md +27 -0
  30. package/docs/reference/native-style-and-deslop.md +20 -0
  31. package/docs/release-spec.md +37 -10
  32. package/docs/skills-publishing.md +25 -1
  33. package/docs/skills.md +37 -12
  34. package/index.js +222 -2
  35. package/mcp/collections.json +23 -6
  36. package/mcp/local/code-intel.js +113 -0
  37. package/mcp/local/memory.js +46 -0
  38. package/mcp/local/playbooks.js +168 -0
  39. package/mcp/local/state.js +71 -0
  40. package/mcp/local/team-run.js +113 -0
  41. package/mcp/local/trace.js +60 -0
  42. package/mcp/local-capabilities.json +56 -0
  43. package/mcp/native-playbooks.json +117 -0
  44. package/mcp/servers.json +34 -0
  45. package/package.json +8 -2
  46. package/plugins/meta-architect/.app.json +1 -1
  47. package/plugins/meta-architect/.codex-plugin/plugin.json +4 -4
  48. package/plugins/meta-architect/.mcp.json +1 -1
  49. package/plugins/meta-architect/README.md +34 -1
  50. package/plugins/meta-architect/obsidian/main.js +401 -0
  51. package/plugins/meta-architect/obsidian/manifest.json +9 -0
  52. package/plugins/meta-architect/obsidian/styles.css +7 -0
  53. package/plugins/meta-architect/skills/align/SKILL.md +24 -0
  54. package/plugins/meta-architect/skills/align/agents/openai.yaml +4 -0
  55. package/plugins/meta-architect/skills/align/references/shared-language.md +24 -0
  56. package/plugins/meta-architect/skills/arch/SKILL.md +2 -0
  57. package/plugins/meta-architect/skills/build/SKILL.md +3 -0
  58. package/plugins/meta-architect/skills/cleanup/SKILL.md +23 -0
  59. package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +4 -0
  60. package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +18 -0
  61. package/plugins/meta-architect/skills/diagnose/SKILL.md +24 -0
  62. package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +4 -0
  63. package/plugins/meta-architect/skills/flow/SKILL.md +2 -0
  64. package/plugins/meta-architect/skills/maestro/SKILL.md +36 -3
  65. package/plugins/meta-architect/skills/maestro/agents/openai.yaml +2 -2
  66. package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +44 -0
  67. package/plugins/meta-architect/skills/sage/SKILL.md +5 -1
  68. package/plugins/meta-architect/skills/sage/references/source-selection.md +36 -0
  69. package/plugins/meta-architect/skills/tdd/SKILL.md +24 -0
  70. package/plugins/meta-architect/skills/tdd/agents/openai.yaml +4 -0
  71. package/plugins/meta-architect/skills/vet/SKILL.md +5 -1
  72. package/plugins/meta-architect/skills/vet/references/security-playbooks.md +30 -0
  73. package/plugins/meta-architect/skills/vibe/SKILL.md +2 -0
  74. package/scripts/active-autonomy-hook.mjs +96 -0
  75. package/scripts/build-linux-packages.mjs +328 -0
  76. package/scripts/doctor.js +36 -4
  77. package/scripts/install.sh +28 -0
  78. package/scripts/linux-package-lib.mjs +40 -0
  79. package/scripts/linux-package-smoke.mjs +103 -0
  80. package/scripts/ralph/prompt.md +35 -0
  81. package/scripts/release-sync.js +13 -6
  82. package/scripts/release-verify.js +166 -1
  83. package/skills/align/SKILL.md +24 -0
  84. package/skills/align/agents/openai.yaml +4 -0
  85. package/skills/align/references/shared-language.md +24 -0
  86. package/skills/arch/SKILL.md +2 -0
  87. package/skills/build/SKILL.md +3 -0
  88. package/skills/cleanup/SKILL.md +23 -0
  89. package/skills/cleanup/agents/openai.yaml +4 -0
  90. package/skills/cleanup/references/style-and-deslop.md +18 -0
  91. package/skills/diagnose/SKILL.md +24 -0
  92. package/skills/diagnose/agents/openai.yaml +4 -0
  93. package/skills/flow/SKILL.md +2 -0
  94. package/skills/index.json +21 -6
  95. package/skills/maestro/SKILL.md +36 -3
  96. package/skills/maestro/agents/openai.yaml +2 -2
  97. package/skills/maestro/references/native-ingest-map.md +44 -0
  98. package/skills/sage/SKILL.md +5 -1
  99. package/skills/sage/references/source-selection.md +36 -0
  100. package/skills/tdd/SKILL.md +24 -0
  101. package/skills/tdd/agents/openai.yaml +4 -0
  102. package/skills/vet/SKILL.md +5 -1
  103. package/skills/vet/references/security-playbooks.md +30 -0
  104. package/skills/vibe/SKILL.md +2 -0
  105. package/src/bootstrap.js +141 -24
  106. package/src/build-gate.js +2 -2
  107. package/src/decision-log.js +12 -9
  108. package/src/launcher.js +4 -0
  109. package/src/mcp-config.js +130 -8
  110. package/src/mcp-live-client.js +289 -3
  111. package/src/paths.js +37 -1
  112. package/src/policy.js +1 -1
  113. package/src/release-issue-gates.js +190 -0
  114. package/src/release-state.js +30 -1
  115. package/src/runtime/active-autonomy-core.js +208 -0
  116. package/src/runtime/alignment-sentinel.js +165 -0
  117. package/src/runtime/architect-review.js +88 -0
  118. package/src/runtime/build-readiness.js +62 -0
  119. package/src/runtime/code-graph-rehearse.js +113 -0
  120. package/src/runtime/context-economy-core.js +276 -0
  121. package/src/runtime/continuity-notes.js +79 -0
  122. package/src/runtime/core-source-ingest.js +379 -0
  123. package/src/runtime/detached-provider.js +74 -0
  124. package/src/runtime/environment-awareness-core.js +460 -0
  125. package/src/runtime/exposure-catalog.js +276 -0
  126. package/src/runtime/guidance-stack.js +42 -0
  127. package/src/runtime/helper-orchestration-core.js +307 -0
  128. package/src/runtime/learning-loop-core.js +238 -0
  129. package/src/runtime/maestro-events.js +18 -0
  130. package/src/runtime/maestro-manager.js +605 -0
  131. package/src/runtime/maestro-state.js +125 -0
  132. package/src/runtime/mcp-policy.js +192 -0
  133. package/src/runtime/obsidian-integration-core.js +851 -0
  134. package/src/runtime/obsidian-plugin-bridge.js +739 -0
  135. package/src/runtime/orchestrator.js +158 -0
  136. package/src/runtime/prompt-strategy-core.js +230 -0
  137. package/src/runtime/quorum-review.js +90 -0
  138. package/src/runtime/ralph-execution-core.js +217 -0
  139. package/src/runtime/redaction-gateway.js +174 -0
  140. package/src/runtime/runtime-state.js +1223 -0
  141. package/src/runtime/semantic-recording-core.js +147 -0
  142. package/src/runtime/signal-hooks.js +67 -0
  143. package/src/runtime/skills-registry-export.js +670 -0
  144. package/src/runtime/startup-path.js +14 -0
  145. package/src/runtime/universal-plugin-broker-core.js +575 -0
  146. package/src/runtime/workspace-intelligence-runtime.js +674 -0
  147. package/src/runtime/workspace-virtualizer.js +102 -0
  148. package/src/runtime/workspaces.js +25 -0
  149. package/src/runtime-artifacts.js +407 -84
  150. package/src/skill-installer.js +53 -5
  151. package/src/skills.js +1454 -78
  152. package/src/state-sync.js +51 -8
  153. package/docs/qa/release-readiness-0.1.11.md +0 -79
  154. package/plugins/meta-architect/skills/meta-architect/SKILL.md +0 -32
  155. package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +0 -4
  156. package/skills/meta-architect/SKILL.md +0 -32
  157. package/skills/meta-architect/agents/openai.yaml +0 -4
  158. /package/plugins/meta-architect/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
  159. /package/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
@@ -0,0 +1,62 @@
1
+ import {
2
+ evaluateBuildGate,
3
+ formatBuildBlockers,
4
+ formatNextAllowedTriggers,
5
+ } from "../build-gate.js";
6
+
7
+ export function evaluateRuntimeBuildReadiness(releaseState, runtimeSummary, options = {}) {
8
+ const enforceIssueGates = options.enforceIssueGates === true;
9
+ const releaseEvaluation = evaluateBuildGate(releaseState);
10
+ const missingArtifacts = runtimeSummary.missingArtifacts.filter(
11
+ (artifact) => enforceIssueGates || artifact !== "release.issueGates",
12
+ );
13
+ const controlPlaneBlockers = [
14
+ ...runtimeSummary.invalidArtifacts.filter((artifact) =>
15
+ ["runtime.release", "runtime.decisions"].includes(artifact),
16
+ ),
17
+ ...missingArtifacts.filter(
18
+ (artifact) => artifact === "runtime.release" || artifact === "runtime.decisions",
19
+ ),
20
+ ];
21
+ const runtimeBlockers = [
22
+ ...runtimeSummary.invalidArtifacts.map((artifact) => `runtime artifact ${artifact} is invalid`),
23
+ ...missingArtifacts.map((artifact) => `runtime artifact ${artifact} is missing`),
24
+ ...(runtimeSummary.pendingMailboxCount > 0
25
+ ? ["pending mailbox proposals require leader review"]
26
+ : []),
27
+ ...(runtimeSummary.criticalPackageExposureCount > 0
28
+ ? [
29
+ `critical package exposure findings require $vet remediation (${runtimeSummary.criticalPackageExposureCount} active)`,
30
+ ]
31
+ : []),
32
+ ...(runtimeSummary.mcpPolicyViolationCount > 0
33
+ ? [
34
+ `MCP policy validation findings require $vet remediation (${runtimeSummary.mcpPolicyViolationCount} active)`,
35
+ ]
36
+ : []),
37
+ ...(enforceIssueGates && runtimeSummary.releaseIssueGateBlockerCount > 0
38
+ ? [
39
+ `release issue gates require implementation proof (${runtimeSummary.releaseIssueGatePassed}/${runtimeSummary.releaseIssueGateTotal} passed)`,
40
+ ]
41
+ : []),
42
+ ];
43
+ const releaseBlockers = formatBuildBlockers(releaseEvaluation);
44
+ const nextTriggers =
45
+ releaseEvaluation.allowed && runtimeBlockers.length > 0
46
+ ? runtimeSummary.criticalPackageExposureCount > 0 ||
47
+ runtimeSummary.mcpPolicyViolationCount > 0
48
+ ? ["$vet"]
49
+ : enforceIssueGates && runtimeSummary.releaseIssueGateBlockerCount > 0
50
+ ? ["implement release issue gates"]
51
+ : ["repair runtime artifacts"]
52
+ : formatNextAllowedTriggers(releaseEvaluation);
53
+
54
+ return {
55
+ allowed: releaseEvaluation.allowed && runtimeBlockers.length === 0,
56
+ controlPlaneBlockers,
57
+ runtimeBlockers,
58
+ releaseBlockers,
59
+ blockers: [...releaseBlockers, ...runtimeBlockers],
60
+ nextTriggers,
61
+ };
62
+ }
@@ -0,0 +1,113 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
4
+ import { getRuntimeSubsystemPath } from "../paths.js";
5
+
6
+ export const codeGraphRehearseSchemaVersion = "0.1.0";
7
+ const defaultMaxSteps = 12;
8
+
9
+ export function getCodeGraphRehearsePath() {
10
+ return getRuntimeSubsystemPath("context", "code-graph-rehearse.json");
11
+ }
12
+
13
+ export function createDefaultCodeGraphRehearse() {
14
+ return {
15
+ schemaVersion: codeGraphRehearseSchemaVersion,
16
+ product: "Meta-Architect",
17
+ purpose:
18
+ "Provides a bounded read-only trajectory preview over likely code touchpoints before execution.",
19
+ max_steps: defaultMaxSteps,
20
+ mutation_policy: {
21
+ may_mutate_source: false,
22
+ may_mutate_release_state: false,
23
+ },
24
+ evidence_boundary: {
25
+ records_as: "rehearsal_trace",
26
+ never_records_as: "implementation_evidence",
27
+ does_not_unlock: ["source_mutation", "production_release"],
28
+ },
29
+ applies_to: ["$arch", "$flow", "$build", "executor_roles"],
30
+ };
31
+ }
32
+
33
+ export function validateCodeGraphRehearse(value) {
34
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
35
+ throw new Error("code graph rehearse must be an object");
36
+ }
37
+ if (value.schemaVersion !== codeGraphRehearseSchemaVersion) {
38
+ throw new Error(`Unsupported code graph rehearse schemaVersion: ${value.schemaVersion}`);
39
+ }
40
+ if (!Number.isInteger(value.max_steps) || value.max_steps <= 0) {
41
+ throw new Error("code graph rehearse requires positive max_steps");
42
+ }
43
+ if (value.mutation_policy?.may_mutate_source !== false) {
44
+ throw new Error("code graph rehearse must not mutate source");
45
+ }
46
+ if (value.evidence_boundary?.records_as !== "rehearsal_trace") {
47
+ throw new Error("code graph rehearse must record as rehearsal_trace");
48
+ }
49
+ return value;
50
+ }
51
+
52
+ export async function seedCodeGraphRehearseArtifacts() {
53
+ await ensureDir(getRuntimeSubsystemPath("context"));
54
+ await writeFileIfMissing(
55
+ getCodeGraphRehearsePath(),
56
+ `${JSON.stringify(createDefaultCodeGraphRehearse(), null, 2)}\n`,
57
+ );
58
+ }
59
+
60
+ export async function loadCodeGraphRehearse() {
61
+ return validateCodeGraphRehearse(await readJson(getCodeGraphRehearsePath()));
62
+ }
63
+
64
+ export function createCodeGraphTouchpoint(filePath, imports = []) {
65
+ return {
66
+ path: filePath,
67
+ extension: path.extname(filePath),
68
+ imports: imports.filter((entry) => typeof entry === "string" && entry.trim()),
69
+ };
70
+ }
71
+
72
+ export function extractStaticImports(sourceText) {
73
+ const imports = new Set();
74
+ const patterns = [
75
+ /import\s+(?:[^'"]+\s+from\s+)?["']([^"']+)["']/g,
76
+ /export\s+[^'"]+\s+from\s+["']([^"']+)["']/g,
77
+ /await\s+import\(["']([^"']+)["']\)/g,
78
+ /import\(["']([^"']+)["']\)/g,
79
+ /require\(["']([^"']+)["']\)/g,
80
+ ];
81
+
82
+ for (const pattern of patterns) {
83
+ for (const match of sourceText.matchAll(pattern)) {
84
+ if (match[1]) {
85
+ imports.add(match[1]);
86
+ }
87
+ }
88
+ }
89
+
90
+ return [...imports].sort();
91
+ }
92
+
93
+ export async function createCodeGraphTouchpointFromFile(filePath) {
94
+ const sourceText = await fs.readFile(filePath, "utf8");
95
+ return createCodeGraphTouchpoint(filePath, extractStaticImports(sourceText));
96
+ }
97
+
98
+ export function createRehearsalTrace({ story, touchpoints = [], plannedSteps = [], maxSteps }) {
99
+ const limit = Number.isInteger(maxSteps) && maxSteps > 0 ? maxSteps : defaultMaxSteps;
100
+ const boundedSteps = plannedSteps.slice(0, limit);
101
+ return {
102
+ record_type: "rehearsal_trace",
103
+ story,
104
+ bounded: plannedSteps.length <= limit,
105
+ truncated: plannedSteps.length > limit,
106
+ max_steps: limit,
107
+ steps: boundedSteps,
108
+ touchpoints,
109
+ source_mutation_allowed: false,
110
+ production_evidence: false,
111
+ does_not_unlock: ["source_mutation", "production_release"],
112
+ };
113
+ }
@@ -0,0 +1,276 @@
1
+ import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
2
+ import { getRuntimeSubsystemPath } from "../paths.js";
3
+
4
+ export const contextEconomySchemaVersion = "0.1.0";
5
+
6
+ const safetySignals = [
7
+ "security warning",
8
+ "irreversible",
9
+ "destructive",
10
+ "credential",
11
+ "verification failed",
12
+ "validation failed",
13
+ "user confused",
14
+ ];
15
+
16
+ const removableWords = new Set([
17
+ "a",
18
+ "an",
19
+ "the",
20
+ "just",
21
+ "really",
22
+ "basically",
23
+ "sure",
24
+ "happy",
25
+ "glad",
26
+ ]);
27
+
28
+ export function getContextEconomyCorePath() {
29
+ return getRuntimeSubsystemPath("context", "context-economy-core.json");
30
+ }
31
+
32
+ export function createDefaultContextEconomyCore() {
33
+ return {
34
+ schemaVersion: contextEconomySchemaVersion,
35
+ product: "Meta-Architect",
36
+ purpose:
37
+ "MA-owned default context compression policy for terse progress, summaries, MCP descriptors, and exported host payloads.",
38
+ style: "compact_technical",
39
+ evidence_source: {
40
+ repo: "JuliusBrussee/caveman",
41
+ endpoint: "https://gitmcp.io/JuliusBrussee/caveman",
42
+ applied_as: "MA Context Economy Core",
43
+ adoption_boundary:
44
+ "Use the compression and auto-clarity contract as core MA behavior without adopting third-party persona branding.",
45
+ },
46
+ applies_to: [
47
+ "$maestro",
48
+ "gated_lanes",
49
+ "helper_skills",
50
+ "executor_roles",
51
+ "reviewer_roles",
52
+ "verifier_roles",
53
+ "team_workers",
54
+ "mcp_descriptors",
55
+ "exported_host_payloads",
56
+ ],
57
+ preserve_exact: [
58
+ "code_blocks",
59
+ "commands",
60
+ "schemas",
61
+ "security_warnings",
62
+ "authority_fields",
63
+ "verification_failures",
64
+ "known_gaps",
65
+ "commit_messages",
66
+ ],
67
+ safety_valves: safetySignals,
68
+ compression_rules: [
69
+ "Remove filler and pleasantries from progress, summaries, and descriptors.",
70
+ "Fragments are allowed when meaning stays exact.",
71
+ "Keep technical nouns, commands, paths, code, schemas, evidence status, and blockers exact.",
72
+ "Use auto-clarity bypass for safety warnings, irreversible actions, failed checks, credentials, and confused users.",
73
+ ],
74
+ hard_rules: [
75
+ "Context Economy is default MA behavior, not a third-party persona.",
76
+ "Technical terms, code, schemas, commands, warnings, and evidence boundaries stay exact.",
77
+ "Disable compression when safety, authority, or user clarity would degrade.",
78
+ ],
79
+ };
80
+ }
81
+
82
+ function compactPlainText(text) {
83
+ return text
84
+ .split(/\s+/)
85
+ .filter((word) => !removableWords.has(word.toLowerCase().replace(/[^a-z]/g, "")))
86
+ .join(" ")
87
+ .replace(/\s+([,.;:!?])/g, "$1")
88
+ .trim();
89
+ }
90
+
91
+ export function shouldBypassContextEconomy({ text = "", tags = [] } = {}) {
92
+ const haystack = `${text} ${tags.join(" ")}`.toLowerCase();
93
+ return safetySignals.some((signal) => haystack.includes(signal));
94
+ }
95
+
96
+ export function createContextEconomyView({ text, tags = [], level = "core" }) {
97
+ if (typeof text !== "string") {
98
+ throw new Error("Context Economy view requires text");
99
+ }
100
+
101
+ const bypassed = shouldBypassContextEconomy({ text, tags });
102
+ const parts = text.split(/(```[\s\S]*?```)/g);
103
+ const output = bypassed
104
+ ? text
105
+ : parts
106
+ .map((part) => (part.startsWith("```") ? part : compactPlainText(part)))
107
+ .join("")
108
+ .trim();
109
+
110
+ return {
111
+ record_type: "context_economy_view",
112
+ level,
113
+ bypassed,
114
+ records_as: "context_budget",
115
+ original_chars: text.length,
116
+ output_chars: output.length,
117
+ output,
118
+ preserved_exact: ["code_blocks", "commands", "warnings", "schemas", "authority_fields"],
119
+ };
120
+ }
121
+
122
+ export function createContextEconomyPayload({
123
+ surface = "$maestro",
124
+ payload = {},
125
+ tags = [],
126
+ level = "core",
127
+ } = {}) {
128
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
129
+ throw new Error("Context Economy payload requires an object payload");
130
+ }
131
+
132
+ const transformed = {};
133
+ const fields = [];
134
+ for (const [key, value] of Object.entries(payload)) {
135
+ const result = transformContextEconomyValue({ key, value, tags, level });
136
+ transformed[key] = result.value;
137
+ fields.push({
138
+ key,
139
+ compressed: result.compressed,
140
+ bypassed: result.bypassed,
141
+ original_chars: result.originalChars,
142
+ output_chars: result.outputChars,
143
+ });
144
+ }
145
+
146
+ return {
147
+ record_type: "context_economy_payload",
148
+ surface,
149
+ level,
150
+ records_as: "context_budget",
151
+ build_evidence: false,
152
+ payload: transformed,
153
+ fields,
154
+ preserved_exact: [
155
+ "code",
156
+ "commands",
157
+ "paths",
158
+ "schemas",
159
+ "authority_fields",
160
+ "security_warnings",
161
+ "verification_evidence",
162
+ ],
163
+ };
164
+ }
165
+
166
+ export function createMcpDescriptorEconomy({ name, description, inputSchema = {}, tags = [] }) {
167
+ if (!name || typeof name !== "string") {
168
+ throw new Error("MCP descriptor economy requires a tool name");
169
+ }
170
+ const compacted = createContextEconomyView({
171
+ text: description ?? "",
172
+ tags,
173
+ level: "mcp_descriptor",
174
+ });
175
+ return {
176
+ record_type: "mcp_descriptor_economy",
177
+ records_as: "context_budget",
178
+ build_evidence: false,
179
+ name,
180
+ description: compacted.output,
181
+ inputSchema,
182
+ bypassed: compacted.bypassed,
183
+ preserved_exact: ["name", "inputSchema"],
184
+ };
185
+ }
186
+
187
+ export function validateContextEconomyCore(value) {
188
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
189
+ throw new Error("Context Economy core must be an object");
190
+ }
191
+ if (value.schemaVersion !== contextEconomySchemaVersion) {
192
+ throw new Error(`Unsupported Context Economy schemaVersion: ${value.schemaVersion}`);
193
+ }
194
+ if (value.evidence_source?.repo !== "JuliusBrussee/caveman") {
195
+ throw new Error("Context Economy core requires Caveman evidence source mapping");
196
+ }
197
+ for (const required of ["code_blocks", "security_warnings", "authority_fields"]) {
198
+ if (!value.preserve_exact?.includes(required)) {
199
+ throw new Error(`Context Economy core must preserve ${required}`);
200
+ }
201
+ }
202
+ if (!value.compression_rules?.some((rule) => rule.includes("auto-clarity bypass"))) {
203
+ throw new Error("Context Economy core requires auto-clarity compression rule");
204
+ }
205
+ for (const signal of ["security warning", "irreversible", "verification failed"]) {
206
+ if (!value.safety_valves?.includes(signal)) {
207
+ throw new Error(`Context Economy core requires ${signal} safety valve`);
208
+ }
209
+ }
210
+ if (JSON.stringify(value).includes(".omx")) {
211
+ throw new Error("Context Economy core must not expose OMX runtime paths");
212
+ }
213
+ return value;
214
+ }
215
+
216
+ function transformContextEconomyValue({ key, value, tags, level }) {
217
+ if (typeof value !== "string") {
218
+ return {
219
+ value,
220
+ compressed: false,
221
+ bypassed: false,
222
+ originalChars: 0,
223
+ outputChars: 0,
224
+ };
225
+ }
226
+ if (shouldPreserveField(key)) {
227
+ return {
228
+ value,
229
+ compressed: false,
230
+ bypassed: true,
231
+ originalChars: value.length,
232
+ outputChars: value.length,
233
+ };
234
+ }
235
+ const view = createContextEconomyView({ text: value, tags, level });
236
+ return {
237
+ value: view.output,
238
+ compressed: !view.bypassed && view.output !== value,
239
+ bypassed: view.bypassed,
240
+ originalChars: view.original_chars,
241
+ outputChars: view.output_chars,
242
+ };
243
+ }
244
+
245
+ function shouldPreserveField(key) {
246
+ const normalized = key.toLowerCase();
247
+ return [
248
+ "code",
249
+ "command",
250
+ "commands",
251
+ "schema",
252
+ "inputschema",
253
+ "path",
254
+ "paths",
255
+ "authority",
256
+ "authority_boundary",
257
+ "security_warning",
258
+ "warning",
259
+ "verification_evidence",
260
+ "evidence",
261
+ "known_gap",
262
+ "known_gaps",
263
+ ].includes(normalized);
264
+ }
265
+
266
+ export async function seedContextEconomyCoreArtifacts() {
267
+ await ensureDir(getRuntimeSubsystemPath("context"));
268
+ await writeFileIfMissing(
269
+ getContextEconomyCorePath(),
270
+ `${JSON.stringify(createDefaultContextEconomyCore(), null, 2)}\n`,
271
+ );
272
+ }
273
+
274
+ export async function loadContextEconomyCore() {
275
+ return validateContextEconomyCore(await readJson(getContextEconomyCorePath()));
276
+ }
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs/promises";
2
+ import { ensureDir, readJson, writeFileIfMissing, writeJson } from "../fs-utils.js";
3
+ import { getRuntimeSubsystemPath } from "../paths.js";
4
+ import { guardLeaderMutation } from "./runtime-state.js";
5
+
6
+ export function getContinuityRoot() {
7
+ return getRuntimeSubsystemPath("memory");
8
+ }
9
+
10
+ export function getContinuityNotesPath() {
11
+ return getRuntimeSubsystemPath("memory", "notes.md");
12
+ }
13
+
14
+ export function getContinuityIndexPath() {
15
+ return getRuntimeSubsystemPath("memory", "index.json");
16
+ }
17
+
18
+ export async function seedContinuityArtifacts() {
19
+ await ensureDir(getContinuityRoot());
20
+ await writeFileIfMissing(
21
+ getContinuityNotesPath(),
22
+ "# Continuity Notes\n\nNo continuity notes captured yet.\n",
23
+ );
24
+ await writeFileIfMissing(
25
+ getContinuityIndexPath(),
26
+ `${JSON.stringify(
27
+ {
28
+ schemaVersion: "0.1.0",
29
+ sessionCount: 0,
30
+ lastUpdatedAt: null,
31
+ },
32
+ null,
33
+ 2,
34
+ )}\n`,
35
+ );
36
+ }
37
+
38
+ export async function loadContinuityNotes() {
39
+ return fs.readFile(getContinuityNotesPath(), "utf8");
40
+ }
41
+
42
+ export async function loadContinuityIndex() {
43
+ return readJson(getContinuityIndexPath());
44
+ }
45
+
46
+ export async function storeContinuityNote(content, options = {}) {
47
+ const guard = await guardLeaderMutation({
48
+ actor: options.actor,
49
+ kind: "memory-note-write",
50
+ payload: { content },
51
+ });
52
+ if (!guard.allowed) {
53
+ return { proposed: true, proposalPath: guard.proposalPath };
54
+ }
55
+
56
+ const note = content.trim();
57
+ if (!note) {
58
+ throw new Error("memory.store_note requires non-empty content");
59
+ }
60
+
61
+ const [existingNotes, existingIndex] = await Promise.all([
62
+ loadContinuityNotes(),
63
+ loadContinuityIndex(),
64
+ ]);
65
+ const timestamp = new Date().toISOString();
66
+ const nextNotes = `${existingNotes.trimEnd()}\n\n## ${timestamp}\n\n${note}\n`;
67
+ const nextIndex = {
68
+ ...existingIndex,
69
+ sessionCount: existingIndex.sessionCount + 1,
70
+ lastUpdatedAt: timestamp,
71
+ };
72
+
73
+ await Promise.all([
74
+ fs.writeFile(getContinuityNotesPath(), nextNotes),
75
+ writeJson(getContinuityIndexPath(), nextIndex),
76
+ ]);
77
+
78
+ return { proposed: false, proposalPath: null, index: nextIndex };
79
+ }