Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e722fce
refactor: decompose src/ into shared core libraries and modular gener…
josstei Apr 13, 2026
dae0978
feat(lib): add typed error hierarchy (lib/errors)
josstei Apr 13, 2026
5405036
feat(lib): add safe I/O primitives (lib/io)
josstei Apr 13, 2026
54a7ab7
feat(lib): add case conversion utilities (lib/naming)
josstei Apr 13, 2026
486ff94
feat(lib): add unified frontmatter parser (lib/frontmatter)
josstei Apr 13, 2026
3cea393
feat(lib): add reusable validation primitives (lib/validation)
josstei Apr 13, 2026
7f194ec
feat(lib): add generic discovery framework (lib/discovery)
josstei Apr 13, 2026
0da133e
test(lib): add migration parity tests for all lib/ modules
josstei Apr 13, 2026
817969b
build: add lib/ to detached payload allowlist for Claude and Codex pl…
josstei Apr 13, 2026
6cb6727
refactor(core): migrate core layer to lib/ foundation
josstei Apr 13, 2026
a5da9b4
refactor(transforms): migrate transforms to lib/ and auto-discovery
josstei Apr 13, 2026
45bcf72
refactor(mcp): migrate handlers to lib/errors and lib/validation
josstei Apr 13, 2026
e763c40
refactor(hooks,generator): migrate to lib/ foundation
josstei Apr 13, 2026
5756959
refactor(cleanup): remove deprecated modules, add layer boundary enfo…
josstei Apr 13, 2026
26292b0
refactor: finalize internals — eliminate wrapper functions and inline…
josstei Apr 13, 2026
f50a0d8
refactor: extract generation session, tool outcome, and registry buil…
josstei Apr 13, 2026
e92cbee
Merge remote-tracking branch 'origin/dev' into impl/src-decomposition
josstei Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions claude/src/agents/accessibility-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Bash, Glob, Grep, WebSearch, TaskCreate, TaskUpdate, TaskLi
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_shell
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/analytics-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, WebSearch, TaskCreate, TaskU
max_turns: 25
temperature: 0.2
timeout_mins: 10
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/api-designer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Glob, Grep, WebSearch, WebFetch]
max_turns: 15
temperature: 0.3
timeout_mins: 5
capabilities: read_only
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Glob, Grep, WebSearch, WebFetch]
max_turns: 15
temperature: 0.3
timeout_mins: 5
capabilities: read_only
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Glob, Grep]
max_turns: 15
temperature: 0.2
timeout_mins: 5
capabilities: read_only
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/coder.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 25
temperature: 0.2
timeout_mins: 10
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/compliance-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Glob, Grep, WebSearch, WebFetch]
max_turns: 15
temperature: 0.3
timeout_mins: 5
capabilities: read_only
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/content-strategist.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Glob, Grep, WebSearch, WebFetch]
max_turns: 15
temperature: 0.3
timeout_mins: 5
capabilities: read_only
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/copywriter.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Glob, Grep]
max_turns: 20
temperature: 0.3
timeout_mins: 8
capabilities: read_write
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/data-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Bash, Glob, Grep]
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_shell
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/design-system-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 25
temperature: 0.2
timeout_mins: 10
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/devops-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/i18n-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/performance-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Bash, Glob, Grep, WebSearch, WebFetch]
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_shell
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/product-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Glob, Grep, WebSearch]
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_write
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/refactor.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 25
temperature: 0.2
timeout_mins: 10
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/security-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Bash, Glob, Grep, WebSearch, WebFetch, TaskCreate, TaskUpda
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_shell
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/seo-specialist.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Bash, Glob, Grep, WebSearch, WebFetch, TaskCreate, TaskUpda
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_shell
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/technical-writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Glob, Grep, WebSearch, TaskCreate, TaskUpdate,
max_turns: 15
temperature: 0.3
timeout_mins: 5
capabilities: read_write
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/tester.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Bash, Glob, Grep, TaskCreate, TaskUpdate, Task
max_turns: 25
temperature: 0.2
timeout_mins: 10
capabilities: full
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
1 change: 1 addition & 0 deletions claude/src/agents/ux-designer.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ tools.claude: [Read, Write, Edit, Glob, Grep, WebSearch]
max_turns: 20
temperature: 0.2
timeout_mins: 8
capabilities: read_write
---
<!-- @feature exampleBlocks -->
<example>
Expand Down
61 changes: 12 additions & 49 deletions claude/src/core/agent-registry.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,21 @@
'use strict';

const KNOWN_AGENTS = Object.freeze([
'architect',
'api_designer',
'code_reviewer',
'coder',
'data_engineer',
'debugger',
'devops_engineer',
'performance_engineer',
'refactor',
'security_engineer',
'technical_writer',
'tester',
'seo_specialist',
'copywriter',
'content_strategist',
'ux_designer',
'accessibility_specialist',
'product_manager',
'analytics_engineer',
'i18n_specialist',
'design_system_engineer',
'compliance_reviewer',
]);
const { toSnakeCase } = require('../lib/naming');
const agentRegistryData = require('../generated/agent-registry.json');

const AGENT_CAPABILITIES = Object.freeze({
architect: 'read_only',
api_designer: 'read_only',
code_reviewer: 'read_only',
content_strategist: 'read_only',
compliance_reviewer: 'read_only',
debugger: 'read_shell',
performance_engineer: 'read_shell',
security_engineer: 'read_shell',
seo_specialist: 'read_shell',
accessibility_specialist: 'read_shell',
technical_writer: 'read_write',
product_manager: 'read_write',
ux_designer: 'read_write',
copywriter: 'read_write',
coder: 'full',
data_engineer: 'full',
devops_engineer: 'full',
tester: 'full',
refactor: 'full',
design_system_engineer: 'full',
i18n_specialist: 'full',
analytics_engineer: 'full',
});
const KNOWN_AGENTS = Object.freeze(
agentRegistryData.map((entry) => toSnakeCase(entry.name))
);

const AGENT_CAPABILITIES = Object.freeze(
Object.fromEntries(
agentRegistryData.map((entry) => [toSnakeCase(entry.name), entry.capabilities])
)
);

function normalizeAgentName(name) {
if (typeof name !== 'string') return '';
return name.toLowerCase().replace(/-/g, '_');
return toSnakeCase(name.toLowerCase());
}

const AGENT_PATTERNS = KNOWN_AGENTS.map((agent) => {
Expand Down
20 changes: 0 additions & 20 deletions claude/src/core/atomic-write.js

This file was deleted.

8 changes: 3 additions & 5 deletions claude/src/core/env-file-parser.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const fs = require('fs');
const { readFileSafe } = require('../lib/io');

function trimQuotes(value) {
if ((value.startsWith('"') && value.endsWith('"')) ||
Expand Down Expand Up @@ -33,10 +33,8 @@ function stripInlineComment(value) {

function parseEnvFile(filePath) {
const result = {};
let content;
try {
content = fs.readFileSync(filePath, 'utf8');
} catch {
const content = readFileSafe(filePath, null);
if (content === null) {
return result;
}
const lines = content.split('\n');
Expand Down
34 changes: 34 additions & 0 deletions claude/src/core/feature-blocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

const FEATURE_BLOCK_REGEX =
/^[ \t]*<!-- @feature (\S+) -->\n([\s\S]*?)^[ \t]*<!-- @end-feature -->\n?/gm;

const COLLAPSED_NEWLINE_REGEX = /\n{3,}/g;

/**
* @param {string} content - Markdown content potentially containing feature blocks
* @param {Record<string, boolean>} features - Map of feature flag names to boolean inclusion values
* @param {{ mode?: 'strict' | 'lenient' }} [opts] - Configuration options
* @returns {string} Content with feature blocks resolved and excess newlines collapsed
* @throws {Error} In strict mode, when a feature flag is not present in the features object
*/
function stripFeatureBlocks(content, features, opts) {
const mode = (opts && opts.mode) || 'strict';

const replaced = content.replace(
FEATURE_BLOCK_REGEX,
(_match, flagName, body) => {
if (!(flagName in features)) {
if (mode === 'strict') {
throw new Error(`Unknown feature flag: "${flagName}"`);
}
return '';
}
return features[flagName] ? body : '';
}
);

return replaced.replace(COLLAPSED_NEWLINE_REGEX, '\n\n');
}

module.exports = { stripFeatureBlocks };
36 changes: 36 additions & 0 deletions claude/src/core/markdown-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;

/**
* Serializes structured data and a body string into the
* JSON-frontmatter format used by session state files.
*
* @param {Object} data - JSON-serializable data for the frontmatter block
* @param {string} [body] - Optional body content placed after the closing delimiter
* @returns {string} The formatted session state string
*/
function serialize(data, body) {
return `---\n${JSON.stringify(data, null, 2)}\n---\n${body || ''}`;
}

/**
* Parses a session state string containing JSON frontmatter and an optional body.
*
* @param {string} content - Raw session state content with `---` delimiters
* @returns {{ data: Object, body: string }} Parsed frontmatter data and body content
* @throws {Error} When no frontmatter delimiters are found in the content
*/
function parse(content) {
const match = content.match(FRONTMATTER_PATTERN);
if (!match) {
throw new Error('No YAML frontmatter found in session state');
}

return {
data: JSON.parse(match[1]),
body: match[2],
};
}

module.exports = { serialize, parse };
13 changes: 3 additions & 10 deletions claude/src/core/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,19 @@

const fs = require('node:fs');
const path = require('node:path');
const { readJsonSafe } = require('../lib/io');

const PACKAGE_NAME = '@maestro-orchestrator/maestro';
const VERSION_JSON_FILENAME = 'version.json';

function readJsonFile(filePath) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch {
return null;
}
}

function findPackageJsonVersion(startDir) {
let currentDir = path.resolve(startDir);

while (true) {
const candidate = path.join(currentDir, 'package.json');

if (fs.existsSync(candidate)) {
const pkg = readJsonFile(candidate);
const pkg = readJsonSafe(candidate);
if (pkg && pkg.name === PACKAGE_NAME && typeof pkg.version === 'string') {
return pkg.version;
}
Expand All @@ -38,7 +31,7 @@ function findPackageJsonVersion(startDir) {

function findVersionJsonFallback() {
const versionJsonPath = path.join(__dirname, '..', VERSION_JSON_FILENAME);
const versionData = readJsonFile(versionJsonPath);
const versionData = readJsonSafe(versionJsonPath);

if (versionData && typeof versionData.version === 'string') {
return versionData.version;
Expand Down
Loading
Loading