@jstn-sdk/ma 0.1.12 → 0.14.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/.codex/agents/Architect.toml +1 -2
- package/.codex/agents/Auditor.toml +1 -2
- package/.codex/agents/Builder.toml +1 -2
- package/.codex/agents/Flow.toml +1 -2
- package/.codex/agents/Sage.toml +1 -2
- package/.codex/agents/Vibe.toml +1 -2
- package/.codex/hooks.json +24 -13
- package/.codex/prompts/enforcement.md +4 -0
- package/.codex/prompts/onboarding.md +6 -1
- package/.codex/prompts/release-rules.md +0 -0
- package/.codex/prompts/skill-contract.md +4 -0
- package/COVERAGE.md +211 -0
- package/DEMO.md +274 -0
- package/LICENSE +0 -0
- package/README.md +132 -656
- package/bin/ma.js +748 -55
- package/data/clone-data.ledger.json +41 -0
- package/data/clone-data.proof.json +50 -0
- package/data/clone-data.rvf +37 -0
- package/docs/README.md +10 -1
- package/docs/autonomous-tasks.md +46 -0
- package/docs/codex-integration.md +16 -0
- package/docs/getting-started.md +62 -22
- package/docs/mcp-setup.md +64 -0
- package/docs/qa/release-issue-gates-0.14.0.json +644 -0
- package/docs/qa/release-readiness-0.1.5.md +1 -1
- package/docs/qa/{release-readiness-0.1.12.md → release-readiness-0.14.0.md} +25 -9
- package/docs/quality.md +24 -0
- package/docs/reference/native-security-playbooks.md +6 -0
- package/docs/reference/native-source-selection.md +6 -0
- package/docs/release-spec.md +39 -10
- package/docs/skills.md +14 -1
- package/index.js +295 -2
- package/mcp/collections.json +23 -6
- package/mcp/fallback.json +0 -0
- package/mcp/local/code-intel.js +179 -41
- package/mcp/local/context.js +180 -0
- package/mcp/local/memory.js +17 -6
- package/mcp/local/quality.js +39 -0
- package/mcp/local/state.js +7 -3
- package/mcp/local/team-run.js +56 -4
- package/mcp/local-capabilities.json +9 -0
- package/mcp/servers.json +24 -0
- package/package.json +29 -4
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +1 -1
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +8 -1
- package/plugins/meta-architect/obsidian/main.js +534 -0
- package/plugins/meta-architect/obsidian/manifest.json +9 -0
- package/plugins/meta-architect/obsidian/styles.css +7 -0
- package/plugins/meta-architect/skills/arch/SKILL.md +2 -0
- package/plugins/meta-architect/skills/build/SKILL.md +3 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +2 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +2 -0
- package/plugins/meta-architect/skills/sage/references/source-selection.md +8 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +2 -0
- package/plugins/meta-architect/skills/vet/references/security-playbooks.md +7 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +2 -0
- package/schemas/autonomous-task-queue.schema.json +56 -0
- package/schemas/handoff-packet.schema.json +36 -0
- package/schemas/setup-receipt.schema.json +28 -0
- package/schemas/skill-frontmatter.schema.json +20 -0
- package/schemas/support-bundle.schema.json +37 -0
- package/schemas/task-contract.schema.json +31 -0
- package/scripts/active-autonomy-hook.mjs +226 -0
- package/scripts/build-linux-packages.mjs +7 -3
- package/scripts/cleanup-test-fixtures.sh +55 -0
- package/scripts/context-hydration-hook.mjs +89 -0
- package/scripts/demo-smoke.js +285 -0
- package/scripts/doctor.js +27 -12
- package/scripts/install.sh +57 -0
- package/scripts/install.sh.sha256 +1 -0
- package/scripts/linux-package-smoke.mjs +2 -2
- package/scripts/package-size-check.mjs +26 -0
- package/scripts/plugin-sync.js +83 -17
- package/scripts/postinstall.js +17 -10
- package/scripts/prepack.js +9 -0
- package/scripts/ralph/prompt.md +35 -0
- package/scripts/release-sync.js +72 -7
- package/scripts/release-verify.js +260 -2
- package/scripts/setup-npmrc.js +48 -23
- package/scripts/skills-install.js +9 -2
- package/scripts/skills-manifest.js +2 -21
- package/scripts/skills-pack.js +2 -2
- package/scripts/skills-validate.js +5 -55
- package/skills/arch/SKILL.md +2 -0
- package/skills/build/SKILL.md +3 -0
- package/skills/flow/SKILL.md +2 -0
- package/skills/index.json +0 -0
- package/skills/sage/SKILL.md +2 -0
- package/skills/sage/references/source-selection.md +8 -0
- package/skills/vet/SKILL.md +2 -0
- package/skills/vet/references/security-playbooks.md +7 -0
- package/skills/vibe/SKILL.md +2 -0
- package/sprint/00-idea.md +0 -0
- package/sprint/01-architecture.md +0 -0
- package/sprint/02-oss-evidence.md +0 -0
- package/sprint/03-logic.md +0 -0
- package/sprint/04-security.md +0 -0
- package/sprint/05-dx-ux.md +0 -0
- package/sprint/06-build-plan.md +0 -0
- package/sprint/07-release.md +0 -0
- package/src/agents.js +279 -0
- package/src/bootstrap.js +268 -62
- package/src/build-gate.js +2 -2
- package/src/codex-app-server.js +291 -0
- package/src/decision-log.js +0 -0
- package/src/fs-utils.js +175 -4
- package/src/launcher.js +28 -21
- package/src/mcp-config.js +9 -1
- package/src/mcp-live-client.js +422 -3
- package/src/paths.js +10 -1
- package/src/policy.js +3 -3
- package/src/prelaunch.js +189 -0
- package/src/quality/ai-quality-orchestrator.js +328 -0
- package/src/release-issue-gates.js +252 -0
- package/src/release-operations.js +62 -0
- package/src/release-state.js +0 -0
- package/src/runtime/active-autonomy-core.js +208 -0
- package/src/runtime/agent-compat.js +31 -0
- package/src/runtime/alignment-sentinel.js +165 -0
- package/src/runtime/architect-review.js +326 -0
- package/src/runtime/autonomous-tasks.js +408 -0
- package/src/runtime/build-readiness.js +28 -4
- package/src/runtime/code-graph-rehearse.js +113 -0
- package/src/runtime/codeburn-core.js +112 -0
- package/src/runtime/context-authority.js +40 -0
- package/src/runtime/context-economy-core.js +316 -0
- package/src/runtime/continuity-graph.js +201 -0
- package/src/runtime/continuity-notes.js +71 -26
- package/src/runtime/core-source-ingest.js +379 -0
- package/src/runtime/detached-provider.js +142 -0
- package/src/runtime/doctor-report.js +18 -0
- package/src/runtime/environment-awareness-core.js +460 -0
- package/src/runtime/exposure-catalog.js +276 -0
- package/src/runtime/graphify-core.js +167 -0
- package/src/runtime/guidance-stack.js +9 -2
- package/src/runtime/handoff-packets.js +92 -0
- package/src/runtime/headroom-core.js +104 -0
- package/src/runtime/helper-orchestration-core.js +307 -0
- package/src/runtime/hook-profiles.js +20 -0
- package/src/runtime/learning-loop-core.js +344 -0
- package/src/runtime/live-agent-verification.js +122 -0
- package/src/runtime/maestro-events.js +18 -0
- package/src/runtime/maestro-manager.js +19 -0
- package/src/runtime/maestro-output.js +58 -0
- package/src/runtime/maestro-state.js +125 -0
- package/src/runtime/managed-markdown.js +29 -0
- package/src/runtime/mcp-authority.js +147 -0
- package/src/runtime/mcp-policy.js +192 -0
- package/src/runtime/obsidian-integration-core.js +1089 -0
- package/src/runtime/obsidian-plugin-bridge.js +1045 -0
- package/src/runtime/pi-maestro-core.js +89 -0
- package/src/runtime/preferences.js +79 -0
- package/src/runtime/project-context.js +636 -0
- package/src/runtime/prompt-strategy-core.js +230 -0
- package/src/runtime/quorum-review.js +90 -0
- package/src/runtime/ralph-execution-core.js +217 -0
- package/src/runtime/redaction-gateway.js +373 -0
- package/src/runtime/runtime-state.js +935 -2
- package/src/runtime/schema-migrations.js +162 -0
- package/src/runtime/semantic-recording-core.js +147 -0
- package/src/runtime/signal-hooks.js +28 -0
- package/src/runtime/skills-registry-export.js +754 -0
- package/src/runtime/task-contracts.js +83 -0
- package/src/runtime/universal-plugin-broker-core.js +898 -0
- package/src/runtime/workspace-intelligence-runtime.js +674 -0
- package/src/runtime/workspace-virtualizer.js +102 -0
- package/src/runtime-artifacts.js +225 -62
- package/src/setup-lifecycle.js +359 -0
- package/src/skill-frontmatter.js +78 -0
- package/src/skill-installer.js +226 -71
- package/src/skills.js +1166 -96
- package/src/state-sync.js +0 -0
- package/src/test-fixtures.js +543 -0
- package/src/tui/grid.js +67 -0
- package/src/tui/status-grid.js +23 -0
- package/support-bundle.json +114 -0
- package/templates/AGENTS.md +6 -2
- package/templates/catalog-manifest.json +0 -0
- package/templates/model-instructions/core.md +0 -0
- package/templates/model-instructions/release.md +0 -0
- package/templates/model-instructions/security.md +0 -0
- package/templates/quality/ai-quality-rules.yml +37 -0
- package/docs/assets/image/Screenshot(1).png +0 -0
- package/docs/assets/image/Screenshot(2).png +0 -0
- package/docs/assets/image/Screenshot(3).png +0 -0
- package/docs/assets/image/Screenshot(4).png +0 -0
- package/docs/assets/image/Screenshot(5).png +0 -0
- package/docs/assets/image/Screenshot(6).png +0 -0
- package/docs/assets/image/Screenshot(7).png +0 -0
- package/docs/assets/image/Screenshot(8).png +0 -0
- package/docs/assets/image/Screenshot(9).png +0 -0
- package/docs/assets/meta-architect-logo.png +0 -0
- package/docs/assets/meta-architect-logo.svg +0 -8
- package/docs/onboarding.md +0 -65
- package/docs/skills-publishing.md +0 -255
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
|
|
2
|
+
import { getRuntimeSubsystemPath } from "../paths.js";
|
|
3
|
+
|
|
4
|
+
export const helperOrchestrationSchemaVersion = "0.1.0";
|
|
5
|
+
export const helperSkillNames = ["$align", "$diagnose", "$tdd", "$cleanup"];
|
|
6
|
+
|
|
7
|
+
const helperContracts = [
|
|
8
|
+
{
|
|
9
|
+
skill: "$align",
|
|
10
|
+
semantic_role: "scope_alignment",
|
|
11
|
+
activates_when: [
|
|
12
|
+
"ambiguous_scope",
|
|
13
|
+
"terminology_drift",
|
|
14
|
+
"lane_handoff_needs_shared_language",
|
|
15
|
+
"docs_or_prompt_contract_needs_tightening",
|
|
16
|
+
],
|
|
17
|
+
outputs: [
|
|
18
|
+
"current_ambiguity_or_mismatch",
|
|
19
|
+
"normalized_terminology",
|
|
20
|
+
"scope_boundary_and_exclusions",
|
|
21
|
+
"acceptance_checks_or_rewritten_prompts",
|
|
22
|
+
"exact_next_trigger",
|
|
23
|
+
],
|
|
24
|
+
supports: ["$maestro", "$arch", "$sage", "$flow", "$vet", "$vibe", "$build"],
|
|
25
|
+
records_as: "helper_alignment_receipt",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
skill: "$diagnose",
|
|
29
|
+
semantic_role: "blocked_lane_diagnosis",
|
|
30
|
+
activates_when: [
|
|
31
|
+
"lane_blocked",
|
|
32
|
+
"vague_symptom",
|
|
33
|
+
"runtime_artifact_invalid",
|
|
34
|
+
"missing_evidence_or_reproduction_boundary",
|
|
35
|
+
],
|
|
36
|
+
outputs: [
|
|
37
|
+
"observed_symptom",
|
|
38
|
+
"likely_failure_slices",
|
|
39
|
+
"missing_evidence_or_repro_steps",
|
|
40
|
+
"smallest_next_probe",
|
|
41
|
+
"exact_next_trigger",
|
|
42
|
+
],
|
|
43
|
+
supports: ["$maestro", "$flow", "$vet", "$build", "verifier_roles", "debugger_roles"],
|
|
44
|
+
records_as: "helper_diagnosis_receipt",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
skill: "$tdd",
|
|
48
|
+
semantic_role: "regression_first_boundary",
|
|
49
|
+
activates_when: [
|
|
50
|
+
"implementation_expanding",
|
|
51
|
+
"cleanup_requires_behavior_lock",
|
|
52
|
+
"bounded_build_slice_needs_test_shape",
|
|
53
|
+
"regression_risk_before_refactor",
|
|
54
|
+
],
|
|
55
|
+
outputs: [
|
|
56
|
+
"behavior_to_lock",
|
|
57
|
+
"minimal_regression_or_failing_test_shape",
|
|
58
|
+
"implementation_boundary",
|
|
59
|
+
"proof_test_belongs_to_change",
|
|
60
|
+
"exact_next_trigger",
|
|
61
|
+
],
|
|
62
|
+
supports: ["$maestro", "$build", "executor_roles", "test_engineer_roles", "$cleanup"],
|
|
63
|
+
records_as: "helper_tdd_receipt",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
skill: "$cleanup",
|
|
67
|
+
semantic_role: "contract_preserving_simplification",
|
|
68
|
+
activates_when: [
|
|
69
|
+
"artifact_is_noisy_after_decision",
|
|
70
|
+
"anti_slop_pass_needed",
|
|
71
|
+
"docs_need_product_native_wording",
|
|
72
|
+
"code_or_plan_can_be_simplified_without_behavior_change",
|
|
73
|
+
],
|
|
74
|
+
outputs: [
|
|
75
|
+
"removable_complexity_or_noisy_wording",
|
|
76
|
+
"behavior_preserving_simplifications",
|
|
77
|
+
"residual_risks_after_cleanup",
|
|
78
|
+
"exact_next_trigger",
|
|
79
|
+
],
|
|
80
|
+
supports: ["$maestro", "$arch", "$sage", "$flow", "$vet", "$vibe", "$build", "writer_roles"],
|
|
81
|
+
records_as: "helper_cleanup_receipt",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
export function getHelperOrchestrationCorePath() {
|
|
86
|
+
return getRuntimeSubsystemPath("context", "helper-orchestration-core.json");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function createDefaultHelperOrchestrationCore() {
|
|
90
|
+
return {
|
|
91
|
+
schemaVersion: helperOrchestrationSchemaVersion,
|
|
92
|
+
product: "Meta-Architect",
|
|
93
|
+
purpose:
|
|
94
|
+
"Defines how $align, $diagnose, $tdd, and $cleanup work together as core non-gating helper capabilities across MA lanes, roles, workers, and exported host payloads.",
|
|
95
|
+
helper_contracts: helperContracts,
|
|
96
|
+
composition_rules: {
|
|
97
|
+
non_gating: true,
|
|
98
|
+
release_state_mutation_allowed: false,
|
|
99
|
+
may_create_parallel_release_gate: false,
|
|
100
|
+
authority_returns_to: "$maestro_or_owning_lane",
|
|
101
|
+
can_run_before_lane: true,
|
|
102
|
+
can_run_between_lanes: true,
|
|
103
|
+
can_run_after_lane: true,
|
|
104
|
+
records_as: "helper_receipt",
|
|
105
|
+
never_records_as: "gate_approval",
|
|
106
|
+
},
|
|
107
|
+
role_application: {
|
|
108
|
+
all_roles_may_consume_helper_receipts: true,
|
|
109
|
+
planner_roles: ["$align", "$diagnose"],
|
|
110
|
+
architect_roles: ["$align", "$diagnose", "$cleanup"],
|
|
111
|
+
executor_roles: ["$tdd", "$cleanup", "$diagnose"],
|
|
112
|
+
verifier_roles: ["$diagnose", "$tdd", "$cleanup"],
|
|
113
|
+
writer_roles: ["$align", "$cleanup"],
|
|
114
|
+
team_workers: ["$align", "$diagnose", "$tdd", "$cleanup"],
|
|
115
|
+
exported_host_payloads: ["$align", "$diagnose", "$tdd", "$cleanup"],
|
|
116
|
+
},
|
|
117
|
+
handoff_contract: {
|
|
118
|
+
required_fields: [
|
|
119
|
+
"skill",
|
|
120
|
+
"semantic_role",
|
|
121
|
+
"objective",
|
|
122
|
+
"observed_context",
|
|
123
|
+
"result",
|
|
124
|
+
"does_not_unlock",
|
|
125
|
+
"next_trigger",
|
|
126
|
+
],
|
|
127
|
+
does_not_unlock: [
|
|
128
|
+
"release_state_transition",
|
|
129
|
+
"build_gate",
|
|
130
|
+
"merge_gate",
|
|
131
|
+
"production_release",
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function validateHelperOrchestrationCore(value) {
|
|
138
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
139
|
+
throw new Error("helper orchestration core must be an object");
|
|
140
|
+
}
|
|
141
|
+
if (value.schemaVersion !== helperOrchestrationSchemaVersion) {
|
|
142
|
+
throw new Error(`Unsupported helper orchestration schemaVersion: ${value.schemaVersion}`);
|
|
143
|
+
}
|
|
144
|
+
if (!Array.isArray(value.helper_contracts)) {
|
|
145
|
+
throw new Error("helper orchestration core requires helper_contracts");
|
|
146
|
+
}
|
|
147
|
+
const found = value.helper_contracts.map((contract) => contract.skill).sort();
|
|
148
|
+
const expected = [...helperSkillNames].sort();
|
|
149
|
+
if (JSON.stringify(found) !== JSON.stringify(expected)) {
|
|
150
|
+
throw new Error("helper orchestration core must define all four helper skills exactly once");
|
|
151
|
+
}
|
|
152
|
+
for (const contract of value.helper_contracts) {
|
|
153
|
+
if (
|
|
154
|
+
typeof contract.semantic_role !== "string" ||
|
|
155
|
+
!Array.isArray(contract.activates_when) ||
|
|
156
|
+
!Array.isArray(contract.outputs) ||
|
|
157
|
+
!Array.isArray(contract.supports) ||
|
|
158
|
+
typeof contract.records_as !== "string"
|
|
159
|
+
) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
"helper contracts require semantic_role, activates_when, outputs, supports, records_as",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (value.composition_rules?.release_state_mutation_allowed !== false) {
|
|
166
|
+
throw new Error("helper orchestration core must not allow release-state mutation");
|
|
167
|
+
}
|
|
168
|
+
if (value.composition_rules?.never_records_as !== "gate_approval") {
|
|
169
|
+
throw new Error("helper orchestration core must never record as gate approval");
|
|
170
|
+
}
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function resolveHelperContract(skill, core = createDefaultHelperOrchestrationCore()) {
|
|
175
|
+
const document = validateHelperOrchestrationCore(core);
|
|
176
|
+
const contract = document.helper_contracts.find((entry) => entry.skill === skill);
|
|
177
|
+
if (!contract) {
|
|
178
|
+
throw new Error(`Unknown helper skill: ${skill}`);
|
|
179
|
+
}
|
|
180
|
+
return contract;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function chooseHelperRoute({
|
|
184
|
+
releaseState = {},
|
|
185
|
+
runtimeSummary = {},
|
|
186
|
+
taskIntent = "",
|
|
187
|
+
} = {}) {
|
|
188
|
+
const intent = taskIntent.toLowerCase();
|
|
189
|
+
const helpers = [];
|
|
190
|
+
const add = (skill, reason) => {
|
|
191
|
+
if (!helpers.some((entry) => entry.skill === skill)) {
|
|
192
|
+
helpers.push({ skill, reason });
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
releaseState.idea_status !== "CLEAR" ||
|
|
198
|
+
releaseState.architecture_status !== "APPROVED" ||
|
|
199
|
+
intent.includes("scope") ||
|
|
200
|
+
intent.includes("terminology") ||
|
|
201
|
+
intent.includes("prompt")
|
|
202
|
+
) {
|
|
203
|
+
add("$align", "Normalize scope, shared language, and the next owning lane.");
|
|
204
|
+
}
|
|
205
|
+
if (
|
|
206
|
+
releaseState.logic_status === "RED" ||
|
|
207
|
+
releaseState.security_status === "RED" ||
|
|
208
|
+
runtimeSummary.pendingMailboxCount > 0 ||
|
|
209
|
+
runtimeSummary.invalidArtifacts?.length > 0 ||
|
|
210
|
+
intent.includes("blocked") ||
|
|
211
|
+
intent.includes("failure")
|
|
212
|
+
) {
|
|
213
|
+
add("$diagnose", "Decompose blockers into reproducible slices and next probes.");
|
|
214
|
+
}
|
|
215
|
+
if (
|
|
216
|
+
["READY", "RUNNING"].includes(releaseState.build_status) ||
|
|
217
|
+
intent.includes("test") ||
|
|
218
|
+
intent.includes("regression") ||
|
|
219
|
+
intent.includes("refactor")
|
|
220
|
+
) {
|
|
221
|
+
add("$tdd", "Lock behavior before implementation expands or cleanup changes code.");
|
|
222
|
+
}
|
|
223
|
+
if (
|
|
224
|
+
releaseState.build_status === "DONE" ||
|
|
225
|
+
intent.includes("cleanup") ||
|
|
226
|
+
intent.includes("polish") ||
|
|
227
|
+
intent.includes("slop") ||
|
|
228
|
+
intent.includes("docs")
|
|
229
|
+
) {
|
|
230
|
+
add("$cleanup", "Simplify artifacts without changing the owning lane decision.");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
record_type: "helper_route_recommendation",
|
|
235
|
+
helpers,
|
|
236
|
+
helper_count: helpers.length,
|
|
237
|
+
non_gating: true,
|
|
238
|
+
release_state_mutation_allowed: false,
|
|
239
|
+
next_owner:
|
|
240
|
+
helpers.length === 0
|
|
241
|
+
? "$maestro_or_owning_lane"
|
|
242
|
+
: helpers.at(-1).skill === "$cleanup"
|
|
243
|
+
? "$maestro_or_release_verification"
|
|
244
|
+
: "$maestro_or_owning_lane",
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function createHelperReceipt({
|
|
249
|
+
skill,
|
|
250
|
+
objective,
|
|
251
|
+
observedContext,
|
|
252
|
+
result,
|
|
253
|
+
nextTrigger,
|
|
254
|
+
core = createDefaultHelperOrchestrationCore(),
|
|
255
|
+
}) {
|
|
256
|
+
const contract = resolveHelperContract(skill, core);
|
|
257
|
+
if (!objective || !observedContext || !result || !nextTrigger) {
|
|
258
|
+
throw new Error("helper receipt requires objective, observedContext, result, and nextTrigger");
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
record_type: "helper_receipt",
|
|
262
|
+
skill,
|
|
263
|
+
semantic_role: contract.semantic_role,
|
|
264
|
+
objective,
|
|
265
|
+
observed_context: observedContext,
|
|
266
|
+
result,
|
|
267
|
+
records_as: contract.records_as,
|
|
268
|
+
does_not_unlock: ["release_state_transition", "build_gate", "merge_gate", "production_release"],
|
|
269
|
+
next_trigger: nextTrigger,
|
|
270
|
+
authority: "$maestro_or_owning_lane",
|
|
271
|
+
created_at: new Date().toISOString(),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function evaluateHelperCoreCoverage(core = createDefaultHelperOrchestrationCore()) {
|
|
276
|
+
const document = validateHelperOrchestrationCore(core);
|
|
277
|
+
const supportedRoles = new Set();
|
|
278
|
+
for (const contract of document.helper_contracts) {
|
|
279
|
+
for (const support of contract.supports) {
|
|
280
|
+
supportedRoles.add(support);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
record_type: "helper_core_coverage",
|
|
285
|
+
helper_count: document.helper_contracts.length,
|
|
286
|
+
helper_skills: document.helper_contracts.map((contract) => contract.skill),
|
|
287
|
+
supported_surface_count: supportedRoles.size,
|
|
288
|
+
non_gating: document.composition_rules.non_gating === true,
|
|
289
|
+
release_state_mutation_allowed:
|
|
290
|
+
document.composition_rules.release_state_mutation_allowed === true,
|
|
291
|
+
all_helpers_defined: helperSkillNames.every((skill) =>
|
|
292
|
+
document.helper_contracts.some((contract) => contract.skill === skill),
|
|
293
|
+
),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export async function seedHelperOrchestrationCoreArtifacts() {
|
|
298
|
+
await ensureDir(getRuntimeSubsystemPath("context"));
|
|
299
|
+
await writeFileIfMissing(
|
|
300
|
+
getHelperOrchestrationCorePath(),
|
|
301
|
+
`${JSON.stringify(createDefaultHelperOrchestrationCore(), null, 2)}\n`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export async function loadHelperOrchestrationCore() {
|
|
306
|
+
return validateHelperOrchestrationCore(await readJson(getHelperOrchestrationCorePath()));
|
|
307
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const hookProfiles = {
|
|
2
|
+
local: { scanScope: "active-project", block: true, writeReceipts: true, readOnly: false },
|
|
3
|
+
ci: { scanScope: "active-project", block: true, writeReceipts: true, readOnly: false },
|
|
4
|
+
pr: {
|
|
5
|
+
scanScope: "active-project",
|
|
6
|
+
block: true,
|
|
7
|
+
writeReceipts: true,
|
|
8
|
+
readOnly: false,
|
|
9
|
+
requireFreshness: true,
|
|
10
|
+
},
|
|
11
|
+
audit: { scanScope: "broad", block: false, writeReceipts: false, readOnly: true },
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function resolveHookProfile(
|
|
15
|
+
value = process.env.MA_HOOK_PROFILE ?? process.env.MA_PROFILE ?? "local",
|
|
16
|
+
) {
|
|
17
|
+
return hookProfiles[value]
|
|
18
|
+
? { id: value, ...hookProfiles[value] }
|
|
19
|
+
: { id: "local", ...hookProfiles.local };
|
|
20
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
|
|
3
|
+
import { getRuntimeSubsystemPath } from "../paths.js";
|
|
4
|
+
import { createFreshness } from "./context-authority.js";
|
|
5
|
+
import { appendObsidianLearningRecord } from "./obsidian-integration-core.js";
|
|
6
|
+
import { maskSensitiveText } from "./redaction-gateway.js";
|
|
7
|
+
|
|
8
|
+
export const learningLoopCoreSchemaVersion = "0.1.0";
|
|
9
|
+
|
|
10
|
+
export const learningLoopDomains = [
|
|
11
|
+
"core_orchestration",
|
|
12
|
+
"memory_knowledge",
|
|
13
|
+
"intelligence_learning",
|
|
14
|
+
"code_quality_testing",
|
|
15
|
+
"security_compliance",
|
|
16
|
+
"architecture_methodology",
|
|
17
|
+
"devops_observability",
|
|
18
|
+
"extensibility",
|
|
19
|
+
"domain_specific",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export function getLearningLoopCorePath() {
|
|
23
|
+
return getRuntimeSubsystemPath("context", "learning-loop-core.json");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getLearningRecordsPath() {
|
|
27
|
+
return getRuntimeSubsystemPath("learning", "records.jsonl");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function createDefaultLearningLoopCore() {
|
|
31
|
+
return {
|
|
32
|
+
schemaVersion: learningLoopCoreSchemaVersion,
|
|
33
|
+
product: "Meta-Architect",
|
|
34
|
+
purpose:
|
|
35
|
+
"First-party learning loop that turns verified workspace outcomes into durable, lane-aware improvements over time.",
|
|
36
|
+
loop: {
|
|
37
|
+
cadence: "every_verified_workflow_or_release_gate",
|
|
38
|
+
sequence: [
|
|
39
|
+
"observe_runtime_outcome",
|
|
40
|
+
"classify_learning_domain",
|
|
41
|
+
"record_semantic_receipt",
|
|
42
|
+
"promote_verified_learning",
|
|
43
|
+
"apply_to_next_run",
|
|
44
|
+
"verify_effectiveness_delta",
|
|
45
|
+
],
|
|
46
|
+
fail_closed_rule:
|
|
47
|
+
"Unverified observations stay as candidate learnings and must not change gates, release state, or durable policy.",
|
|
48
|
+
},
|
|
49
|
+
domains: [
|
|
50
|
+
{
|
|
51
|
+
id: "core_orchestration",
|
|
52
|
+
label: "Core & Orchestration",
|
|
53
|
+
learns_from: ["maestro_runs", "lane_handoffs", "manager_events"],
|
|
54
|
+
writes_to: [".ma/state/manager-runs.json", ".ma/context/workspace-effectiveness.json"],
|
|
55
|
+
promotion_gate: "handoff_replay_or_release_check_passed",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "memory_knowledge",
|
|
59
|
+
label: "Memory & Knowledge",
|
|
60
|
+
learns_from: ["memory_notes", "obsidian_vault_context", "semantic_receipts"],
|
|
61
|
+
writes_to: [".ma/memory/notes.md", ".ma/memory/index.json", ".ma/context/project.md"],
|
|
62
|
+
promotion_gate: "source_provenance_and_authority_boundary_verified",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "intelligence_learning",
|
|
66
|
+
label: "Intelligence & Learning",
|
|
67
|
+
learns_from: ["prompt_strategy_results", "context_budget_outcomes", "rehearsal_traces"],
|
|
68
|
+
writes_to: [".ma/context/prompt-strategy-core.json", ".ma/context/learning-loop-core.json"],
|
|
69
|
+
promotion_gate: "strategy_result_has_verification_delta",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "code_quality_testing",
|
|
73
|
+
label: "Code Quality & Testing",
|
|
74
|
+
learns_from: ["test_failures", "lint_results", "build_results", "ralph_progress"],
|
|
75
|
+
writes_to: [".ma/specs/logic.md", ".ma/plans/build.md"],
|
|
76
|
+
promotion_gate: "fresh_test_or_build_evidence_passed",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "security_compliance",
|
|
80
|
+
label: "Security & Compliance",
|
|
81
|
+
learns_from: ["vet_findings", "exposure_catalog", "redaction_receipts"],
|
|
82
|
+
writes_to: [".ma/specs/security.md", ".ma/evidence/audits.json"],
|
|
83
|
+
promotion_gate: "security_review_passed_or_blocker_preserved",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "architecture_methodology",
|
|
87
|
+
label: "Architecture & Methodology",
|
|
88
|
+
learns_from: ["architecture_decisions", "methodology_reviews", "tradeoff_outcomes"],
|
|
89
|
+
writes_to: [".ma/specs/architecture.md", ".ma/decisions.json"],
|
|
90
|
+
promotion_gate: "architecture_review_accepts_reusable_pattern",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "devops_observability",
|
|
94
|
+
label: "DevOps & Observability",
|
|
95
|
+
learns_from: ["release_checks", "package_smokes", "runtime_traces", "hook_audits"],
|
|
96
|
+
writes_to: [".ma/runbook.md", ".ma/logs/", ".ma/hooks/audit.log"],
|
|
97
|
+
promotion_gate: "release_or_smoke_gate_passed",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "extensibility",
|
|
101
|
+
label: "Extensibility",
|
|
102
|
+
learns_from: ["skill_exports", "plugin_installs", "mcp_policy_results", "host_payloads"],
|
|
103
|
+
writes_to: [".ma/context/skills-registry-export.json", "mcp/servers.json"],
|
|
104
|
+
promotion_gate: "compatibility_matrix_verified",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "domain_specific",
|
|
108
|
+
label: "Domain-Specific",
|
|
109
|
+
learns_from: ["workspace_stack", "project_domain_notes", "trusted_sources"],
|
|
110
|
+
writes_to: [
|
|
111
|
+
".ma/context/workspace-context-pack.json",
|
|
112
|
+
".ma/evidence/semantic-receipts.json",
|
|
113
|
+
],
|
|
114
|
+
promotion_gate: "domain_claim_has_source_or_user_authority",
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
learning_record_schema: {
|
|
118
|
+
domain: "one_of_learningLoopDomains",
|
|
119
|
+
claim: "string",
|
|
120
|
+
source: "path_or_runtime_surface",
|
|
121
|
+
evidence: ["path_or_command_or_receipt"],
|
|
122
|
+
status: "candidate | verified | rejected | superseded",
|
|
123
|
+
applies_to: ["agent_or_role_or_lane"],
|
|
124
|
+
fact_ids: ["canonical_project_fact_id"],
|
|
125
|
+
cannot_mutate: ["release_state_without_owning_lane", "source_evidence", "security_boundary"],
|
|
126
|
+
next_verification: "string",
|
|
127
|
+
},
|
|
128
|
+
hard_rules: [
|
|
129
|
+
"Learning records require domain, claim, source, evidence, status, applies_to, and next_verification.",
|
|
130
|
+
"fact_ids may reference only canonical source-truth project facts.",
|
|
131
|
+
"Candidate learnings can inform context but cannot mutate gates, release state, or durable policy.",
|
|
132
|
+
"Verified learnings must preserve lane authority and semantic channel boundaries.",
|
|
133
|
+
"Obsidian and memory context can inform planning but do not become build evidence without owning-lane promotion.",
|
|
134
|
+
"Security, compliance, redaction, and irreversible-action warnings must not be compressed or auto-promoted.",
|
|
135
|
+
],
|
|
136
|
+
records: [],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function validateLearningLoopCore(value) {
|
|
141
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
142
|
+
throw new Error("learning loop core must be an object");
|
|
143
|
+
}
|
|
144
|
+
if (value.schemaVersion !== learningLoopCoreSchemaVersion) {
|
|
145
|
+
throw new Error(`Unsupported learning loop core schemaVersion: ${value.schemaVersion}`);
|
|
146
|
+
}
|
|
147
|
+
if (!Array.isArray(value.domains) || value.domains.length !== learningLoopDomains.length) {
|
|
148
|
+
throw new Error("learning loop core must include every required learning domain");
|
|
149
|
+
}
|
|
150
|
+
const ids = new Set(value.domains.map((domain) => domain.id));
|
|
151
|
+
for (const required of learningLoopDomains) {
|
|
152
|
+
if (!ids.has(required)) {
|
|
153
|
+
throw new Error(`learning loop core missing domain: ${required}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
for (const domain of value.domains) {
|
|
157
|
+
if (
|
|
158
|
+
typeof domain.label !== "string" ||
|
|
159
|
+
!Array.isArray(domain.learns_from) ||
|
|
160
|
+
!Array.isArray(domain.writes_to) ||
|
|
161
|
+
typeof domain.promotion_gate !== "string"
|
|
162
|
+
) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
"learning loop domains require label, learns_from, writes_to, and promotion_gate",
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!Array.isArray(value.records)) {
|
|
169
|
+
throw new Error("learning loop core requires records array");
|
|
170
|
+
}
|
|
171
|
+
if (JSON.stringify(value).includes(".omx")) {
|
|
172
|
+
throw new Error("learning loop core must not expose OMX runtime paths");
|
|
173
|
+
}
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function createLearningRecord({
|
|
178
|
+
domain,
|
|
179
|
+
claim,
|
|
180
|
+
source,
|
|
181
|
+
evidence = [],
|
|
182
|
+
filesInvolved = [],
|
|
183
|
+
decisionsMade = [],
|
|
184
|
+
knownRisks = [],
|
|
185
|
+
userPreferences = {},
|
|
186
|
+
status = "candidate",
|
|
187
|
+
appliesTo = ["all_applicable_agents", "all_applicable_roles"],
|
|
188
|
+
nextVerification,
|
|
189
|
+
factIds = [],
|
|
190
|
+
failureState,
|
|
191
|
+
attemptedFixes = [],
|
|
192
|
+
resolutionStatus,
|
|
193
|
+
}) {
|
|
194
|
+
if (!learningLoopDomains.includes(domain)) {
|
|
195
|
+
throw new Error(`Unsupported learning domain: ${domain}`);
|
|
196
|
+
}
|
|
197
|
+
if (!claim || !source || !nextVerification) {
|
|
198
|
+
throw new Error("Learning record requires domain, claim, source, and nextVerification");
|
|
199
|
+
}
|
|
200
|
+
if (
|
|
201
|
+
!Array.isArray(factIds) ||
|
|
202
|
+
factIds.some((entry) => typeof entry !== "string" || !/^fact-[a-f0-9]{16}$/.test(entry))
|
|
203
|
+
) {
|
|
204
|
+
throw new Error("Learning record factIds must use canonical fact IDs");
|
|
205
|
+
}
|
|
206
|
+
const createdAt = new Date().toISOString();
|
|
207
|
+
return {
|
|
208
|
+
domain,
|
|
209
|
+
claim: sanitizeLearningText(claim),
|
|
210
|
+
source: sanitizeLearningText(source),
|
|
211
|
+
evidence: evidence
|
|
212
|
+
.filter((entry) => typeof entry === "string" && entry.trim())
|
|
213
|
+
.map(sanitizeLearningText),
|
|
214
|
+
files_involved: filesInvolved
|
|
215
|
+
.filter((entry) => typeof entry === "string" && entry.trim())
|
|
216
|
+
.map(sanitizeLearningText),
|
|
217
|
+
decisions_made: decisionsMade
|
|
218
|
+
.filter((entry) => typeof entry === "string" && entry.trim())
|
|
219
|
+
.map(sanitizeLearningText),
|
|
220
|
+
known_risks: knownRisks
|
|
221
|
+
.filter((entry) => typeof entry === "string" && entry.trim())
|
|
222
|
+
.map(sanitizeLearningText),
|
|
223
|
+
user_preferences: userPreferences && typeof userPreferences === "object" ? userPreferences : {},
|
|
224
|
+
status,
|
|
225
|
+
authority: "learning_memory",
|
|
226
|
+
freshness: createFreshness({ checkedAt: createdAt }),
|
|
227
|
+
applies_to: appliesTo.filter((entry) => typeof entry === "string" && entry.trim()),
|
|
228
|
+
fact_ids: factIds.filter((entry) => typeof entry === "string" && entry.trim()),
|
|
229
|
+
cannot_mutate: ["release_state_without_owning_lane", "source_evidence", "security_boundary"],
|
|
230
|
+
next_verification: nextVerification,
|
|
231
|
+
created_at: createdAt,
|
|
232
|
+
...(failureState
|
|
233
|
+
? {
|
|
234
|
+
failure_state: failureState,
|
|
235
|
+
attempted_fixes: attemptedFixes
|
|
236
|
+
.filter((entry) => typeof entry === "string")
|
|
237
|
+
.map(sanitizeLearningText),
|
|
238
|
+
resolution_status: resolutionStatus ?? "active",
|
|
239
|
+
}
|
|
240
|
+
: {}),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function sanitizeLearningText(value) {
|
|
245
|
+
return maskSensitiveText(String(value)).sanitizedText;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function addLearningRecord(core, record) {
|
|
249
|
+
const validated = validateLearningLoopCore(core);
|
|
250
|
+
if (!learningLoopDomains.includes(record.domain)) {
|
|
251
|
+
throw new Error(`Unsupported learning domain: ${record.domain}`);
|
|
252
|
+
}
|
|
253
|
+
if (!["candidate", "verified", "rejected", "superseded"].includes(record.status)) {
|
|
254
|
+
throw new Error(`Unsupported learning record status: ${record.status}`);
|
|
255
|
+
}
|
|
256
|
+
return validateLearningLoopCore({
|
|
257
|
+
...validated,
|
|
258
|
+
records: [...validated.records, record],
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function evaluateLearningLoopReadiness(core) {
|
|
263
|
+
const validated = validateLearningLoopCore(core);
|
|
264
|
+
const coveredDomains = new Set(validated.domains.map((domain) => domain.id));
|
|
265
|
+
const verifiedDomains = new Set(
|
|
266
|
+
validated.records
|
|
267
|
+
.filter((record) => record.status === "verified")
|
|
268
|
+
.map((record) => record.domain),
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
record_type: "learning_loop_readiness",
|
|
273
|
+
ready: learningLoopDomains.every((domain) => coveredDomains.has(domain)),
|
|
274
|
+
domains: learningLoopDomains.length,
|
|
275
|
+
verified_domains: verifiedDomains.size,
|
|
276
|
+
candidate_records: validated.records.filter((record) => record.status === "candidate").length,
|
|
277
|
+
promotion_rule: validated.loop.fail_closed_rule,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export async function seedLearningLoopCoreArtifacts() {
|
|
282
|
+
await ensureDir(getRuntimeSubsystemPath("context"));
|
|
283
|
+
await writeFileIfMissing(
|
|
284
|
+
getLearningLoopCorePath(),
|
|
285
|
+
`${JSON.stringify(createDefaultLearningLoopCore(), null, 2)}\n`,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export async function loadLearningLoopCore() {
|
|
290
|
+
return validateLearningLoopCore(await readJson(getLearningLoopCorePath()));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export async function appendLearningRecord(record) {
|
|
294
|
+
const validated = createLearningRecord(record);
|
|
295
|
+
await ensureDir(getRuntimeSubsystemPath("learning"));
|
|
296
|
+
await fs.appendFile(getLearningRecordsPath(), `${JSON.stringify(validated)}\n`, "utf8");
|
|
297
|
+
return validated;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export async function recordWorkLearning({ vaultPath, ...record }) {
|
|
301
|
+
const validated = await appendLearningRecord(record);
|
|
302
|
+
if (vaultPath) await appendObsidianLearningRecord({ vaultPath, record: validated });
|
|
303
|
+
return validated;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export async function recordFailureMemory({
|
|
307
|
+
cause,
|
|
308
|
+
source = "workflow",
|
|
309
|
+
evidence = [],
|
|
310
|
+
attemptedFixes = [],
|
|
311
|
+
resolutionStatus = "active",
|
|
312
|
+
filesInvolved = [],
|
|
313
|
+
vaultPath,
|
|
314
|
+
} = {}) {
|
|
315
|
+
if (!cause) throw new Error("failure memory requires cause");
|
|
316
|
+
if (!["active", "resolved", "stale"].includes(resolutionStatus)) {
|
|
317
|
+
throw new Error(`Unsupported failure resolution status: ${resolutionStatus}`);
|
|
318
|
+
}
|
|
319
|
+
return recordWorkLearning({
|
|
320
|
+
vaultPath,
|
|
321
|
+
domain: "code_quality_testing",
|
|
322
|
+
claim: `Failure: ${cause}`,
|
|
323
|
+
source,
|
|
324
|
+
evidence,
|
|
325
|
+
filesInvolved,
|
|
326
|
+
knownRisks: [cause],
|
|
327
|
+
status: resolutionStatus === "resolved" ? "verified" : "candidate",
|
|
328
|
+
nextVerification:
|
|
329
|
+
resolutionStatus === "resolved" ? "Monitor for recurrence" : "Re-run the failing workflow",
|
|
330
|
+
failureState: resolutionStatus,
|
|
331
|
+
attemptedFixes,
|
|
332
|
+
resolutionStatus,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export async function loadLearningRecords({ limit = 20 } = {}) {
|
|
337
|
+
const raw = await fs.readFile(getLearningRecordsPath(), "utf8").catch(() => "");
|
|
338
|
+
return raw
|
|
339
|
+
.split("\n")
|
|
340
|
+
.filter(Boolean)
|
|
341
|
+
.map((line) => JSON.parse(line))
|
|
342
|
+
.slice(-Math.max(1, Math.min(100, limit)))
|
|
343
|
+
.reverse();
|
|
344
|
+
}
|