@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.
- 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 +287 -37
- package/bin/ma.js +232 -71
- 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 +7 -1
- package/docs/getting-started.md +108 -37
- package/docs/installed-sdk.md +23 -0
- package/docs/mcp-setup.md +65 -1
- 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.13.md +116 -0
- package/docs/qa/release-readiness-0.1.5.md +1 -1
- package/docs/reference/native-engineering-patterns.md +35 -0
- package/docs/reference/native-security-playbooks.md +27 -0
- package/docs/reference/native-source-selection.md +27 -0
- package/docs/reference/native-style-and-deslop.md +20 -0
- package/docs/release-spec.md +37 -10
- package/docs/skills-publishing.md +25 -1
- package/docs/skills.md +37 -12
- package/index.js +222 -2
- package/mcp/collections.json +23 -6
- package/mcp/local/code-intel.js +113 -0
- package/mcp/local/memory.js +46 -0
- package/mcp/local/playbooks.js +168 -0
- package/mcp/local/state.js +71 -0
- package/mcp/local/team-run.js +113 -0
- package/mcp/local/trace.js +60 -0
- package/mcp/local-capabilities.json +56 -0
- package/mcp/native-playbooks.json +117 -0
- package/mcp/servers.json +34 -0
- package/package.json +8 -2
- package/plugins/meta-architect/.app.json +1 -1
- package/plugins/meta-architect/.codex-plugin/plugin.json +4 -4
- package/plugins/meta-architect/.mcp.json +1 -1
- package/plugins/meta-architect/README.md +34 -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 +24 -0
- package/plugins/meta-architect/skills/align/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/align/references/shared-language.md +24 -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/cleanup/SKILL.md +23 -0
- package/plugins/meta-architect/skills/cleanup/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/cleanup/references/style-and-deslop.md +18 -0
- package/plugins/meta-architect/skills/diagnose/SKILL.md +24 -0
- package/plugins/meta-architect/skills/diagnose/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/flow/SKILL.md +2 -0
- package/plugins/meta-architect/skills/maestro/SKILL.md +36 -3
- package/plugins/meta-architect/skills/maestro/agents/openai.yaml +2 -2
- package/plugins/meta-architect/skills/maestro/references/native-ingest-map.md +44 -0
- package/plugins/meta-architect/skills/sage/SKILL.md +5 -1
- package/plugins/meta-architect/skills/sage/references/source-selection.md +36 -0
- package/plugins/meta-architect/skills/tdd/SKILL.md +24 -0
- package/plugins/meta-architect/skills/tdd/agents/openai.yaml +4 -0
- package/plugins/meta-architect/skills/vet/SKILL.md +5 -1
- package/plugins/meta-architect/skills/vet/references/security-playbooks.md +30 -0
- package/plugins/meta-architect/skills/vibe/SKILL.md +2 -0
- package/scripts/active-autonomy-hook.mjs +96 -0
- package/scripts/build-linux-packages.mjs +328 -0
- package/scripts/doctor.js +36 -4
- package/scripts/install.sh +28 -0
- package/scripts/linux-package-lib.mjs +40 -0
- package/scripts/linux-package-smoke.mjs +103 -0
- package/scripts/ralph/prompt.md +35 -0
- package/scripts/release-sync.js +13 -6
- package/scripts/release-verify.js +166 -1
- package/skills/align/SKILL.md +24 -0
- package/skills/align/agents/openai.yaml +4 -0
- package/skills/align/references/shared-language.md +24 -0
- package/skills/arch/SKILL.md +2 -0
- package/skills/build/SKILL.md +3 -0
- package/skills/cleanup/SKILL.md +23 -0
- package/skills/cleanup/agents/openai.yaml +4 -0
- package/skills/cleanup/references/style-and-deslop.md +18 -0
- package/skills/diagnose/SKILL.md +24 -0
- package/skills/diagnose/agents/openai.yaml +4 -0
- package/skills/flow/SKILL.md +2 -0
- package/skills/index.json +21 -6
- package/skills/maestro/SKILL.md +36 -3
- package/skills/maestro/agents/openai.yaml +2 -2
- package/skills/maestro/references/native-ingest-map.md +44 -0
- package/skills/sage/SKILL.md +5 -1
- package/skills/sage/references/source-selection.md +36 -0
- package/skills/tdd/SKILL.md +24 -0
- package/skills/tdd/agents/openai.yaml +4 -0
- package/skills/vet/SKILL.md +5 -1
- package/skills/vet/references/security-playbooks.md +30 -0
- package/skills/vibe/SKILL.md +2 -0
- package/src/bootstrap.js +141 -24
- package/src/build-gate.js +2 -2
- package/src/decision-log.js +12 -9
- package/src/launcher.js +4 -0
- package/src/mcp-config.js +130 -8
- package/src/mcp-live-client.js +289 -3
- package/src/paths.js +37 -1
- package/src/policy.js +1 -1
- package/src/release-issue-gates.js +190 -0
- package/src/release-state.js +30 -1
- 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 +62 -0
- package/src/runtime/code-graph-rehearse.js +113 -0
- package/src/runtime/context-economy-core.js +276 -0
- package/src/runtime/continuity-notes.js +79 -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 +42 -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 +605 -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 +158 -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 +1223 -0
- package/src/runtime/semantic-recording-core.js +147 -0
- package/src/runtime/signal-hooks.js +67 -0
- package/src/runtime/skills-registry-export.js +670 -0
- package/src/runtime/startup-path.js +14 -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 +25 -0
- package/src/runtime-artifacts.js +407 -84
- package/src/skill-installer.js +53 -5
- package/src/skills.js +1454 -78
- package/src/state-sync.js +51 -8
- package/docs/qa/release-readiness-0.1.11.md +0 -79
- package/plugins/meta-architect/skills/meta-architect/SKILL.md +0 -32
- package/plugins/meta-architect/skills/meta-architect/agents/openai.yaml +0 -4
- package/skills/meta-architect/SKILL.md +0 -32
- package/skills/meta-architect/agents/openai.yaml +0 -4
- /package/plugins/meta-architect/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
- /package/skills/{meta-architect → maestro}/references/core-release-rules.md +0 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
const { MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } = require("obsidian");
|
|
2
|
+
|
|
3
|
+
const DEFAULT_SETTINGS = {
|
|
4
|
+
projectName: "Meta-Architect",
|
|
5
|
+
activeContextPath: "Meta-Architect/Plugin Context/Active Note Context.md",
|
|
6
|
+
queuePath: "Meta-Architect/Plugin Requests/request-queue.json",
|
|
7
|
+
attachmentDir: "Meta-Architect/Attachments",
|
|
8
|
+
sourceWorkspace: "",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const FORBIDDEN_TARGETS = [".ma/release.json", ".ma/decisions.json", ".ma/plans/", ".ma/specs/"];
|
|
12
|
+
|
|
13
|
+
module.exports = class MetaArchitectPlugin extends Plugin {
|
|
14
|
+
async onload() {
|
|
15
|
+
this.settings = Object.assign({}, DEFAULT_SETTINGS, (await this.loadData()) || {});
|
|
16
|
+
this.addRibbonIcon("network", "Send current note/selection to MA", async () => {
|
|
17
|
+
await this.captureActiveNote();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const statusBarItem = this.addStatusBarItem();
|
|
21
|
+
statusBarItem.addClass("ma-status");
|
|
22
|
+
statusBarItem.setText("MA: vault context");
|
|
23
|
+
|
|
24
|
+
this.addCommand({
|
|
25
|
+
id: "ma-capture-active-note",
|
|
26
|
+
name: "Send current note/selection to MA",
|
|
27
|
+
callback: async () => this.captureActiveNote(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
this.addCommand({
|
|
31
|
+
id: "ma-drain-request-queue",
|
|
32
|
+
name: "Drain MA request queue",
|
|
33
|
+
callback: async () => {
|
|
34
|
+
const result = await this.drainRequestQueue();
|
|
35
|
+
new Notice(
|
|
36
|
+
`MA queue drained: ${result.processed.length} processed, ${result.refused.length} refused`,
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
this.addCommand({
|
|
42
|
+
id: "ma-open-context-preview",
|
|
43
|
+
name: "Preview current MA context",
|
|
44
|
+
checkCallback: (checking) => {
|
|
45
|
+
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
|
46
|
+
if (!view) return false;
|
|
47
|
+
if (!checking) new ContextPreviewModal(this.app, this.createSelectionContext()).open();
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.addCommand({
|
|
53
|
+
id: "ma-open-map",
|
|
54
|
+
name: "Open MA map of content",
|
|
55
|
+
callback: async () => this.openNote("Meta-Architect/Map of Content.md"),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
this.addSettingTab(new MetaArchitectSettingTab(this.app, this));
|
|
59
|
+
this.registerProtocolHandler();
|
|
60
|
+
this.registerVaultWatchers();
|
|
61
|
+
this.registerInterval(
|
|
62
|
+
window.setInterval(() => this.drainRequestQueue().catch(() => {}), 30 * 1000),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async loadSettings() {
|
|
67
|
+
this.settings = Object.assign({}, DEFAULT_SETTINGS, (await this.loadData()) || {});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async saveSettings() {
|
|
71
|
+
await this.saveData(this.settings);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
createSelectionContext() {
|
|
75
|
+
const file = this.app.workspace.getActiveFile();
|
|
76
|
+
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
|
77
|
+
const leaf = this.app.workspace.activeLeaf;
|
|
78
|
+
const editor = view?.editor || leaf?.view?.editor;
|
|
79
|
+
const selectedText = editor?.getSelection?.() || "";
|
|
80
|
+
return {
|
|
81
|
+
record_type: "obsidian_active_note_context",
|
|
82
|
+
records_as: "vault_context",
|
|
83
|
+
build_evidence: false,
|
|
84
|
+
captured_at: new Date().toISOString(),
|
|
85
|
+
active_note_path: file?.path || null,
|
|
86
|
+
selected_text: selectedText,
|
|
87
|
+
selected_text_char_count: selectedText.length,
|
|
88
|
+
cursor: editor?.getCursor?.() || null,
|
|
89
|
+
pane_state: leaf?.getViewState?.() || null,
|
|
90
|
+
metadata: file ? this.app.metadataCache.getFileCache(file) || {} : {},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async captureActiveNote() {
|
|
95
|
+
const context = this.createSelectionContext();
|
|
96
|
+
const file = this.app.workspace.getActiveFile();
|
|
97
|
+
if (file) {
|
|
98
|
+
await this.app.fileManager.processFrontMatter(file, (frontmatter) => {
|
|
99
|
+
frontmatter.ma_records_as = "vault_context";
|
|
100
|
+
frontmatter.ma_project = this.settings.projectName;
|
|
101
|
+
frontmatter.ma_capabilities = [
|
|
102
|
+
"obsidian_integration_core",
|
|
103
|
+
"active_note_selection_context",
|
|
104
|
+
"metadata_cache_deep_graph",
|
|
105
|
+
];
|
|
106
|
+
if (this.settings.sourceWorkspace) {
|
|
107
|
+
frontmatter.ma_source_workspace = this.settings.sourceWorkspace;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
await this.writeVaultContextNote(
|
|
112
|
+
this.settings.activeContextPath,
|
|
113
|
+
this.renderContextNote(context),
|
|
114
|
+
true,
|
|
115
|
+
);
|
|
116
|
+
await this.writeBinaryAttachment(
|
|
117
|
+
`${this.settings.attachmentDir}/active-context-${Date.now()}.json`,
|
|
118
|
+
JSON.stringify(context, null, 2),
|
|
119
|
+
"application/json",
|
|
120
|
+
);
|
|
121
|
+
new Notice("MA captured current Obsidian context");
|
|
122
|
+
return context;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
renderContextNote(context) {
|
|
126
|
+
const activeLink = context.active_note_path
|
|
127
|
+
? this.app.fileManager.generateMarkdownLink(
|
|
128
|
+
this.app.vault.getAbstractFileByPath(context.active_note_path),
|
|
129
|
+
this.settings.activeContextPath,
|
|
130
|
+
undefined,
|
|
131
|
+
"active note",
|
|
132
|
+
)
|
|
133
|
+
: "none";
|
|
134
|
+
return withVaultContextFrontmatter(`# Active Note Context
|
|
135
|
+
|
|
136
|
+
- Active note: ${activeLink}
|
|
137
|
+
- Selection chars: ${context.selected_text_char_count}
|
|
138
|
+
- Cursor: ${JSON.stringify(context.cursor)}
|
|
139
|
+
- Captured: ${context.captured_at}
|
|
140
|
+
|
|
141
|
+
## Selected Text
|
|
142
|
+
|
|
143
|
+
${context.selected_text || "_No active selection captured._"}
|
|
144
|
+
|
|
145
|
+
## Obsidian MetadataCache
|
|
146
|
+
|
|
147
|
+
\`\`\`json
|
|
148
|
+
${JSON.stringify(context.metadata, null, 2)}
|
|
149
|
+
\`\`\`
|
|
150
|
+
|
|
151
|
+
## Pane State
|
|
152
|
+
|
|
153
|
+
\`\`\`json
|
|
154
|
+
${JSON.stringify(context.pane_state || {}, null, 2)}
|
|
155
|
+
\`\`\`
|
|
156
|
+
`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
registerProtocolHandler() {
|
|
160
|
+
this.registerObsidianProtocolHandler("ma", async (params) => {
|
|
161
|
+
if (params.action === "queue") {
|
|
162
|
+
await this.queueRequest(params);
|
|
163
|
+
new Notice("MA request queued");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (params.action === "capture" || params.open === "active") {
|
|
167
|
+
await this.captureActiveNote();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
await this.openNote(params.path || "Meta-Architect/Map of Content.md");
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
registerVaultWatchers() {
|
|
175
|
+
for (const eventName of ["create", "modify", "delete", "rename"]) {
|
|
176
|
+
this.registerEvent(
|
|
177
|
+
this.app.vault.on(eventName, () => {
|
|
178
|
+
this.drainRequestQueue().catch(() => {});
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
for (const eventName of ["resolved", "changed", "deleted"]) {
|
|
183
|
+
this.registerEvent(
|
|
184
|
+
this.app.metadataCache.on(eventName, () => {
|
|
185
|
+
this.drainRequestQueue().catch(() => {});
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
for (const eventName of ["active-leaf-change", "layout-change"]) {
|
|
190
|
+
this.registerEvent(
|
|
191
|
+
this.app.workspace.on(eventName, () => {
|
|
192
|
+
this.drainRequestQueue().catch(() => {});
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async queueRequest(params) {
|
|
199
|
+
await this.ensureFolder(this.pathParent(this.settings.queuePath));
|
|
200
|
+
const file = this.app.vault.getAbstractFileByPath(this.settings.queuePath);
|
|
201
|
+
const queue = file ? JSON.parse(await this.app.vault.read(file)) : [];
|
|
202
|
+
queue.push({
|
|
203
|
+
...params,
|
|
204
|
+
id: params.id || `ma-${Date.now()}`,
|
|
205
|
+
queued_at: new Date().toISOString(),
|
|
206
|
+
records_as: "vault_context",
|
|
207
|
+
});
|
|
208
|
+
const payload = `${JSON.stringify(queue, null, 2)}\n`;
|
|
209
|
+
if (file) await this.app.vault.modify(file, payload);
|
|
210
|
+
else await this.app.vault.create(this.settings.queuePath, payload);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async drainRequestQueue() {
|
|
214
|
+
const file = this.app.vault.getAbstractFileByPath(this.settings.queuePath);
|
|
215
|
+
const queue = file ? JSON.parse(await this.app.vault.read(file)) : [];
|
|
216
|
+
const processed = [];
|
|
217
|
+
const refused = [];
|
|
218
|
+
for (const request of queue) {
|
|
219
|
+
try {
|
|
220
|
+
const target = request.note_path || request.path || "";
|
|
221
|
+
if (target) assertSafeVaultPath(target);
|
|
222
|
+
if (request.action === "capture_active_note") {
|
|
223
|
+
processed.push(await this.captureActiveNote());
|
|
224
|
+
} else if (request.action === "create_note") {
|
|
225
|
+
processed.push(await this.writeVaultContextNote(target, request.content, true));
|
|
226
|
+
} else if (request.action === "rename_note") {
|
|
227
|
+
assertSafeVaultPath(request.to);
|
|
228
|
+
const fileToRename = this.app.vault.getAbstractFileByPath(request.from);
|
|
229
|
+
await this.app.fileManager.renameFile(fileToRename, request.to);
|
|
230
|
+
processed.push({ action: "rename_note", from: request.from, to: request.to });
|
|
231
|
+
} else if (request.action === "write_attachment") {
|
|
232
|
+
processed.push(
|
|
233
|
+
await this.writeBinaryAttachment(target, request.data || "", request.content_type),
|
|
234
|
+
);
|
|
235
|
+
} else {
|
|
236
|
+
throw new Error(`unsupported_action:${request.action}`);
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
refused.push({
|
|
240
|
+
action: request?.action || null,
|
|
241
|
+
reason: error.message,
|
|
242
|
+
records_as: "vault_context",
|
|
243
|
+
build_evidence: false,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (file && queue.length > 0) await this.app.vault.modify(file, "[]\n");
|
|
248
|
+
return {
|
|
249
|
+
record_type: "obsidian_plugin_queue_drain",
|
|
250
|
+
records_as: "vault_context",
|
|
251
|
+
build_evidence: false,
|
|
252
|
+
processed,
|
|
253
|
+
refused,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async writeVaultContextNote(notePath, content, overwrite) {
|
|
258
|
+
assertSafeVaultPath(notePath);
|
|
259
|
+
if (!content?.trim()) throw new Error("vault_context note content required");
|
|
260
|
+
await this.ensureFolder(this.pathParent(notePath));
|
|
261
|
+
const file = this.app.vault.getAbstractFileByPath(notePath);
|
|
262
|
+
const payload = withVaultContextFrontmatter(content);
|
|
263
|
+
if (file && overwrite) await this.app.vault.modify(file, payload);
|
|
264
|
+
else if (file) throw new Error(`note_exists:${notePath}`);
|
|
265
|
+
else await this.app.vault.create(notePath, payload);
|
|
266
|
+
return {
|
|
267
|
+
action: "write_vault_context_note",
|
|
268
|
+
note_path: notePath,
|
|
269
|
+
records_as: "vault_context",
|
|
270
|
+
build_evidence: false,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async writeBinaryAttachment(attachmentPath, data, contentType) {
|
|
275
|
+
assertSafeVaultPath(attachmentPath);
|
|
276
|
+
await this.ensureFolder(this.pathParent(attachmentPath));
|
|
277
|
+
const bytes = new TextEncoder().encode(String(data || ""));
|
|
278
|
+
if (this.app.vault.createBinary) {
|
|
279
|
+
await this.app.vault.createBinary(attachmentPath, bytes.buffer);
|
|
280
|
+
} else {
|
|
281
|
+
await this.app.vault.adapter.writeBinary(attachmentPath, bytes.buffer);
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
action: "write_attachment",
|
|
285
|
+
attachment_path: attachmentPath,
|
|
286
|
+
content_type: contentType || "application/octet-stream",
|
|
287
|
+
records_as: "vault_context",
|
|
288
|
+
build_evidence: false,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async openNote(notePath) {
|
|
293
|
+
const file = this.app.vault.getAbstractFileByPath(notePath);
|
|
294
|
+
if (!file) {
|
|
295
|
+
new Notice(`MA note not found: ${notePath}`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
await this.app.workspace.getLeaf(true).openFile(file);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async ensureFolder(folderPath) {
|
|
302
|
+
if (!folderPath || folderPath === ".") return;
|
|
303
|
+
const segments = folderPath.split("/").filter(Boolean);
|
|
304
|
+
let current = "";
|
|
305
|
+
for (const segment of segments) {
|
|
306
|
+
current = current ? `${current}/${segment}` : segment;
|
|
307
|
+
if (!this.app.vault.getAbstractFileByPath(current)) {
|
|
308
|
+
await this.app.vault.createFolder(current).catch(() => {});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
pathParent(filePath) {
|
|
314
|
+
const parts = filePath.split("/");
|
|
315
|
+
parts.pop();
|
|
316
|
+
return parts.join("/");
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
class ContextPreviewModal extends Modal {
|
|
321
|
+
constructor(app, context) {
|
|
322
|
+
super(app);
|
|
323
|
+
this.context = context;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
onOpen() {
|
|
327
|
+
this.contentEl.addClass("ma-context-modal");
|
|
328
|
+
this.contentEl.createEl("h2", { text: "Meta-Architect Context Preview" });
|
|
329
|
+
this.contentEl.createEl("pre", { text: JSON.stringify(this.context, null, 2) });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
onClose() {
|
|
333
|
+
this.contentEl.empty();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
class MetaArchitectSettingTab extends PluginSettingTab {
|
|
338
|
+
constructor(app, plugin) {
|
|
339
|
+
super(app, plugin);
|
|
340
|
+
this.plugin = plugin;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
display() {
|
|
344
|
+
const { containerEl } = this;
|
|
345
|
+
containerEl.empty();
|
|
346
|
+
containerEl.createEl("h2", { text: "Meta-Architect" });
|
|
347
|
+
|
|
348
|
+
new Setting(containerEl)
|
|
349
|
+
.setName("Project name")
|
|
350
|
+
.setDesc("Stored in MA frontmatter as ma_project.")
|
|
351
|
+
.addText((text) =>
|
|
352
|
+
text.setValue(this.plugin.settings.projectName).onChange(async (value) => {
|
|
353
|
+
this.plugin.settings.projectName = value || "Meta-Architect";
|
|
354
|
+
await this.plugin.saveSettings();
|
|
355
|
+
}),
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
new Setting(containerEl)
|
|
359
|
+
.setName("Active context note")
|
|
360
|
+
.setDesc("Where captured note/selection context is written.")
|
|
361
|
+
.addText((text) =>
|
|
362
|
+
text.setValue(this.plugin.settings.activeContextPath).onChange(async (value) => {
|
|
363
|
+
this.plugin.settings.activeContextPath = value || DEFAULT_SETTINGS.activeContextPath;
|
|
364
|
+
await this.plugin.saveSettings();
|
|
365
|
+
}),
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function withVaultContextFrontmatter(content) {
|
|
371
|
+
if (content.trimStart().startsWith("---")) {
|
|
372
|
+
return content;
|
|
373
|
+
}
|
|
374
|
+
return `---
|
|
375
|
+
ma_records_as: vault_context
|
|
376
|
+
ma_project: Meta-Architect
|
|
377
|
+
ma_capabilities:
|
|
378
|
+
- obsidian_integration_core
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
${content}`;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function assertSafeVaultPath(targetPath) {
|
|
385
|
+
const normalized = String(targetPath || "")
|
|
386
|
+
.replaceAll("\\", "/")
|
|
387
|
+
.replace(/^\/+/, "");
|
|
388
|
+
if (
|
|
389
|
+
!normalized ||
|
|
390
|
+
normalized === ".." ||
|
|
391
|
+
normalized.startsWith("../") ||
|
|
392
|
+
normalized.includes("/../")
|
|
393
|
+
) {
|
|
394
|
+
throw new Error("path_traversal_forbidden");
|
|
395
|
+
}
|
|
396
|
+
for (const forbidden of FORBIDDEN_TARGETS) {
|
|
397
|
+
if (normalized === forbidden || normalized.startsWith(forbidden)) {
|
|
398
|
+
throw new Error(`forbidden_authoritative_mutation:${forbidden}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "meta-architect",
|
|
3
|
+
"name": "Meta-Architect",
|
|
4
|
+
"version": "0.1.13",
|
|
5
|
+
"minAppVersion": "1.5.0",
|
|
6
|
+
"description": "Connects active Obsidian notes, selections, graph metadata, canvases, attachments, and request queues to Meta-Architect vault context.",
|
|
7
|
+
"author": "JustineDevs",
|
|
8
|
+
"isDesktopOnly": false
|
|
9
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: align
|
|
3
|
+
description: "Use when the user needs scope alignment, shared language, or docs clarity before or between gated lanes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Align
|
|
7
|
+
|
|
8
|
+
Use this skill inside Codex when the problem is ambiguity, drift, or mismatched language rather than missing implementation. `align` is a non-gating helper skill.
|
|
9
|
+
|
|
10
|
+
## Output
|
|
11
|
+
|
|
12
|
+
Produce:
|
|
13
|
+
- current ambiguity or mismatch
|
|
14
|
+
- normalized terminology
|
|
15
|
+
- scope boundary and exclusions
|
|
16
|
+
- acceptance checks or rewritten prompts
|
|
17
|
+
- exact next trigger, usually `$maestro` or the lane that owns the next decision
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
- Align language and scope without creating a new release gate.
|
|
22
|
+
- Prefer tightening existing artifacts over inventing parallel docs.
|
|
23
|
+
- Keep terminology Meta-Architect-native for user-facing surfaces.
|
|
24
|
+
- Use `references/shared-language.md` for naming, taxonomy, and docs-clarity patterns.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Shared Language
|
|
2
|
+
|
|
3
|
+
Use this reference pack with `align` when terminology, scope, or docs are drifting.
|
|
4
|
+
|
|
5
|
+
## Naming rules
|
|
6
|
+
|
|
7
|
+
- `$maestro` is the only umbrella surface.
|
|
8
|
+
- `$arch -> $sage -> $flow -> $vet -> $vibe -> $build` remains the fixed gated sequence.
|
|
9
|
+
- `align`, `diagnose`, `tdd`, and `cleanup` are helper skills only.
|
|
10
|
+
- User-facing guidance stays Meta-Architect-native; external source names may appear as evidence, not as product surfaces.
|
|
11
|
+
|
|
12
|
+
## Alignment checklist
|
|
13
|
+
|
|
14
|
+
- Name the current artifact, lane, and decision owner.
|
|
15
|
+
- Replace vague nouns with one stable term.
|
|
16
|
+
- Separate what is in scope, out of scope, and not yet decided.
|
|
17
|
+
- Rewrite prompts or docs so the next trigger is obvious.
|
|
18
|
+
|
|
19
|
+
## Docs-clarity patterns
|
|
20
|
+
|
|
21
|
+
- Put the next trigger in one line.
|
|
22
|
+
- Distinguish terminal helper commands from in-session skills.
|
|
23
|
+
- Distinguish gated lanes from helper skills.
|
|
24
|
+
- Prefer concise, high-signal wording over long catalogs or branding-heavy lists.
|
|
@@ -11,9 +11,11 @@ Use this skill inside Codex to turn a product idea into a concrete architecture
|
|
|
11
11
|
|
|
12
12
|
Produce:
|
|
13
13
|
- problem framing
|
|
14
|
+
- `decision`, `status`, `evidence`, `blockers`, `next_allowed_triggers`
|
|
14
15
|
- user and workload assumptions
|
|
15
16
|
- system architecture and subsystem boundaries
|
|
16
17
|
- stack recommendation with tradeoffs
|
|
18
|
+
- rejected alternatives with rationale
|
|
17
19
|
- data model and storage choices
|
|
18
20
|
- auth, security, and operational concerns
|
|
19
21
|
- phased delivery plan
|
|
@@ -14,11 +14,14 @@ Produce:
|
|
|
14
14
|
- blockers that still prevent implementation
|
|
15
15
|
- the narrowest viable build slice
|
|
16
16
|
- branch or worktree suggestions when relevant
|
|
17
|
+
- bounded execution state when the build lane is already in progress
|
|
17
18
|
- test and verification expectations
|
|
19
|
+
- repair path when the bounded slice needs another pass
|
|
18
20
|
- the exact next implementation step
|
|
19
21
|
|
|
20
22
|
## Rules
|
|
21
23
|
|
|
22
24
|
- Do not claim readiness if architecture, evidence, logic, security, or DX/UX gaps remain unresolved.
|
|
23
25
|
- Keep the recommended build slice small, testable, and reversible.
|
|
26
|
+
- Treat `$build` as the sole owner of `.ma/plans/build.md` and `build_status`.
|
|
24
27
|
- If the user wants code immediately and the path is clear, end with a concrete implementation plan rather than more review prose.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cleanup
|
|
3
|
+
description: "Use when the user wants contract-preserving simplification, anti-slop cleanup, or a final-pass polish after the main decision is made."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cleanup
|
|
7
|
+
|
|
8
|
+
Use this skill inside Codex when the core behavior is understood but the artifact still needs simplification, deslop work, or clearer prose. `cleanup` is a non-gating helper skill.
|
|
9
|
+
|
|
10
|
+
## Output
|
|
11
|
+
|
|
12
|
+
Produce:
|
|
13
|
+
- removable complexity or noisy wording
|
|
14
|
+
- behavior-preserving simplifications
|
|
15
|
+
- residual risks after cleanup
|
|
16
|
+
- exact next trigger, usually the owning lane or release verification
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
|
|
20
|
+
- Prefer deletion over addition.
|
|
21
|
+
- Preserve behavior and decision ownership while cleaning up.
|
|
22
|
+
- Keep user-facing wording concise and product-native.
|
|
23
|
+
- Use `references/style-and-deslop.md` for simplification and prose cleanup patterns.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Style And Deslop
|
|
2
|
+
|
|
3
|
+
Use this reference pack with `cleanup` when an artifact works but still feels bloated, generic, or hard to trust.
|
|
4
|
+
|
|
5
|
+
## Cleanup priorities
|
|
6
|
+
|
|
7
|
+
- remove repeated framing
|
|
8
|
+
- cut placeholder language and empty intensifiers
|
|
9
|
+
- collapse duplicate concepts into one stable term
|
|
10
|
+
- prefer shorter, sharper instructions when they preserve meaning
|
|
11
|
+
- delete unused or non-essential surface area before adding more structure
|
|
12
|
+
|
|
13
|
+
## Safe cleanup checks
|
|
14
|
+
|
|
15
|
+
- behavior or contract is unchanged
|
|
16
|
+
- the next trigger is still explicit
|
|
17
|
+
- helper-vs-gated distinctions remain intact
|
|
18
|
+
- no upstream brand names are introduced as product surfaces
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: diagnose
|
|
3
|
+
description: "Use when the user needs failure triage, blocked-lane diagnosis, or root-cause decomposition before the next gate can move."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Diagnose
|
|
7
|
+
|
|
8
|
+
Use this skill inside Codex when a lane is blocked, a symptom is vague, or the next useful move is to decompose the failure before editing code. `diagnose` is a non-gating helper skill.
|
|
9
|
+
|
|
10
|
+
## Output
|
|
11
|
+
|
|
12
|
+
Produce:
|
|
13
|
+
- observed symptom
|
|
14
|
+
- likely failure slices
|
|
15
|
+
- missing evidence or missing reproduction steps
|
|
16
|
+
- smallest next probe
|
|
17
|
+
- exact next trigger, usually the owning lane or `$maestro`
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
- Decompose the problem before proposing broad fixes.
|
|
22
|
+
- Prefer the smallest reproducible boundary that can confirm or kill a hypothesis.
|
|
23
|
+
- Keep release-state ownership with the gated lane that is blocked.
|
|
24
|
+
- Escalate assumptions clearly when evidence is still incomplete.
|
|
@@ -10,7 +10,9 @@ Use this skill inside Codex to pressure-test how the system behaves, not just ho
|
|
|
10
10
|
## Output
|
|
11
11
|
|
|
12
12
|
Produce:
|
|
13
|
+
- `decision`, `status`, `evidence`, `blockers`, `next_allowed_triggers`
|
|
13
14
|
- key actors and system states
|
|
15
|
+
- state map and failure flows
|
|
14
16
|
- main flows and failure flows
|
|
15
17
|
- invariants and state transitions
|
|
16
18
|
- race conditions, dead ends, and consistency risks
|
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maestro
|
|
3
|
-
description: "Use when the user wants Meta-Architect
|
|
3
|
+
description: "Use when the user wants the singular Meta-Architect in-session autonomous manager: choose the best next workflow step, manage the fixed gated workflow, and route bounded helper handoffs inside Codex."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Maestro
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Use this skill inside Codex as the singular Meta-Architect umbrella surface and bounded autonomous manager. It inspects workflow state, chooses the smallest safe next step, manages the fixed gated design-and-review sequence one lane at a time, and routes helper handoffs when they are enough. There is no separate shipped `$meta-architect` skill.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
1. Inspect the current gate state, active evidence, and current blockers.
|
|
15
|
+
2. Choose the smallest safe next step and decide whether the next move is:
|
|
16
|
+
- a direct advisory result
|
|
17
|
+
- a helper-skill handoff
|
|
18
|
+
- a gated-lane handoff
|
|
19
|
+
3. When the issue is alignment, diagnosis, regression-first execution, or final-pass cleanup, hand work to the publishable but non-gating helper skills:
|
|
20
|
+
- `$align`
|
|
21
|
+
- `$diagnose`
|
|
22
|
+
- `$tdd`
|
|
23
|
+
- `$cleanup`
|
|
24
|
+
4. When the user wants the full Meta-Architect workflow, manage the fixed gated sequence without inventing new gates or skipping lane ownership:
|
|
25
|
+
- `$arch`
|
|
26
|
+
- `$sage`
|
|
27
|
+
- `$flow`
|
|
28
|
+
- `$vet`
|
|
29
|
+
- `$vibe`
|
|
30
|
+
- `$build`
|
|
31
|
+
5. End with a clear result shape: decision, evidence, blockers, the lane assignment if any, and the exact next trigger.
|
|
9
32
|
|
|
10
33
|
## Output
|
|
11
34
|
|
|
@@ -22,4 +45,14 @@ Produce:
|
|
|
22
45
|
- Prefer the smallest next step that moves the workflow forward safely.
|
|
23
46
|
- Respect current gate state before recommending implementation or release work.
|
|
24
47
|
- Be explicit when more evidence, planning, or validation is still needed.
|
|
25
|
-
-
|
|
48
|
+
- Treat the in-session skill flow as primary. Use `ma ...` terminal helpers only when repo-local setup, inspection, or scripted state automation is explicitly the better support path.
|
|
49
|
+
- Keep `$maestro` as the only umbrella surface. It owns next-step management and bounded handoff decisions, but it does not replace the outputs owned by the gated lanes.
|
|
50
|
+
- Helper skills are publishable mirrors, but they are non-gating. They support a lane and then hand control back to `$maestro` or the fixed gated sequence.
|
|
51
|
+
- Do not expand the release-gated sequence for this release. Gate ownership stays with `$arch -> $sage -> $flow -> $vet -> $vibe -> $build`.
|
|
52
|
+
- Stay inside Codex unless the user explicitly asks for repo-local helper commands.
|
|
53
|
+
- Keep the workflow architecture-first. Do not jump into code before the architecture and review lanes are grounded.
|
|
54
|
+
- Use approved discovery accelerators such as Ossium, Trendshift, Dev Hunt, Libraries.io, Open Hub, and Open-source Projects when you need faster OSS candidate discovery, then validate any promising project through upstream repos and official docs.
|
|
55
|
+
- Keep the `$sage` order explicit: known upstream sources first, discovery accelerators second, exact repo mapping third, approval only after upstream verification.
|
|
56
|
+
- Prefer official docs, upstream repos, and repo-configured GitMCP sources when validating tooling choices.
|
|
57
|
+
- For release gates and branch policy, read `references/core-release-rules.md`.
|
|
58
|
+
- For the native helper-family contract and pattern classification, read `references/native-ingest-map.md`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "$maestro"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use $maestro
|
|
3
|
+
short_description: "Bounded autonomous manager for the gated workflow and helper handoffs"
|
|
4
|
+
default_prompt: "Use $maestro as the singular Meta-Architect in-session autonomous manager: inspect workflow state, choose the smallest safe next step, hand work to $align, $diagnose, $tdd, or $cleanup when a publishable non-gating helper is enough, and manage the fixed gated sequence at $arch, $sage, $flow, $vet, $vibe, and $build without inventing new gates."
|