@maestria/prime-agent 0.3.1 → 0.3.3
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/README.md +1 -1
- package/dist/extension.mjs +3 -3
- package/dist/extension.mjs.map +1 -1
- package/package.json +2 -2
- package/skills/adventurer/SKILL.md +1 -1
- package/skills/architect/SKILL.md +1 -1
- package/skills/blitz/SKILL.md +1 -1
- package/skills/builder/SKILL.md +1 -1
- package/skills/diagnose/SKILL.md +2 -2
- package/skills/fein/SKILL.md +1 -1
- package/skills/global-rules/SKILL.md +11 -10
- package/skills/handoff/SKILL.md +1 -1
- package/skills/iteration-limits/SKILL.md +1 -1
- package/skills/orchestrator/SKILL.md +2 -2
- package/skills/planner/SKILL.md +1 -1
- package/skills/reviewer/SKILL.md +4 -4
- package/skills/sonar/SKILL.md +1 -1
- package/skills/writer/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ For skills-only installs, point Prime at the package's `skills/` directory in se
|
|
|
29
29
|
- **Verified subset only:** the extension covers mode commands and mode prompt injection. There is no recursive-subagent dispatch - "delegate to a specialist" loads the relevant skill and applies its methodology. JSON/RPC headless-mode integration is deferred.
|
|
30
30
|
- **Advisory, not enforced:** skills, rules, and role prompts are guidance, not security enforcement. Prime has no skill-level tool-denial mechanism, so read-only roles state their role intent without claiming a runtime boundary.
|
|
31
31
|
- **Not a sandbox:** Prime executes model-generated Python and project commands with your user permissions. Restrict use to trusted repositories, skills, and instructions.
|
|
32
|
-
- **
|
|
32
|
+
- **Extension has no filesystem writes:** the compiled extension does not write to `~/.pi` or `.prime/agent`; Prime's package manager still manages its own registration files.
|
|
33
33
|
- **No extra dependencies:** the extension uses only the Prime-bundled API; no pi package dependency is required.
|
|
34
34
|
|
|
35
35
|
## Documentation and Changelog
|
package/dist/extension.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)}}
|
|
3
|
-
`);n.ui.setEditorText(r)}})}
|
|
1
|
+
import e from"node:path";import{readFileSync as t}from"node:fs";const n=()=>({mode:null}),r=e=>e.type===`custom`&&`customType`in e&&e.customType===`maestria_mode`,i=e=>{if(typeof e!=`object`||!e||!(`mode`in e))return!1;let{mode:t}=e;return t===null||t===`fein`||t===`sonar`||t===`blitz`},a=e=>{if(!Array.isArray(e))return null;for(let t=e.length-1;t>=0;--t){let n=e[t];if(r(n)&&i(n.data))return n.data}return null},o=(e,t)=>{e.appendEntry(`maestria_mode`,{mode:t.mode})},s=(e,t)=>{e.mode=a(t)?.mode??null},c=[`fein`,`sonar`,`blitz`],l={blitz:`[MODE: blitz]`,fein:`[MODE: fein]`,sonar:`[MODE: sonar]`},u={blitz:`Set workflow mode to blitz (fast path)`,fein:`Set workflow mode to fein (full pipeline)`,sonar:`Set workflow mode to sonar (research only)`},d={},f=(n,r)=>{let i=d[n];if(i!==void 0)return i;let a=``;try{let i=t(e.join(r,n,`SKILL.md`),`utf-8`),o=i.indexOf(`## MODE:`);if(o===-1)console.warn(`[maestria] prime-agent: mode skill "${n}" has no "## MODE:" heading; mode prompt injection disabled for this mode.`);else{let e=i.slice(o);a=`${l[n]}\n\n${e.replace(/\s+$/u,``)}\n`}}catch(e){console.warn(`[maestria] prime-agent: failed to load mode skill "${n}" from ${r}; mode prompt injection disabled for this mode.`,e)}return d[n]=a,a},p=(e,t)=>n=>{if(!e.mode)return;let r=f(e.mode,t);if(r)return{systemPrompt:[n.systemPrompt,``,r,``,`The user has set workflow mode to "${e.mode}". Honor this mode throughout the session until it is changed or cleared.`].join(`
|
|
2
|
+
`)}},m=(e,t)=>{for(let n of c)e.registerCommand(n,{description:u[n],handler:async(r,i)=>{t.mode=n,o(e,t),r.trim()?e.sendUserMessage(r.trim(),{deliverAs:`steer`}):i.ui.notify(`Mode set to ${n}. Describe what you'd like to work on.`),await Promise.resolve()}});e.registerCommand(`mode-clear`,{description:`Clear workflow mode and return to neutral routing`,handler:async(n,r)=>{t.mode=null,o(e,t),r.ui.notify(`Workflow mode cleared. Neutral routing is active.`),await Promise.resolve()}}),e.registerCommand(`maestria-status`,{description:`Show the current maestria workflow mode and extension subset`,handler:async(e,n)=>{let r=[`# Maestria status (prime-agent)`,``,`Workflow mode: ${t.mode??`none`}`,``,`Commands: /fein, /sonar, /blitz, /mode-clear`,``,`This extension covers mode selection and mode prompt injection only.`,`Recursive-subagent (rlm) dispatch and JSON/RPC headless mode are NOT provided by this package.`].join(`
|
|
3
|
+
`);n.ui.setEditorText(r),await Promise.resolve()}})},h=()=>{let t=import.meta.dirname;return e.resolve(t,`../skills`)},g=e=>{let t=n(),r=h();m(e,t),e.on(`before_agent_start`,p(t,r)),e.on(`session_start`,(e,n)=>{s(t,n.sessionManager.getBranch())}),e.on(`session_tree`,(e,n)=>{s(t,n.sessionManager.getBranch())})};export{g as default};
|
|
4
4
|
//# sourceMappingURL=extension.mjs.map
|
package/dist/extension.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.mjs","names":[],"sources":["../src/state.ts","../src/modes.ts","../src/extension.ts"],"sourcesContent":["// packages/prime-agent/src/state.ts\n// Minimal session-scoped state for the Prime extension: the active workflow\n// mode (fein/sonar/blitz) or none.\n//\n// State is persisted through the host session API (`pi.appendEntry`) as a\n// `custom` session entry with `customType: \"maestria_mode\"`. Custom entries\n// are session entries: they survive reloads, forks, and compaction, and they\n// are NOT part of LLM context. Restore reads only the current branch\n// (`sessionManager.getBranch()`), never a sibling branch of the session tree,\n// mirroring the @maestria/pi extension's state pattern. No files are written\n// (no `~/.pi`, no `.prime/agent` writes); everything rides on the host session.\n\nimport type { CustomEntry, ExtensionAPI, SessionEntry } from './pi-api.js';\n\n/** Session entry type used to persist the active mode. */\nexport const MODE_STATE_CUSTOM_TYPE = 'maestria_mode';\n\nexport interface MaestriaModeState {\n /** Active workflow mode, or null when neutral routing is active. */\n mode: 'fein' | 'sonar' | 'blitz' | null;\n}\n\nexport function createInitialState(): MaestriaModeState {\n return { mode: null };\n}\n\nfunction isCustomEntry(entry: SessionEntry): entry is CustomEntry & { data?: MaestriaModeState } {\n // SessionEntryBase.type is a plain string, so a discriminated-union narrowing\n // on `type` does not apply; cast to read the optional customType.\n const maybe = entry as SessionEntry & { customType?: string };\n return maybe.type === 'custom' && maybe.customType === MODE_STATE_CUSTOM_TYPE;\n}\n\nfunction isModeState(value: unknown): value is MaestriaModeState {\n if (typeof value !== 'object' || value === null) return false;\n const mode = (value as Record<string, unknown>).mode;\n return mode === null || mode === 'fein' || mode === 'sonar' || mode === 'blitz';\n}\n\n/**\n * Read the mode state from the current session branch: the most recent\n * `maestria_mode` custom entry wins. Returns null when no entry exists.\n */\nexport function readModeStateFromEntries(\n entries: SessionEntry[] | null | undefined,\n): MaestriaModeState | null {\n if (!Array.isArray(entries)) return null;\n // Entries are returned in tree order; the last matching entry is the most\n // recently appended one on the current branch.\n for (let i = entries.length - 1; i >= 0; i--) {\n const entry = entries[i];\n if (isCustomEntry(entry) && isModeState(entry.data)) return entry.data;\n }\n return null;\n}\n\n/** Persist the current mode as a session custom entry (no LLM context). */\nexport function persistModeState(pi: ExtensionAPI, state: MaestriaModeState): void {\n pi.appendEntry(MODE_STATE_CUSTOM_TYPE, { mode: state.mode });\n}\n\n/**\n * Restore the mode state from the current session branch into `state`.\n * When the branch has no `maestria_mode` entry, mode resets to null\n * (fail-closed: never inherit a sibling branch's mode).\n */\nexport function restoreModeState(\n state: MaestriaModeState,\n entries: SessionEntry[] | null | undefined,\n): void {\n const persisted = readModeStateFromEntries(entries);\n state.mode = persisted?.mode ?? null;\n}\n","// packages/prime-agent/src/modes.ts\n// Prime-local implementation of the Maestria workflow modes (fein/sonar/blitz).\n//\n// Behavioral model: the @maestria/pi extension's mode implementation\n// (packages/pi/src/modes.ts + packages/shared/pi/src/modes-core.ts), adapted to\n// the Prime fork's public extension API and to this package's skills-first\n// projection. This module is deliberately self-contained (Prime-local thin\n// extension): it does not import @maestria/pi or @maestria/shared-pi, and it\n// uses only the public ExtensionAPI surface mirrored in ./pi-api.ts.\n//\n// Mode content is NOT duplicated here: it is loaded from the package's\n// generated skills (`skills/<mode>/SKILL.md`, the `## MODE:` section onward),\n// so the extension's injected prompt is exactly the sync-projected mode skill\n// (canonical content lives in packages/core/agent-directives/, ADR-CORE-005).\n\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type {\n BeforeAgentStartEvent,\n BeforeAgentStartEventResult,\n ExtensionAPI,\n ExtensionCommandContext,\n ExtensionContext,\n} from './pi-api.js';\nimport type { MaestriaModeState } from './state.js';\nimport { persistModeState } from './state.js';\n\nexport const MODE_KEYWORDS = ['fein', 'sonar', 'blitz'] as const;\nexport type ModeKeyword = (typeof MODE_KEYWORDS)[number];\n\n/** Marker line prepended to injected mode content (shared with other Maestria platforms). */\nexport const MODE_MARKERS: Record<ModeKeyword, string> = {\n fein: '[MODE: fein]',\n sonar: '[MODE: sonar]',\n blitz: '[MODE: blitz]',\n};\n\nconst MODE_COMMAND_DESCRIPTIONS: Record<ModeKeyword, string> = {\n fein: 'Set workflow mode to fein (full pipeline)',\n sonar: 'Set workflow mode to sonar (research only)',\n blitz: 'Set workflow mode to blitz (fast path)',\n};\n\n// ---------------------------------------------------------------------------\n// Mode prompt loading (from generated skills)\n// ---------------------------------------------------------------------------\n\nconst _promptCache: Partial<Record<ModeKeyword, string>> = {};\n\n/**\n * Load the mode prompt for a keyword from the package's generated skills\n * directory: `skills/<mode>/SKILL.md`, sliced from the `## MODE:` heading\n * onward, prefixed with the `[MODE: <mode>]` marker. Returns an empty string\n * (and warns) when the skill file is missing or has no mode section, so a\n * packaging mistake degrades to \"no injection\" rather than an extension crash.\n */\nexport function getModePrompt(keyword: ModeKeyword, skillsDir: string): string {\n if (keyword in _promptCache) return _promptCache[keyword]!;\n\n let prompt = '';\n try {\n const content = readFileSync(join(skillsDir, keyword, 'SKILL.md'), 'utf8');\n const modeIdx = content.indexOf('## MODE:');\n if (modeIdx === -1) {\n // A generated skill without the mode section must not leak the whole\n // SKILL.md into the system prompt: degrade to \"no injection\" instead.\n console.warn(\n `[maestria] prime-agent: mode skill \"${keyword}\" has no \"## MODE:\" heading; ` +\n `mode prompt injection disabled for this mode.`,\n );\n } else {\n const body = content.slice(modeIdx);\n prompt = `${MODE_MARKERS[keyword]}\\n\\n${body.replace(/\\s+$/, '')}\\n`;\n }\n } catch (error) {\n console.warn(\n `[maestria] prime-agent: failed to load mode skill \"${keyword}\" from ${skillsDir}; ` +\n `mode prompt injection disabled for this mode.`,\n error,\n );\n }\n _promptCache[keyword] = prompt;\n return prompt;\n}\n\n// ---------------------------------------------------------------------------\n// before_agent_start mode prompt injection\n// ---------------------------------------------------------------------------\n\n/**\n * Create the `before_agent_start` handler that appends the active mode prompt\n * to the chained system prompt. Returns void when no mode is active (no\n * modification), so Prime's normal prompt assembly stands as-is.\n */\nexport function createModePromptHandler(\n state: MaestriaModeState,\n skillsDir: string,\n): (event: BeforeAgentStartEvent, _ctx: ExtensionContext) => BeforeAgentStartEventResult | void {\n return (event: BeforeAgentStartEvent): BeforeAgentStartEventResult | void => {\n if (!state.mode) return;\n\n const modePrompt = getModePrompt(state.mode, skillsDir);\n if (!modePrompt) return;\n\n return {\n systemPrompt: [\n event.systemPrompt,\n '',\n modePrompt,\n '',\n `The user has set workflow mode to \"${state.mode}\". Honor this mode throughout the session until it is changed or cleared.`,\n ].join('\\n'),\n };\n };\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const MODE_CLEAR_COMMAND = 'mode-clear';\nexport const STATUS_COMMAND = 'maestria-status';\n\n/**\n * Install the mode slash commands (`/fein`, `/sonar`, `/blitz`, `/mode-clear`)\n * and the status/help command (`/maestria-status`). Mode selection is persisted\n * as a session custom entry; the prompt is injected on the next agent turn by\n * the `before_agent_start` handler.\n */\nexport function installCommands(pi: ExtensionAPI, state: MaestriaModeState): void {\n for (const keyword of MODE_KEYWORDS) {\n pi.registerCommand(keyword, {\n description: MODE_COMMAND_DESCRIPTIONS[keyword],\n handler: async (args: string, ctx: ExtensionCommandContext) => {\n state.mode = keyword;\n persistModeState(pi, state);\n // Forward a goal argument (e.g. `/fein implement the pipeline`) so the\n // injected mode prompt's \"if the user provided a goal, run it now\"\n // instruction has the goal to act on.\n if (args.trim()) {\n pi.sendUserMessage(args.trim(), { deliverAs: 'steer' });\n } else {\n ctx.ui.notify(`Mode set to ${keyword}. Describe what you'd like to work on.`);\n }\n },\n });\n }\n\n pi.registerCommand(MODE_CLEAR_COMMAND, {\n description: 'Clear workflow mode and return to neutral routing',\n handler: async (_args: string, ctx: ExtensionCommandContext) => {\n state.mode = null;\n persistModeState(pi, state);\n ctx.ui.notify('Workflow mode cleared. Neutral routing is active.');\n },\n });\n\n pi.registerCommand(STATUS_COMMAND, {\n description: 'Show the current maestria workflow mode and extension subset',\n handler: async (_args: string, ctx: ExtensionCommandContext) => {\n const mode = state.mode ?? 'none';\n const summary = [\n '# Maestria status (prime-agent)',\n '',\n `Workflow mode: ${mode}`,\n '',\n 'Commands: /fein, /sonar, /blitz, /mode-clear',\n '',\n 'This extension covers mode selection and mode prompt injection only.',\n 'Recursive-subagent (rlm) dispatch and JSON/RPC headless mode are NOT provided by this package.',\n ].join('\\n');\n ctx.ui.setEditorText(summary);\n },\n });\n}\n","// packages/prime-agent/src/extension.ts\n// Prime Agent extension entry point (default-export factory).\n//\n// Compiled to `dist/extension.mjs` and declared in package.json under\n// `pi.extensions`; Prime loads it with its extension loader (pinned fork\n// 7787f07415d843b9a800f6a4720e0c739bd608e5, loader.ts: a jiti import of the\n// declared path calling the default export with the live ExtensionAPI).\n//\n// Verified subset (public Prime/Pi extension API only, see src/pi-api.ts):\n// - slash commands /fein /sonar /blitz /mode-clear and /maestria-status\n// - before_agent_start mode prompt injection (systemPrompt chaining)\n// - session-scoped mode state via custom session entries, restored on\n// session_start (reload/resume/fork) and session_tree (branch navigation)\n//\n// NOT provided (explicitly deferred, documented in README/INSTALL/ADR-CORE-014):\n// native recursive-subagent (`rlm`) dispatch - the pinned fork exposes no\n// public JS extension bridge for it (it is an IPython-side tool) - and\n// JSON/RPC headless mode integration. No tool interception is installed and no\n// sandbox/enforcement claim is made. This extension writes no files (no\n// `~/.pi`, no `.prime/agent` writes): state rides on host session entries.\n\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ExtensionAPI } from './pi-api.js';\nimport { createInitialState, restoreModeState } from './state.js';\nimport { createModePromptHandler, installCommands } from './modes.js';\n\n/**\n * Resolve the package's generated `skills/` directory. When running from the\n * built `dist/extension.mjs`, this is `<packageRoot>/skills`; when running from\n * source (tests), it is the same package-relative location.\n */\nfunction resolveSkillsDir(): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n return resolve(moduleDir, '../skills');\n}\n\nexport default function (pi: ExtensionAPI): void {\n const state = createInitialState();\n const skillsDir = resolveSkillsDir();\n\n // Mode commands + status command (session-scoped state, persisted via\n // pi.appendEntry custom entries).\n installCommands(pi, state);\n\n // Mode prompt injection on the next agent turn.\n pi.on('before_agent_start', createModePromptHandler(state, skillsDir));\n\n // Restore the active mode when a session starts, is reloaded, resumed, or\n // forked, and when navigating the session tree to a different branch.\n pi.on('session_start', (_event, ctx) => {\n restoreModeState(state, ctx.sessionManager.getBranch());\n });\n\n pi.on('session_tree', (_event, ctx) => {\n restoreModeState(state, ctx.sessionManager.getBranch());\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.mjs","names":[],"sources":["../src/state.ts","../src/modes.ts","../src/extension.ts"],"sourcesContent":["// packages/prime-agent/src/state.ts\n// Minimal session-scoped state for the Prime extension: the active workflow\n// mode (fein/sonar/blitz) or none.\n//\n// State is persisted through the host session API (`pi.appendEntry`) as a\n// `custom` session entry with `customType: \"maestria_mode\"`. Custom entries\n// are session entries: they survive reloads, forks, and compaction, and they\n// are NOT part of LLM context. Restore reads only the current branch\n// (`sessionManager.getBranch()`), never a sibling branch of the session tree,\n// mirroring the @maestria/pi extension's state pattern. No files are written\n// (no `~/.pi`, no `.prime/agent` writes); everything rides on the host session.\n\nimport type { CustomEntry, ExtensionAPI, SessionEntry } from './pi-api.js';\n\n/** Session entry type used to persist the active mode. */\nexport const MODE_STATE_CUSTOM_TYPE = 'maestria_mode';\n\nexport interface MaestriaModeState {\n /** Active workflow mode, or null when neutral routing is active. */\n mode: 'fein' | 'sonar' | 'blitz' | null;\n}\n\nexport const createInitialState = (): MaestriaModeState => ({ mode: null });\n\nconst isCustomEntry = (entry: SessionEntry): entry is CustomEntry =>\n entry.type === 'custom' && 'customType' in entry && entry.customType === MODE_STATE_CUSTOM_TYPE;\n\nconst isModeState = (value: unknown): value is MaestriaModeState => {\n if (typeof value !== 'object' || value === null || !('mode' in value)) {\n return false;\n }\n const { mode } = value;\n return mode === null || mode === 'fein' || mode === 'sonar' || mode === 'blitz';\n};\n\n/**\n * Read the mode state from the current session branch: the most recent\n * `maestria_mode` custom entry wins. Returns null when no entry exists.\n */\nexport const readModeStateFromEntries = (\n entries: SessionEntry[] | null | undefined,\n): MaestriaModeState | null => {\n if (!Array.isArray(entries)) {\n return null;\n }\n // Entries are returned in tree order; the last matching entry is the most\n // recently appended one on the current branch.\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const entry = entries[i];\n if (isCustomEntry(entry) && isModeState(entry.data)) {\n return entry.data;\n }\n }\n return null;\n};\n\n/** Persist the current mode as a session custom entry (no LLM context). */\nexport const persistModeState = (pi: ExtensionAPI, state: MaestriaModeState): void => {\n pi.appendEntry(MODE_STATE_CUSTOM_TYPE, { mode: state.mode });\n};\n\n/**\n * Restore the mode state from the current session branch into `state`.\n * When the branch has no `maestria_mode` entry, mode resets to null\n * (fail-closed: never inherit a sibling branch's mode).\n */\nexport const restoreModeState = (\n state: MaestriaModeState,\n entries: SessionEntry[] | null | undefined,\n): void => {\n const persisted = readModeStateFromEntries(entries);\n state.mode = persisted?.mode ?? null;\n};\n","// packages/prime-agent/src/modes.ts\n// Prime-local implementation of the Maestria workflow modes (fein/sonar/blitz).\n//\n// Behavioral model: the @maestria/pi extension's mode implementation\n// (packages/pi/src/modes.ts + packages/shared/pi/src/modes-core.ts), adapted to\n// the Prime fork's public extension API and to this package's skills-first\n// projection. This module is deliberately self-contained (Prime-local thin\n// extension): it does not import @maestria/pi or @maestria/shared-pi, and it\n// uses only the public ExtensionAPI surface mirrored in ./pi-api.ts.\n//\n// Mode content is NOT duplicated here: it is loaded from the package's\n// generated skills (`skills/<mode>/SKILL.md`, the `## MODE:` section onward),\n// so the extension's injected prompt is exactly the sync-projected mode skill\n// (canonical content lives in packages/core/agent-directives/, ADR-CORE-005).\n\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\n\nimport type {\n BeforeAgentStartEvent,\n BeforeAgentStartEventResult,\n ExtensionAPI,\n ExtensionCommandContext,\n ExtensionContext,\n} from './pi-api.js';\nimport type { MaestriaModeState } from './state.js';\nimport { persistModeState } from './state.js';\n\nexport const MODE_KEYWORDS = ['fein', 'sonar', 'blitz'] as const;\nexport type ModeKeyword = (typeof MODE_KEYWORDS)[number];\n\n/** Marker line prepended to injected mode content (shared with other Maestria platforms). */\nexport const MODE_MARKERS: Record<ModeKeyword, string> = {\n blitz: '[MODE: blitz]',\n fein: '[MODE: fein]',\n sonar: '[MODE: sonar]',\n};\n\nconst MODE_COMMAND_DESCRIPTIONS: Record<ModeKeyword, string> = {\n blitz: 'Set workflow mode to blitz (fast path)',\n fein: 'Set workflow mode to fein (full pipeline)',\n sonar: 'Set workflow mode to sonar (research only)',\n};\n\n// ---------------------------------------------------------------------------\n// Mode prompt loading (from generated skills)\n// ---------------------------------------------------------------------------\n\nconst _promptCache: Partial<Record<ModeKeyword, string>> = {};\n\n/**\n * Load the mode prompt for a keyword from the package's generated skills\n * directory: `skills/<mode>/SKILL.md`, sliced from the `## MODE:` heading\n * onward, prefixed with the `[MODE: <mode>]` marker. Returns an empty string\n * (and warns) when the skill file is missing or has no mode section, so a\n * packaging mistake degrades to \"no injection\" rather than an extension crash.\n */\nexport const getModePrompt = (keyword: ModeKeyword, skillsDir: string): string => {\n const cachedPrompt = _promptCache[keyword];\n if (cachedPrompt !== undefined) {\n return cachedPrompt;\n }\n\n let prompt = '';\n try {\n const content = readFileSync(path.join(skillsDir, keyword, 'SKILL.md'), 'utf-8');\n const modeIdx = content.indexOf('## MODE:');\n if (modeIdx === -1) {\n // A generated skill without the mode section must not leak the whole\n // SKILL.md into the system prompt: degrade to \"no injection\" instead.\n console.warn(\n `[maestria] prime-agent: mode skill \"${keyword}\" has no \"## MODE:\" heading; ` +\n `mode prompt injection disabled for this mode.`,\n );\n } else {\n const body = content.slice(modeIdx);\n prompt = `${MODE_MARKERS[keyword]}\\n\\n${body.replace(/\\s+$/u, '')}\\n`;\n }\n } catch (error) {\n console.warn(\n `[maestria] prime-agent: failed to load mode skill \"${keyword}\" from ${skillsDir}; ` +\n `mode prompt injection disabled for this mode.`,\n error,\n );\n }\n _promptCache[keyword] = prompt;\n return prompt;\n};\n\n// ---------------------------------------------------------------------------\n// before_agent_start mode prompt injection\n// ---------------------------------------------------------------------------\n\n/**\n * Create the `before_agent_start` handler that appends the active mode prompt\n * to the chained system prompt. Returns void when no mode is active (no\n * modification), so Prime's normal prompt assembly stands as-is.\n */\nexport const createModePromptHandler =\n (\n state: MaestriaModeState,\n skillsDir: string,\n ): ((\n event: BeforeAgentStartEvent,\n _ctx: ExtensionContext,\n ) => BeforeAgentStartEventResult | undefined) =>\n (event: BeforeAgentStartEvent): BeforeAgentStartEventResult | undefined => {\n if (!state.mode) {\n return undefined;\n }\n\n const modePrompt = getModePrompt(state.mode, skillsDir);\n if (!modePrompt) {\n return undefined;\n }\n\n return {\n systemPrompt: [\n event.systemPrompt,\n '',\n modePrompt,\n '',\n `The user has set workflow mode to \"${state.mode}\". Honor this mode throughout the session until it is changed or cleared.`,\n ].join('\\n'),\n };\n };\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const MODE_CLEAR_COMMAND = 'mode-clear';\nexport const STATUS_COMMAND = 'maestria-status';\n\n/**\n * Install the mode slash commands (`/fein`, `/sonar`, `/blitz`, `/mode-clear`)\n * and the status/help command (`/maestria-status`). Mode selection is persisted\n * as a session custom entry; the prompt is injected on the next agent turn by\n * the `before_agent_start` handler.\n */\nexport const installCommands = (pi: ExtensionAPI, state: MaestriaModeState): void => {\n for (const keyword of MODE_KEYWORDS) {\n pi.registerCommand(keyword, {\n description: MODE_COMMAND_DESCRIPTIONS[keyword],\n handler: async (args: string, ctx: ExtensionCommandContext) => {\n state.mode = keyword;\n persistModeState(pi, state);\n // Forward a goal argument (e.g. `/fein implement the pipeline`) so the\n // injected mode prompt's \"if the user provided a goal, run it now\"\n // instruction has the goal to act on.\n if (args.trim()) {\n pi.sendUserMessage(args.trim(), { deliverAs: 'steer' });\n } else {\n ctx.ui.notify(`Mode set to ${keyword}. Describe what you'd like to work on.`);\n }\n await Promise.resolve();\n },\n });\n }\n\n pi.registerCommand(MODE_CLEAR_COMMAND, {\n description: 'Clear workflow mode and return to neutral routing',\n handler: async (_args: string, ctx: ExtensionCommandContext) => {\n state.mode = null;\n persistModeState(pi, state);\n ctx.ui.notify('Workflow mode cleared. Neutral routing is active.');\n await Promise.resolve();\n },\n });\n\n pi.registerCommand(STATUS_COMMAND, {\n description: 'Show the current maestria workflow mode and extension subset',\n handler: async (_args: string, ctx: ExtensionCommandContext) => {\n const mode = state.mode ?? 'none';\n const summary = [\n '# Maestria status (prime-agent)',\n '',\n `Workflow mode: ${mode}`,\n '',\n 'Commands: /fein, /sonar, /blitz, /mode-clear',\n '',\n 'This extension covers mode selection and mode prompt injection only.',\n 'Recursive-subagent (rlm) dispatch and JSON/RPC headless mode are NOT provided by this package.',\n ].join('\\n');\n ctx.ui.setEditorText(summary);\n await Promise.resolve();\n },\n });\n};\n","// packages/prime-agent/src/extension.ts\n// Prime Agent extension entry point (default-export factory).\n//\n// Compiled to `dist/extension.mjs` and declared in package.json under\n// `pi.extensions`; Prime loads it with its extension loader (pinned fork\n// 7787f07415d843b9a800f6a4720e0c739bd608e5, loader.ts: a jiti import of the\n// declared path calling the default export with the live ExtensionAPI).\n//\n// Verified subset (public Prime/Pi extension API only, see src/pi-api.ts):\n// - slash commands /fein /sonar /blitz /mode-clear and /maestria-status\n// - before_agent_start mode prompt injection (systemPrompt chaining)\n// - session-scoped mode state via custom session entries, restored on\n// session_start (reload/resume/fork) and session_tree (branch navigation)\n//\n// NOT provided (explicitly deferred, documented in README/INSTALL/ADR-CORE-014):\n// native recursive-subagent (`rlm`) dispatch - the pinned fork exposes no\n// public JS extension bridge for it (it is an IPython-side tool) - and\n// JSON/RPC headless mode integration. No tool interception is installed and no\n// sandbox/enforcement claim is made. This extension writes no files (no\n// `~/.pi`, no `.prime/agent` writes): state rides on host session entries.\n\nimport path from 'node:path';\n\nimport { createModePromptHandler, installCommands } from './modes.js';\nimport type {\n ExtensionAPI,\n ExtensionContext,\n SessionStartEvent,\n SessionTreeEvent,\n} from './pi-api.js';\nimport { createInitialState, restoreModeState } from './state.js';\n\n/**\n * Resolve the package's generated `skills/` directory. When running from the\n * built `dist/extension.mjs`, this is `<packageRoot>/skills`; when running from\n * source (tests), it is the same package-relative location.\n */\nconst resolveSkillsDir = (): string => {\n const moduleDir = import.meta.dirname;\n return path.resolve(moduleDir, '../skills');\n};\n\nconst extension = (pi: ExtensionAPI): void => {\n const state = createInitialState();\n const skillsDir = resolveSkillsDir();\n\n // Mode commands + status command (session-scoped state, persisted via\n // pi.appendEntry custom entries).\n installCommands(pi, state);\n\n // Mode prompt injection on the next agent turn.\n pi.on('before_agent_start', createModePromptHandler(state, skillsDir));\n\n // Restore the active mode when a session starts, is reloaded, resumed, or\n // forked, and when navigating the session tree to a different branch.\n pi.on('session_start', (_event: SessionStartEvent, ctx: ExtensionContext) => {\n restoreModeState(state, ctx.sessionManager.getBranch());\n });\n\n pi.on('session_tree', (_event: SessionTreeEvent, ctx: ExtensionContext) => {\n restoreModeState(state, ctx.sessionManager.getBranch());\n });\n};\n\nexport default extension;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maestria/prime-agent",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Maestria methodology for Prime Agent - specialist roles, orchestrator, global rules, and workflow modes as Agent Skills, plus a small Prime/Pi extension for mode commands and mode prompt injection",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^26.2.0",
|
|
40
40
|
"typescript": "^7.0.2",
|
|
41
|
-
"vite-plus": "0.
|
|
41
|
+
"vite-plus": "0.3.0",
|
|
42
42
|
"vitest": "4.1.11"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: adventurer
|
|
3
2
|
description: |-
|
|
4
3
|
Codebase reconnaissance skill. Maps unknown territory -
|
|
5
4
|
traces call chains, maps module relationships, generates structured recon
|
|
@@ -7,6 +6,7 @@ description: |-
|
|
|
7
6
|
only, never implementation or design.
|
|
8
7
|
Use for: understanding unfamiliar code, tracing dependencies, gathering context
|
|
9
8
|
before implementation, investigating module structures.
|
|
9
|
+
name: adventurer
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: architect
|
|
3
2
|
description: |-
|
|
4
3
|
Architecture decisions using decision matrices and ADRs.
|
|
5
4
|
Evaluates options with weighted criteria, clarifies business context first.
|
|
6
5
|
Use for: technology choices, implementation approaches, trade-off analysis,
|
|
7
6
|
threat modeling, or ADR decisions.
|
|
7
|
+
name: architect
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
package/skills/blitz/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: blitz
|
|
3
2
|
description: Fast implementation mode - skip optional ceremony for familiar, low-risk work; never waive safety or required review. Load when the user invokes blitz or asks for a fast route.
|
|
3
|
+
name: blitz
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
package/skills/builder/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: builder
|
|
3
2
|
description: |-
|
|
4
3
|
Focused implementation skill for atomic tasks. Executes
|
|
5
4
|
one verifiable unit of work with minimal context and a clean diff.
|
|
6
5
|
Use for: targeted fixes, feature implementation, refactors, adding tests.
|
|
6
|
+
name: builder
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
package/skills/diagnose/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: diagnose
|
|
3
2
|
description: |-
|
|
4
3
|
Systematic 6-step regression tracing: from error message
|
|
5
4
|
to root cause to prevention.
|
|
6
5
|
Use for: cryptic errors, regressions, production bugs, unclear root causes.
|
|
6
|
+
name: diagnose
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -66,7 +66,7 @@ Fix the root cause with minimal changes:
|
|
|
66
66
|
|
|
67
67
|
Prevent similar bugs:
|
|
68
68
|
|
|
69
|
-
-
|
|
69
|
+
- Consider regression tests where a durable contract or plausible recurrence justifies them (per Global Rules testing judgment)
|
|
70
70
|
- Consider linting rules to catch the pattern
|
|
71
71
|
- Document the lesson in a knowledge artifact for future reference
|
|
72
72
|
|
package/skills/fein/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: fein
|
|
3
2
|
description: Full pipeline mode - reconnaissance or design, implementation, and independent review. Load when the user invokes fein or asks for the complete maestria pipeline.
|
|
3
|
+
name: fein
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: global-rules
|
|
3
2
|
description: |-
|
|
4
3
|
Universal agent rules contract: universal floors,
|
|
5
4
|
orchestration, delegation, context management, handoff, blind review, bounded
|
|
@@ -7,6 +6,7 @@ description: |-
|
|
|
7
6
|
safety.
|
|
8
7
|
Load once per session and apply to routing, delegation, review, and commit
|
|
9
8
|
decisions.
|
|
9
|
+
name: global-rules
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -14,7 +14,7 @@ description: |-
|
|
|
14
14
|
|
|
15
15
|
# Global Agent Rules - @maestria/prime-agent
|
|
16
16
|
|
|
17
|
-
Cross-platform behavior contract
|
|
17
|
+
Cross-platform behavior contract for outcomes, evidence, safety, delegation, review, and bounded repair. The host controls tool authority and lifecycle; specialists own methodology; project rules cannot waive these floors.
|
|
18
18
|
|
|
19
19
|
## Universal Floors
|
|
20
20
|
|
|
@@ -24,8 +24,13 @@ Cross-platform behavior contract: outcomes, evidence, safety, delegation, review
|
|
|
24
24
|
- **!!! Match effort to stakes.** Use the smallest route, investigation, test set, and review depth that establishes acceptance; escalate only when uncertainty, impact, or complexity warrants it.
|
|
25
25
|
- **!!! Prefer reuse over reinvention.** Check existing project code, dependencies, framework capabilities, and mature ecosystem solutions before custom infrastructure; weigh fit, maintenance, compatibility, security, and total cost when material.
|
|
26
26
|
- **!!! Exhaust available evidence before asking.** Make material assumptions explicit, tag uncertain ones `[inferred]`, and proceed on ordinary ambiguity. Ship affected documentation and changesets with code when project policy requires them.
|
|
27
|
+
- **!!! Exercise testing judgment, not coverage.** New test files, fixtures, mocks, and test-only helpers are opt-in, never automatic: reuse existing suites first and prefer the cheapest verification that establishes acceptance (typecheck, lint, runtime or browser checks). Add tests only for durable contracts and plausible regressions; assert observable behavior, not implementation shape; mock only genuinely external seams (network, clock, randomness).
|
|
27
28
|
- **!!! Keep output self-contained and professional.** Understand existing systems before adapting or deleting them, and never claim isolation, enforcement, or lifecycle control the runtime does not provide.
|
|
28
|
-
- **!!! Human-facing output.** In agent responses, status updates,
|
|
29
|
+
- **!!! Human-facing output.** In all agent-authored text (responses, status updates, briefs, comments/docstrings, commit messages, PR titles/descriptions, and documentation), never emit Unicode U+2014 EM DASH. Prefer commas, colons, parentheses, or ASCII hyphen-minus (`-`). Preserve code syntax, intentional literals, quoted source text, and user-provided text. Scan authored output before handoff or delivery.
|
|
30
|
+
|
|
31
|
+
### Prefer self-explanatory code over comments
|
|
32
|
+
|
|
33
|
+
Default to code that explains itself: prefer clear naming, small functions, appropriate abstractions, and simple control flow; rewrite code that needs comments to explain mechanics. Do not add comments that merely restate what the code does. Add comments only for concise, durable context the code cannot express, especially to explain non-obvious invariants, intentional trade-offs, workarounds for external systems, libraries, platforms, or bugs, and deliberately surprising behavior that might otherwise look wrong and tempt a maintainer to "fix" it.
|
|
29
34
|
|
|
30
35
|
## Modes
|
|
31
36
|
|
|
@@ -33,9 +38,7 @@ Per-turn keywords when the host supports them: `fein` requests the full route wi
|
|
|
33
38
|
|
|
34
39
|
## Outcome and Scope
|
|
35
40
|
|
|
36
|
-
Define the primary user outcome, acceptance evidence, and
|
|
37
|
-
|
|
38
|
-
Changes altering security, authentication, or permission boundaries are mandatory stops; ordinary in-scope security defects may be repaired autonomously.
|
|
41
|
+
Define the primary user outcome, acceptance evidence, and non-goals before substantial work or delegation; measure progress against them, not activity. Keep file, package, and runtime scope explicit. Classify findings as in-scope defects, design blockers, platform limitations, or follow-ups, and do not expand scope for adjacent findings unless they invalidate acceptance or create an immediate safety or production risk. Freeze the outcome, acceptance criteria, non-goals, and repair limits at the start of a work unit; re-plan only when the outcome or evidence changes. Research-only, planning-only, explicitly read-only, and host-blocked work ends at its requested artifact or exact blocker.
|
|
39
42
|
|
|
40
43
|
## Delegation and Context
|
|
41
44
|
|
|
@@ -51,11 +54,9 @@ Default to one independent review and, only when blockers exist, one repair/re-r
|
|
|
51
54
|
|
|
52
55
|
## Authorization, Lifecycle, and Branches
|
|
53
56
|
|
|
54
|
-
Safety and authorization override user intent, methodology, and brevity. Stop and obtain applicable authorization before changes that alter
|
|
55
|
-
|
|
56
|
-
The orchestrator owns continuation for implementation and delivery work until the outcome reaches its terminal artifact; incomplete todos, pending handoffs, or specialist messages saying "continue if needed" are not a user checkpoint. Routine delivery is autonomous. For implementation work, continue through validation, review, and delivery: when repository, branch, remote, ownership, and host capabilities support it, create or use a non-protected feature branch and continue through commit, push, and PR without asking whether to perform those steps - these are delivery mechanics, not approval checkpoints. Where supported, create a reviewable PR without ceremonial approval rather than stopping at a verified working tree; a delegated implementation outcome is complete only at its delivered state - reviewed changes on a pushed feature branch with an open PR. Never commit or push protected branches; inspect status, stage only intended files, and use logical conventional commits. Merge, release, and production operations remain separate authorization boundaries. Track task-owned background processes and stop and verify them before completion unless intentionally part of the requested result; never broadly kill unrelated or user-owned processes outside platform lifecycle controls. An explicitly authorized checkpoint may preserve unreviewed work but never authorizes shipping.
|
|
57
|
+
Safety and authorization override user intent, methodology, and brevity. Security, authentication, and permission boundaries are mandatory stops. Stop and obtain applicable authorization before changes that alter them, involve data migration or possible loss, impact production, are irreversible, create external side effects outside delegated scope, or involve consequential ambiguity after evidence is exhausted. Ordinary in-scope security defects may be repaired autonomously.
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
The orchestrator owns continuation for implementation and delivery work until the outcome reaches its terminal artifact; incomplete todos, pending handoffs, or specialist messages saying "continue if needed" are not a user checkpoint. Routine delivery is autonomous. For implementation work, continue through validation, review, and delivery: when repository, branch, remote, ownership, and host capabilities support it, create or use a non-protected feature branch and continue through commit, push, and PR without asking whether to perform those steps - these are delivery mechanics, not approval checkpoints. Where supported, create a reviewable PR without ceremonial approval rather than stopping at a verified working tree; a delegated implementation outcome is complete only at its delivered state - reviewed changes on a pushed feature branch with an open PR. Never commit or push protected branches; inspect status, stage only intended files, and use logical conventional commits. Before attaching visual PR evidence, confirm both preconditions: the project targets GitHub (GitHub remote with authenticated gh that supports media attachments, for example gh v2.99.0+ repeatable --attach on pr create, edit, and comment) and a capture tool is available (screenshot, screen-capture, or browser tool). When both hold and the change is visual or behavioral, capture a screenshot or short video at reasonable cost and attach it, preferring referenced paths with alt text (for example, --attach './after.png#Short alt text') within host size limits; skip when either check fails, when no display is available, or when review value is low. Vision is not required: when present, use it to verify the capture shows the intended state, otherwise describe the capture from the action taken and leave visual verification to the reviewer. Merge, release, and production operations remain separate authorization boundaries. Track task-owned background processes and stop and verify them before completion unless intentionally part of the requested result; never broadly kill unrelated or user-owned processes outside platform lifecycle controls. An explicitly authorized checkpoint may preserve unreviewed work but never authorizes shipping.
|
|
59
60
|
|
|
60
61
|
## Canonical Source Invariant
|
|
61
62
|
|
package/skills/handoff/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: handoff
|
|
3
2
|
description: |-
|
|
4
3
|
The handoff contract for inter-specialist delegation.
|
|
5
4
|
Load when receiving a task from another specialist, or when handing off work to
|
|
6
5
|
the next stage in the pipeline.
|
|
6
|
+
name: handoff
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: iteration-limits
|
|
3
2
|
description: |-
|
|
4
3
|
The iteration-limit pattern with verifiable termination
|
|
5
4
|
and escalation format.
|
|
6
5
|
Load when defining termination conditions for a loop, or when a loop is at risk
|
|
7
6
|
of running too long.
|
|
7
|
+
name: iteration-limits
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: orchestrator
|
|
3
2
|
description: |-
|
|
4
3
|
Maestria methodology dispatcher for Prime Agent. Routes
|
|
5
4
|
work (direct/focused/full), selects and loads the specialist skills
|
|
@@ -8,6 +7,7 @@ description: |-
|
|
|
8
7
|
(fein/sonar/blitz).
|
|
9
8
|
Use for multi-step or multi-file work, planning, review, debugging,
|
|
10
9
|
architecture decisions, or documentation.
|
|
10
|
+
name: orchestrator
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -79,7 +79,7 @@ Modes are case-insensitive and per-turn.
|
|
|
79
79
|
|
|
80
80
|
For implementation work, own the delivery path: inspect -> plan -> implement -> validate -> one independent review -> repair material blockers only when required -> targeted validation of repaired scope -> final verification -> commit -> push -> PR.
|
|
81
81
|
|
|
82
|
-
**Routine delivery is autonomous.** When repository, branch, remote, ownership, and host capabilities support PR delivery, do not ask whether to create or use a feature branch, commit, push, or create a PR; complete the lifecycle without ceremonial approval. A delegated implementation outcome reaches its terminal artifact only when delivered: reviewed changes on a pushed feature branch with an open PR. Do not stop at a local diff, commit, pushed branch, or `PR pending`, and never treat "not requested" as a reason to withhold routine delivery. Merge, release, and production actions remain separate authorization boundaries.
|
|
82
|
+
**Routine delivery is autonomous.** When repository, branch, remote, ownership, and host capabilities support PR delivery, do not ask whether to create or use a feature branch, commit, push, or create a PR; complete the lifecycle without ceremonial approval. A delegated implementation outcome reaches its terminal artifact only when delivered: reviewed changes on a pushed feature branch with an open PR. Do not stop at a local diff, commit, pushed branch, or `PR pending`, and never treat "not requested" as a reason to withhold routine delivery. When the change is visual or behavioral, attach a screenshot or short video only after confirming both preconditions: the project targets GitHub (GitHub remote with authenticated gh that supports --attach) and a capture tool is available (screenshot, screen-capture, or browser tool); skip when either check fails, when no display is available, or when cost outweighs review value. Vision is not required: use it to verify the capture when present, otherwise describe the capture from the action taken. Merge, release, and production actions remain separate authorization boundaries.
|
|
83
83
|
|
|
84
84
|
The parent session owns continuation until the selected implementation outcome reaches its terminal artifact. Incomplete todos or specialist handoffs are not user checkpoints: take or delegate the next bounded action. A failed or cancelled delegation is transport trouble, not a verdict - retry once with an adjusted brief before reporting a structured blocker; user-initiated or intentional platform cancellation is terminal. Research-only, planning-only, explicitly read-only, `sonar`, and host-blocked routes terminate at their requested artifact or exact blocker. Safety, authorization, ambiguity, and host-capability boundaries always take precedence.
|
|
85
85
|
|
package/skills/planner/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: planner
|
|
3
2
|
description: |-
|
|
4
3
|
Create detailed implementation plans with phased
|
|
5
4
|
dependencies, timelines, verifiable success criteria, and rollback points.
|
|
6
5
|
Breaks complex features into verifiable milestones.
|
|
7
6
|
Use for: complex features requiring multi-phase execution, when the plan needs
|
|
8
7
|
review before building.
|
|
8
|
+
name: planner
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
package/skills/reviewer/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: reviewer
|
|
3
2
|
description: |-
|
|
4
3
|
Code review with quality gates. Reviews for correctness,
|
|
5
4
|
edge cases, security, performance, maintainability, and adherence to
|
|
6
5
|
conventions; provides specific, actionable feedback and preserves blind review.
|
|
7
6
|
Use for: post-implementation review, pre-commit review, architecture document
|
|
8
7
|
review.
|
|
8
|
+
name: reviewer
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|
|
@@ -68,9 +68,9 @@ The initial general reviewer must give a verdict for every category. A specializ
|
|
|
68
68
|
|
|
69
69
|
### 7. Test Coverage
|
|
70
70
|
|
|
71
|
-
-
|
|
72
|
-
- Do tests cover edge cases and error paths?
|
|
73
|
-
- Are tests meaningful (
|
|
71
|
+
- Is meaningful regression risk covered proportionate to stakes (per Global Rules testing judgment)?
|
|
72
|
+
- Do tests cover edge cases and error paths where the contract demands it?
|
|
73
|
+
- Are tests meaningful (observable behavior, not implementation details)?
|
|
74
74
|
|
|
75
75
|
### 8. Assumption Validation
|
|
76
76
|
|
package/skills/sonar/SKILL.md
CHANGED
package/skills/writer/SKILL.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: writer
|
|
3
2
|
description: |-
|
|
4
3
|
Documentation writing following structured patterns.
|
|
5
4
|
Creates clear, comprehensive docs for code, APIs, and systems.
|
|
6
5
|
Use for: README files, API docs, architecture docs, changelogs, decision
|
|
7
6
|
records.
|
|
7
|
+
name: writer
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
<!-- Auto-generated from @maestria/core. Do not edit directly.
|