@jstn-sdk/ma 0.1.12 → 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.
- package/.agents/plugins/marketplace.json +0 -0
- package/.codex/agents/Architect.toml +0 -2
- package/.codex/agents/Auditor.toml +0 -2
- package/.codex/agents/Builder.toml +0 -2
- package/.codex/agents/Flow.toml +0 -2
- package/.codex/agents/Sage.toml +0 -2
- package/.codex/agents/Vibe.toml +0 -2
- package/.codex/hooks.json +14 -13
- package/.codex/prompts/enforcement.md +4 -0
- package/.codex/prompts/skill-contract.md +4 -0
- package/COVERAGE.md +211 -0
- package/DEMO.md +265 -0
- package/README.md +159 -16
- package/bin/ma.js +219 -14
- 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 +4 -1
- 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 -0
- package/docs/getting-started.md +38 -22
- package/docs/installed-sdk.md +0 -0
- package/docs/mcp-setup.md +35 -0
- package/docs/onboarding.md +18 -2
- package/docs/prompt-guidance-contract.md +17 -0
- package/docs/prompt-guidance-fragments/active-autonomy-core.md +7 -0
- package/docs/qa/release-issue-gates-0.1.13.json +644 -0
- package/docs/qa/{release-readiness-0.1.12.md → release-readiness-0.1.13.md} +25 -9
- package/docs/qa/release-readiness-0.1.5.md +1 -1
- package/docs/reference/native-engineering-patterns.md +0 -0
- package/docs/reference/native-security-playbooks.md +6 -0
- package/docs/reference/native-source-selection.md +6 -0
- package/docs/reference/native-style-and-deslop.md +0 -0
- package/docs/release-spec.md +25 -9
- package/docs/skills.md +14 -1
- package/index.js +222 -2
- package/mcp/collections.json +23 -6
- package/mcp/local/code-intel.js +0 -0
- package/mcp/local/memory.js +0 -0
- package/mcp/local/playbooks.js +0 -0
- package/mcp/local/state.js +0 -0
- package/mcp/local/team-run.js +48 -1
- package/mcp/local/trace.js +0 -0
- package/mcp/local-capabilities.json +0 -0
- package/mcp/native-playbooks.json +0 -0
- package/mcp/servers.json +24 -0
- package/package.json +5 -2
- 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 +401 -0
- package/plugins/meta-architect/obsidian/manifest.json +9 -0
- package/plugins/meta-architect/obsidian/styles.css +7 -0
- package/plugins/meta-architect/skills/align/SKILL.md +0 -0
- package/plugins/meta-architect/skills/align/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/align/references/shared-language.md +0 -0
- package/plugins/meta-architect/skills/arch/SKILL.md +2 -0
- package/plugins/meta-architect/skills/arch/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/build/SKILL.md +3 -0
- package/plugins/meta-architect/skills/build/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/cleanup/SKILL.md +0 -0
- package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +0 -0
- package/plugins/meta-architect/skills/diagnose/SKILL.md +0 -0
- package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +2 -0
- package/plugins/meta-architect/skills/flow/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/maestro/SKILL.md +0 -0
- package/plugins/meta-architect/skills/maestro/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/maestro/references/core-release-rules.md +0 -0
- package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +0 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +2 -0
- package/plugins/meta-architect/skills/sage/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/sage/references/source-selection.md +8 -0
- package/plugins/meta-architect/skills/tdd/SKILL.md +0 -0
- package/plugins/meta-architect/skills/tdd/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +2 -0
- package/plugins/meta-architect/skills/vet/agents/openai.yaml +0 -0
- package/plugins/meta-architect/skills/vet/references/security-playbooks.md +7 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +2 -0
- package/plugins/meta-architect/skills/vibe/agents/openai.yaml +0 -0
- package/scripts/active-autonomy-hook.mjs +96 -0
- package/scripts/biome-staged.js +0 -0
- package/scripts/build-linux-packages.mjs +0 -0
- package/scripts/doctor.js +17 -4
- package/scripts/install.sh +28 -0
- package/scripts/linux-package-lib.mjs +0 -0
- package/scripts/linux-package-smoke.mjs +0 -0
- package/scripts/plugin-sync.js +0 -0
- package/scripts/postinstall.js +0 -0
- package/scripts/ralph/prompt.md +35 -0
- package/scripts/release-metadata.js +0 -0
- package/scripts/release-sync.js +0 -0
- package/scripts/release-verify.js +166 -1
- package/scripts/setup-npmrc.js +0 -0
- package/skills/align/SKILL.md +0 -0
- package/skills/align/agents/openai.yaml +0 -0
- package/skills/align/references/shared-language.md +0 -0
- package/skills/arch/SKILL.md +2 -0
- package/skills/arch/agents/openai.yaml +0 -0
- package/skills/build/SKILL.md +3 -0
- package/skills/build/agents/openai.yaml +0 -0
- package/skills/cleanup/SKILL.md +0 -0
- package/skills/cleanup/agents/openai.yaml +0 -0
- package/skills/cleanup/references/style-and-deslop.md +0 -0
- package/skills/diagnose/SKILL.md +0 -0
- package/skills/diagnose/agents/openai.yaml +0 -0
- package/skills/flow/SKILL.md +2 -0
- package/skills/flow/agents/openai.yaml +0 -0
- package/skills/maestro/SKILL.md +0 -0
- package/skills/maestro/agents/openai.yaml +0 -0
- package/skills/maestro/references/core-release-rules.md +0 -0
- package/skills/maestro/references/native-ingest-map.md +0 -0
- package/skills/sage/SKILL.md +2 -0
- package/skills/sage/agents/openai.yaml +0 -0
- package/skills/sage/references/source-selection.md +8 -0
- package/skills/tdd/SKILL.md +0 -0
- package/skills/tdd/agents/openai.yaml +0 -0
- package/skills/vet/SKILL.md +2 -0
- package/skills/vet/agents/openai.yaml +0 -0
- package/skills/vet/references/security-playbooks.md +7 -0
- package/skills/vibe/SKILL.md +2 -0
- package/skills/vibe/agents/openai.yaml +0 -0
- package/src/bootstrap.js +17 -0
- package/src/build-gate.js +2 -2
- package/src/launcher.js +4 -0
- package/src/mcp-live-client.js +289 -3
- package/src/paths.js +4 -0
- package/src/policy.js +1 -1
- package/src/release-issue-gates.js +190 -0
- package/src/runtime/active-autonomy-core.js +208 -0
- package/src/runtime/alignment-sentinel.js +165 -0
- package/src/runtime/architect-review.js +88 -0
- package/src/runtime/build-readiness.js +28 -4
- package/src/runtime/code-graph-rehearse.js +113 -0
- package/src/runtime/context-economy-core.js +276 -0
- package/src/runtime/continuity-notes.js +0 -0
- package/src/runtime/core-source-ingest.js +379 -0
- package/src/runtime/detached-provider.js +74 -0
- package/src/runtime/environment-awareness-core.js +460 -0
- package/src/runtime/exposure-catalog.js +276 -0
- package/src/runtime/guidance-stack.js +0 -0
- package/src/runtime/helper-orchestration-core.js +307 -0
- package/src/runtime/learning-loop-core.js +238 -0
- package/src/runtime/maestro-events.js +18 -0
- package/src/runtime/maestro-manager.js +19 -0
- package/src/runtime/maestro-state.js +125 -0
- package/src/runtime/mcp-policy.js +192 -0
- package/src/runtime/obsidian-integration-core.js +851 -0
- package/src/runtime/obsidian-plugin-bridge.js +739 -0
- package/src/runtime/orchestrator.js +0 -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 +174 -0
- package/src/runtime/runtime-state.js +843 -2
- package/src/runtime/semantic-recording-core.js +147 -0
- package/src/runtime/signal-hooks.js +15 -0
- package/src/runtime/skills-registry-export.js +670 -0
- package/src/runtime/startup-path.js +0 -0
- package/src/runtime/universal-plugin-broker-core.js +575 -0
- package/src/runtime/workspace-intelligence-runtime.js +674 -0
- package/src/runtime/workspace-virtualizer.js +102 -0
- package/src/runtime/workspaces.js +0 -0
- package/src/runtime-artifacts.js +225 -62
- package/src/skill-installer.js +0 -0
- package/src/skills.js +876 -84
|
File without changes
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { ensureDir, readJson, writeFileIfMissing } from "../fs-utils.js";
|
|
2
|
+
import { getRuntimeSubsystemPath } from "../paths.js";
|
|
3
|
+
|
|
4
|
+
export const promptStrategyCoreSchemaVersion = "0.1.0";
|
|
5
|
+
|
|
6
|
+
export function getPromptStrategyCorePath() {
|
|
7
|
+
return getRuntimeSubsystemPath("context", "prompt-strategy-core.json");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createDefaultPromptStrategyCore() {
|
|
11
|
+
return {
|
|
12
|
+
schemaVersion: promptStrategyCoreSchemaVersion,
|
|
13
|
+
product: "Meta-Architect",
|
|
14
|
+
purpose:
|
|
15
|
+
"First-party MA policy for selecting prompt strategies across lanes, roles, workers, reviewers, and exported host payloads.",
|
|
16
|
+
evidence_source: {
|
|
17
|
+
kind: "gitmcp-evidence",
|
|
18
|
+
category: "prompt-techniques",
|
|
19
|
+
repo: "NirDiamant/Prompt_Engineering",
|
|
20
|
+
endpoint: "https://gitmcp.io/NirDiamant/Prompt_Engineering",
|
|
21
|
+
reference_path: "all_prompt_engineering_techniques",
|
|
22
|
+
},
|
|
23
|
+
technique_families: [
|
|
24
|
+
{
|
|
25
|
+
id: "clarity_control",
|
|
26
|
+
semantic_role: "ambiguity_reduction",
|
|
27
|
+
reference_topics: [
|
|
28
|
+
"ambiguity-clarity",
|
|
29
|
+
"basic-prompt-structures",
|
|
30
|
+
"instruction-engineering",
|
|
31
|
+
"specific-task-prompts",
|
|
32
|
+
],
|
|
33
|
+
ma_use:
|
|
34
|
+
"Clarify task intent, output contract, constraints, and unknowns before lane execution.",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "decomposition_sequence",
|
|
38
|
+
semantic_role: "work_breakdown",
|
|
39
|
+
reference_topics: ["task-decomposition-prompts", "prompt-chaining-sequencing"],
|
|
40
|
+
ma_use:
|
|
41
|
+
"Break broad requests into lane-owned steps, PRD stories, and verification handoffs.",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "reasoning_validation",
|
|
45
|
+
semantic_role: "answer_quality_control",
|
|
46
|
+
reference_topics: [
|
|
47
|
+
"cot-prompting",
|
|
48
|
+
"self-consistency",
|
|
49
|
+
"evaluating-prompt-effectiveness",
|
|
50
|
+
"prompt-optimization-techniques",
|
|
51
|
+
],
|
|
52
|
+
ma_use:
|
|
53
|
+
"Use structured reasoning and cross-checks internally, then emit evidence-backed conclusions rather than private reasoning traces.",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "generation_constraints",
|
|
57
|
+
semantic_role: "bounded_output_shape",
|
|
58
|
+
reference_topics: [
|
|
59
|
+
"constrained-guided-generation",
|
|
60
|
+
"negative-prompting",
|
|
61
|
+
"prompt-formatting-structure",
|
|
62
|
+
"prompt-templates-variables-jinja2",
|
|
63
|
+
],
|
|
64
|
+
ma_use:
|
|
65
|
+
"Constrain lane artifacts, host payloads, semantic receipts, and compatibility exports.",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "context_and_examples",
|
|
69
|
+
semantic_role: "context_selection",
|
|
70
|
+
reference_topics: [
|
|
71
|
+
"zero-shot-prompting",
|
|
72
|
+
"few-shot-learning",
|
|
73
|
+
"role-prompting",
|
|
74
|
+
"prompt-length-complexity-management",
|
|
75
|
+
"multilingual-prompting",
|
|
76
|
+
],
|
|
77
|
+
ma_use:
|
|
78
|
+
"Select minimal examples, role boundaries, language constraints, and context budgets for each workspace surface.",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "safety_integrity",
|
|
82
|
+
semantic_role: "prompt_safety",
|
|
83
|
+
reference_topics: ["prompt-security-and-safety", "ethical-prompt-engineering"],
|
|
84
|
+
ma_use:
|
|
85
|
+
"Preserve security warnings, redaction boundaries, authority semantics, and high-stakes safety language.",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
lane_policy: {
|
|
89
|
+
$maestro: ["clarity_control", "decomposition_sequence", "generation_constraints"],
|
|
90
|
+
$arch: ["clarity_control", "decomposition_sequence", "reasoning_validation"],
|
|
91
|
+
$sage: ["clarity_control", "generation_constraints", "safety_integrity"],
|
|
92
|
+
$flow: ["decomposition_sequence", "reasoning_validation", "generation_constraints"],
|
|
93
|
+
$vet: ["safety_integrity", "reasoning_validation", "generation_constraints"],
|
|
94
|
+
$vibe: ["clarity_control", "context_and_examples", "generation_constraints"],
|
|
95
|
+
$build: ["decomposition_sequence", "reasoning_validation", "safety_integrity"],
|
|
96
|
+
ralph_execution_core: [
|
|
97
|
+
"decomposition_sequence",
|
|
98
|
+
"generation_constraints",
|
|
99
|
+
"safety_integrity",
|
|
100
|
+
],
|
|
101
|
+
exported_host_payloads: [
|
|
102
|
+
"generation_constraints",
|
|
103
|
+
"context_and_examples",
|
|
104
|
+
"safety_integrity",
|
|
105
|
+
],
|
|
106
|
+
active_autonomy_core: [
|
|
107
|
+
"clarity_control",
|
|
108
|
+
"decomposition_sequence",
|
|
109
|
+
"generation_constraints",
|
|
110
|
+
"safety_integrity",
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
role_policy: {
|
|
114
|
+
architect: ["clarity_control", "decomposition_sequence", "reasoning_validation"],
|
|
115
|
+
executor: ["decomposition_sequence", "generation_constraints", "safety_integrity"],
|
|
116
|
+
verifier: ["reasoning_validation", "generation_constraints", "safety_integrity"],
|
|
117
|
+
reviewer: ["reasoning_validation", "safety_integrity", "generation_constraints"],
|
|
118
|
+
worker: ["decomposition_sequence", "generation_constraints", "context_and_examples"],
|
|
119
|
+
writer: ["clarity_control", "context_and_examples", "generation_constraints"],
|
|
120
|
+
designer: ["clarity_control", "context_and_examples", "reasoning_validation"],
|
|
121
|
+
},
|
|
122
|
+
hard_rules: [
|
|
123
|
+
"Prompt Strategy Core is an internal MA policy, not a user-facing skill family.",
|
|
124
|
+
"Prompt techniques cannot override lane ownership, semantic receipts, redaction, or release-state authority.",
|
|
125
|
+
"Prompt techniques cannot weaken AUTO-CONTINUE / ASK rules or permission-handoff bans.",
|
|
126
|
+
"Reasoning techniques may structure internal work, but public artifacts report conclusions, evidence, and verification gaps rather than private deliberation traces.",
|
|
127
|
+
"Few-shot or template examples must be MA-owned and workspace-safe before export.",
|
|
128
|
+
"Safety and prompt-security rules cannot be compressed away by Context Economy Core.",
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function validatePromptStrategyCore(value) {
|
|
134
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
135
|
+
throw new Error("prompt strategy core must be an object");
|
|
136
|
+
}
|
|
137
|
+
if (value.schemaVersion !== promptStrategyCoreSchemaVersion) {
|
|
138
|
+
throw new Error(`Unsupported prompt strategy core schemaVersion: ${value.schemaVersion}`);
|
|
139
|
+
}
|
|
140
|
+
if (value.evidence_source?.repo !== "NirDiamant/Prompt_Engineering") {
|
|
141
|
+
throw new Error("prompt strategy core requires the Prompt_Engineering evidence source");
|
|
142
|
+
}
|
|
143
|
+
if (!Array.isArray(value.technique_families) || value.technique_families.length === 0) {
|
|
144
|
+
throw new Error("prompt strategy core requires technique_families");
|
|
145
|
+
}
|
|
146
|
+
if (!value.lane_policy || typeof value.lane_policy !== "object") {
|
|
147
|
+
throw new Error("prompt strategy core requires lane_policy");
|
|
148
|
+
}
|
|
149
|
+
if (!value.role_policy || typeof value.role_policy !== "object") {
|
|
150
|
+
throw new Error("prompt strategy core requires role_policy");
|
|
151
|
+
}
|
|
152
|
+
if (JSON.stringify(value).includes(".omx")) {
|
|
153
|
+
throw new Error("prompt strategy core must not expose OMX runtime paths");
|
|
154
|
+
}
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function resolvePromptStrategyForSurface({ core, surface, risk = "standard" }) {
|
|
159
|
+
const policy = validatePromptStrategyCore(core);
|
|
160
|
+
const techniques = policy.lane_policy?.[surface] ?? policy.lane_policy?.exported_host_payloads;
|
|
161
|
+
if (!Array.isArray(techniques) || techniques.length === 0) {
|
|
162
|
+
throw new Error(`No prompt strategy policy for surface: ${surface}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const required = new Set(techniques);
|
|
166
|
+
if (["high", "security", "release"].includes(risk)) {
|
|
167
|
+
required.add("safety_integrity");
|
|
168
|
+
required.add("reasoning_validation");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
record_type: "prompt_strategy_resolution",
|
|
173
|
+
surface,
|
|
174
|
+
risk,
|
|
175
|
+
techniques: [...required],
|
|
176
|
+
evidence_source: policy.evidence_source,
|
|
177
|
+
authority_boundary: {
|
|
178
|
+
may_override_lane_authority: false,
|
|
179
|
+
may_remove_safety_language: false,
|
|
180
|
+
reports_private_reasoning: false,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function resolvePromptStrategyForRole({
|
|
186
|
+
core,
|
|
187
|
+
role,
|
|
188
|
+
surface = "$maestro",
|
|
189
|
+
risk = "standard",
|
|
190
|
+
} = {}) {
|
|
191
|
+
const policy = validatePromptStrategyCore(core);
|
|
192
|
+
const roleTechniques = policy.role_policy?.[role] ?? policy.role_policy?.worker;
|
|
193
|
+
if (!Array.isArray(roleTechniques) || roleTechniques.length === 0) {
|
|
194
|
+
throw new Error(`No prompt strategy policy for role: ${role}`);
|
|
195
|
+
}
|
|
196
|
+
const surfaceResolution = resolvePromptStrategyForSurface({ core: policy, surface, risk });
|
|
197
|
+
const techniques = new Set([...surfaceResolution.techniques, ...roleTechniques]);
|
|
198
|
+
if (role === "verifier" || role === "reviewer") {
|
|
199
|
+
techniques.add("reasoning_validation");
|
|
200
|
+
techniques.add("safety_integrity");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
record_type: "prompt_strategy_role_resolution",
|
|
205
|
+
role,
|
|
206
|
+
surface,
|
|
207
|
+
risk,
|
|
208
|
+
techniques: [...techniques],
|
|
209
|
+
evidence_source: policy.evidence_source,
|
|
210
|
+
authority_boundary: surfaceResolution.authority_boundary,
|
|
211
|
+
output_contract: {
|
|
212
|
+
outcome_first: true,
|
|
213
|
+
evidence_required: ["verifier", "reviewer", "executor"].includes(role),
|
|
214
|
+
private_reasoning_reported: false,
|
|
215
|
+
may_override_lane_authority: false,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export async function seedPromptStrategyCoreArtifacts() {
|
|
221
|
+
await ensureDir(getRuntimeSubsystemPath("context"));
|
|
222
|
+
await writeFileIfMissing(
|
|
223
|
+
getPromptStrategyCorePath(),
|
|
224
|
+
`${JSON.stringify(createDefaultPromptStrategyCore(), null, 2)}\n`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export async function loadPromptStrategyCore() {
|
|
229
|
+
return validatePromptStrategyCore(await readJson(getPromptStrategyCorePath()));
|
|
230
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export const quorumDecisions = {
|
|
2
|
+
APPROVED: "APPROVED",
|
|
3
|
+
REJECTED: "REJECTED",
|
|
4
|
+
INDETERMINATE: "INDETERMINATE",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
function createFingerprintKey(fingerprint) {
|
|
8
|
+
if (!fingerprint || typeof fingerprint !== "object") {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return JSON.stringify(fingerprint);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function evaluateQuorumVotes(votes = []) {
|
|
16
|
+
if (!Array.isArray(votes) || votes.length === 0) {
|
|
17
|
+
return {
|
|
18
|
+
decision: quorumDecisions.INDETERMINATE,
|
|
19
|
+
winningFingerprint: null,
|
|
20
|
+
blockers: ["No quorum votes were supplied."],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const tallies = new Map();
|
|
25
|
+
const majorityTarget = Math.floor(votes.length / 2) + 1;
|
|
26
|
+
|
|
27
|
+
for (const vote of votes) {
|
|
28
|
+
const fingerprintKey = createFingerprintKey(vote.fingerprint);
|
|
29
|
+
const key = `${vote.decision}::${fingerprintKey ?? "null"}`;
|
|
30
|
+
const tally = tallies.get(key) ?? {
|
|
31
|
+
decision: vote.decision,
|
|
32
|
+
fingerprint: vote.fingerprint ?? null,
|
|
33
|
+
count: 0,
|
|
34
|
+
};
|
|
35
|
+
tally.count += 1;
|
|
36
|
+
tallies.set(key, tally);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const winning = [...tallies.values()].find((entry) => entry.count >= majorityTarget);
|
|
40
|
+
if (!winning) {
|
|
41
|
+
return {
|
|
42
|
+
decision: quorumDecisions.INDETERMINATE,
|
|
43
|
+
winningFingerprint: null,
|
|
44
|
+
blockers: ["Quorum votes did not converge on a majority-compatible fingerprint."],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
decision: winning.decision,
|
|
50
|
+
winningFingerprint: winning.fingerprint,
|
|
51
|
+
blockers: [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function createQuorumReviewReceipt({ votes = [], evaluation }) {
|
|
56
|
+
const result = evaluation ?? evaluateQuorumVotes(votes);
|
|
57
|
+
const majorityFingerprint = result.winningFingerprint
|
|
58
|
+
? JSON.stringify(result.winningFingerprint)
|
|
59
|
+
: null;
|
|
60
|
+
const minorityVotes = votes.filter((vote) => {
|
|
61
|
+
if (result.decision === quorumDecisions.INDETERMINATE) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return (
|
|
65
|
+
vote.decision !== result.decision ||
|
|
66
|
+
JSON.stringify(vote.fingerprint ?? null) !== majorityFingerprint
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
record_type: "quorum_review_receipt",
|
|
72
|
+
decision: result.decision,
|
|
73
|
+
winningFingerprint: result.winningFingerprint,
|
|
74
|
+
reviewer_count: votes.length,
|
|
75
|
+
minority_report: minorityVotes.map((vote) => ({
|
|
76
|
+
model_identifier: vote.model_identifier ?? "unknown",
|
|
77
|
+
decision: vote.decision,
|
|
78
|
+
fingerprint: vote.fingerprint ?? null,
|
|
79
|
+
blockers: vote.blockers ?? [],
|
|
80
|
+
rationale_summary: vote.rationale_summary ?? "",
|
|
81
|
+
})),
|
|
82
|
+
confidence_receipt: {
|
|
83
|
+
records_as: "verification_confidence",
|
|
84
|
+
production_evidence: false,
|
|
85
|
+
may_mark_build_done: result.decision === quorumDecisions.APPROVED,
|
|
86
|
+
requires_existing_build_gate_evidence: true,
|
|
87
|
+
},
|
|
88
|
+
blockers: result.blockers,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { writeJson } from "../fs-utils.js";
|
|
4
|
+
import { getRuntimeWritePath } from "../paths.js";
|
|
5
|
+
|
|
6
|
+
export const ralphPrdSchemaVersion = "0.1.0";
|
|
7
|
+
|
|
8
|
+
export function getRalphPrdPath() {
|
|
9
|
+
return getRuntimeWritePath("plans", "prd.json");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getRalphProgressPath() {
|
|
13
|
+
return getRuntimeWritePath("plans", "progress.txt");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function slugify(value) {
|
|
17
|
+
return `${value}`
|
|
18
|
+
.trim()
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
21
|
+
.replace(/^-+|-+$/g, "");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createRalphPrdContract({
|
|
25
|
+
project = "Meta-Architect-Build",
|
|
26
|
+
branchName = "ralph/meta-architect-build",
|
|
27
|
+
description = "Execute the current bounded Meta-Architect build slice under MA gates.",
|
|
28
|
+
buildSlice = [],
|
|
29
|
+
verificationPlan = [],
|
|
30
|
+
runtimeSummary = null,
|
|
31
|
+
}) {
|
|
32
|
+
const safeProject = project.trim() || "Meta-Architect-Build";
|
|
33
|
+
const safeBranch = branchName.trim() || `ralph/${slugify(safeProject)}`;
|
|
34
|
+
const storyDescription =
|
|
35
|
+
buildSlice.length > 0
|
|
36
|
+
? buildSlice.join(" ")
|
|
37
|
+
: "Implement one reversible, bounded story from the approved MA plan.";
|
|
38
|
+
const acceptanceCriteria = [
|
|
39
|
+
...verificationPlan,
|
|
40
|
+
"Run the smallest relevant real-workspace verification before marking the story passed.",
|
|
41
|
+
"Preserve Obsidian/vault-derived context as vault_context, not build_evidence.",
|
|
42
|
+
"Preserve Context Economy safety valves for warnings, irreversible actions, failed checks, and known gaps.",
|
|
43
|
+
"Do not mutate .ma/release.json or .ma/decisions.json directly from the execution loop.",
|
|
44
|
+
].filter((item, index, items) => item && items.indexOf(item) === index);
|
|
45
|
+
|
|
46
|
+
return validateRalphPrdContract({
|
|
47
|
+
schemaVersion: ralphPrdSchemaVersion,
|
|
48
|
+
product: "Meta-Architect",
|
|
49
|
+
project: safeProject,
|
|
50
|
+
branchName: safeBranch,
|
|
51
|
+
description,
|
|
52
|
+
authority: "$maestro_or_owning_lane_dispatch",
|
|
53
|
+
evidenceBoundary: {
|
|
54
|
+
obsidianRecordsAs: runtimeSummary?.obsidianRecordsAs ?? "vault_context",
|
|
55
|
+
virtualWorkspaceRecordsAs:
|
|
56
|
+
runtimeSummary?.workspaceVirtualizerRecordsAs ?? "virtual_workspace_result",
|
|
57
|
+
rehearsalRecordsAs: runtimeSummary?.codeGraphRehearseRecordsAs ?? "rehearsal_trace",
|
|
58
|
+
releaseStateMutationAllowed: false,
|
|
59
|
+
},
|
|
60
|
+
qualityGates: ["$arch", "$sage", "$flow", "$vet", "$vibe", "$build"],
|
|
61
|
+
userStories: [
|
|
62
|
+
{
|
|
63
|
+
id: "US-001",
|
|
64
|
+
title: "Execute bounded MA build slice",
|
|
65
|
+
description: storyDescription,
|
|
66
|
+
acceptanceCriteria,
|
|
67
|
+
priority: 1,
|
|
68
|
+
passes: false,
|
|
69
|
+
notes:
|
|
70
|
+
"Ralph Execution Core executes story-by-story after MA gates pass; $build owns final promotion readiness.",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function validateRalphPrdContract(value) {
|
|
77
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
78
|
+
throw new Error("Ralph PRD contract must be an object");
|
|
79
|
+
}
|
|
80
|
+
if (value.schemaVersion !== ralphPrdSchemaVersion) {
|
|
81
|
+
throw new Error(`Unsupported Ralph PRD schemaVersion: ${value.schemaVersion}`);
|
|
82
|
+
}
|
|
83
|
+
if (!value.project || !value.branchName || !value.description) {
|
|
84
|
+
throw new Error("Ralph PRD contract requires project, branchName, and description");
|
|
85
|
+
}
|
|
86
|
+
if (value.authority !== "$maestro_or_owning_lane_dispatch") {
|
|
87
|
+
throw new Error("Ralph PRD authority must stay with $maestro or owning lane dispatch");
|
|
88
|
+
}
|
|
89
|
+
if (value.evidenceBoundary?.releaseStateMutationAllowed !== false) {
|
|
90
|
+
throw new Error("Ralph PRD must not allow direct release-state mutation");
|
|
91
|
+
}
|
|
92
|
+
if (value.evidenceBoundary?.obsidianRecordsAs !== "vault_context") {
|
|
93
|
+
throw new Error("Ralph PRD must preserve Obsidian as vault_context");
|
|
94
|
+
}
|
|
95
|
+
if (!Array.isArray(value.userStories) || value.userStories.length === 0) {
|
|
96
|
+
throw new Error("Ralph PRD requires at least one user story");
|
|
97
|
+
}
|
|
98
|
+
for (const story of value.userStories) {
|
|
99
|
+
if (!story.id || !story.title || !story.description) {
|
|
100
|
+
throw new Error("Ralph story requires id, title, and description");
|
|
101
|
+
}
|
|
102
|
+
if (!Array.isArray(story.acceptanceCriteria) || story.acceptanceCriteria.length === 0) {
|
|
103
|
+
throw new Error(`Ralph story ${story.id} requires acceptance criteria`);
|
|
104
|
+
}
|
|
105
|
+
if (story.passes !== false && story.passes !== true) {
|
|
106
|
+
throw new Error(`Ralph story ${story.id} requires boolean passes`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function writeRalphExecutionContract(options) {
|
|
113
|
+
const prd = createRalphPrdContract(options);
|
|
114
|
+
const prdPath = getRalphPrdPath();
|
|
115
|
+
const progressPath = getRalphProgressPath();
|
|
116
|
+
await writeJson(prdPath, prd);
|
|
117
|
+
await fs.mkdir(path.dirname(progressPath), { recursive: true });
|
|
118
|
+
await fs.writeFile(
|
|
119
|
+
progressPath,
|
|
120
|
+
[
|
|
121
|
+
"# Ralph Execution Progress",
|
|
122
|
+
"",
|
|
123
|
+
`Initialized: ${new Date().toISOString()}`,
|
|
124
|
+
"",
|
|
125
|
+
"## Codebase Patterns",
|
|
126
|
+
"",
|
|
127
|
+
"No reusable execution learnings recorded yet.",
|
|
128
|
+
"",
|
|
129
|
+
"## Iterations",
|
|
130
|
+
"",
|
|
131
|
+
"- pending: US-001 awaits MA-gated execution and fresh verification evidence.",
|
|
132
|
+
"",
|
|
133
|
+
].join("\n"),
|
|
134
|
+
);
|
|
135
|
+
return { prd, prdPath, progressPath };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function completeRalphStory({ prd, storyId, verificationEvidence = [], notes = "" }) {
|
|
139
|
+
const next = validateRalphPrdContract(JSON.parse(JSON.stringify(prd)));
|
|
140
|
+
if (!Array.isArray(verificationEvidence) || verificationEvidence.length === 0) {
|
|
141
|
+
throw new Error("Ralph story completion requires fresh verification evidence");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const story = next.userStories.find((candidate) => candidate.id === storyId);
|
|
145
|
+
if (!story) {
|
|
146
|
+
throw new Error(`Ralph story not found: ${storyId}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
story.passes = true;
|
|
150
|
+
story.notes = [story.notes, notes, `verification: ${verificationEvidence.join("; ")}`]
|
|
151
|
+
.filter(Boolean)
|
|
152
|
+
.join("\n");
|
|
153
|
+
return validateRalphPrdContract(next);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function selectNextRalphStory({ prd } = {}) {
|
|
157
|
+
const contract = validateRalphPrdContract(prd);
|
|
158
|
+
const candidates = contract.userStories
|
|
159
|
+
.filter((story) => story.passes === false)
|
|
160
|
+
.sort((a, b) => Number(a.priority ?? 999) - Number(b.priority ?? 999));
|
|
161
|
+
return candidates[0] ?? null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function createRalphIterationPlan({ prd, progress = "", role = "executor" } = {}) {
|
|
165
|
+
const contract = validateRalphPrdContract(prd);
|
|
166
|
+
const story = selectNextRalphStory({ prd: contract });
|
|
167
|
+
if (!story) {
|
|
168
|
+
return {
|
|
169
|
+
record_type: "ralph_iteration_plan",
|
|
170
|
+
status: "complete",
|
|
171
|
+
records_as: "execution_plan",
|
|
172
|
+
build_evidence: false,
|
|
173
|
+
authority: contract.authority,
|
|
174
|
+
next_story: null,
|
|
175
|
+
instruction:
|
|
176
|
+
"All Ralph stories are passed. Return through $maestro or the owning lane with verification evidence.",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
record_type: "ralph_iteration_plan",
|
|
182
|
+
status: "ready",
|
|
183
|
+
records_as: "execution_plan",
|
|
184
|
+
build_evidence: false,
|
|
185
|
+
authority: contract.authority,
|
|
186
|
+
role,
|
|
187
|
+
next_story: {
|
|
188
|
+
id: story.id,
|
|
189
|
+
title: story.title,
|
|
190
|
+
description: story.description,
|
|
191
|
+
acceptanceCriteria: story.acceptanceCriteria,
|
|
192
|
+
priority: story.priority,
|
|
193
|
+
},
|
|
194
|
+
progress_excerpt: progress.slice(-1200),
|
|
195
|
+
required_gates: contract.qualityGates,
|
|
196
|
+
stop_conditions: [
|
|
197
|
+
"fresh_verification_evidence_missing",
|
|
198
|
+
"destructive_or_irreversible_action_required",
|
|
199
|
+
"credential_or_external_production_authority_missing",
|
|
200
|
+
"same_failure_repeats_three_times",
|
|
201
|
+
],
|
|
202
|
+
loop_instruction:
|
|
203
|
+
"Execute exactly this story, run real verification, update progress, then mark passes only with fresh evidence.",
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function appendRalphProgressEntry({ current = "", storyId, status, evidence = [] }) {
|
|
208
|
+
if (!storyId || !status) {
|
|
209
|
+
throw new Error("Ralph progress entry requires storyId and status");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return [
|
|
213
|
+
current.trimEnd(),
|
|
214
|
+
`- ${new Date().toISOString()}: ${storyId} ${status}; evidence=${evidence.join(", ") || "none"}`,
|
|
215
|
+
"",
|
|
216
|
+
].join("\n");
|
|
217
|
+
}
|