@polymorphism-tech/morph-spec 4.10.6 → 4.10.8
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/CLAUDE.md +3 -0
- package/LICENSE +71 -71
- package/README.md +379 -379
- package/bin/morph-spec.js +89 -0
- package/bin/task-manager.js +59 -6
- package/claude-plugin.json +14 -14
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +206 -206
- package/framework/agents/README.md +14 -14
- package/framework/agents/architecture/standards-architect.md +159 -159
- package/framework/agents/frontend/blazor-builder.md +13 -0
- package/framework/agents/frontend/css-specialist.md +87 -0
- package/framework/agents/frontend/nextjs-expert.md +13 -0
- package/framework/agents/frontend/nextjs-ui-specialist.md +218 -0
- package/framework/agents/frontend/ui-ux-designer.md +80 -10
- package/framework/agents/infrastructure/azure-architect.md +149 -149
- package/framework/agents/infrastructure/infra-architect.md +48 -48
- package/framework/agents.json +2268 -2567
- package/framework/hooks/README.md +204 -204
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +10 -5
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +10 -24
- package/framework/hooks/shared/phase-utils.js +139 -139
- package/framework/hooks/shared/worktree-helpers.js +30 -8
- package/framework/rules/csharp-standards.md +13 -13
- package/framework/rules/frontend-standards.md +13 -13
- package/framework/rules/infrastructure-standards.md +16 -16
- package/framework/rules/testing-standards.md +14 -14
- package/framework/skills/README.md +0 -1
- package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +12 -0
- package/framework/skills/level-0-meta/morph-code-review-nextjs/references/review-example-nextjs.md +254 -254
- package/framework/skills/level-0-meta/morph-init/SKILL.md +88 -3
- package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +247 -247
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +270 -270
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +515 -499
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +508 -471
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +12 -1
- package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +272 -258
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +317 -311
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +424 -323
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +2040 -2040
- package/framework/standards/frontend/nextjs/motion-patterns.md +321 -0
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -17
- package/framework/templates/README.md +814 -814
- package/framework/templates/code/dotnet/contracts/Commands.cs +74 -74
- package/framework/templates/code/dotnet/contracts/Entities.cs +25 -25
- package/framework/templates/code/dotnet/contracts/Queries.cs +74 -74
- package/framework/templates/code/dotnet/contracts/README.md +74 -74
- package/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -173
- package/framework/templates/code/dotnet/frontend/component.razor +239 -239
- package/framework/templates/code/dotnet/jobs/agent.cs +163 -163
- package/framework/templates/code/dotnet/jobs/job.cs +171 -171
- package/framework/templates/code/dotnet/test.cs +239 -239
- package/framework/templates/code/sql/rls-policy.sql +57 -57
- package/framework/templates/code/sql/supabase-migration.sql +100 -100
- package/framework/templates/code/sql/supabase-migration.template.sql +113 -113
- package/framework/templates/code/typescript/contracts.ts +168 -168
- package/framework/templates/context/CONTEXT.md +181 -181
- package/framework/templates/context/design-system.md +211 -0
- package/framework/templates/docs/proposal.md +182 -182
- package/framework/templates/docs/user-stories.md +34 -34
- package/framework/templates/examples/design-system-examples.md +357 -357
- package/framework/templates/examples/spec-examples.md +90 -90
- package/framework/templates/feature/decisions.md +187 -187
- package/framework/templates/feature/recap.md +146 -146
- package/framework/templates/feature/tasks.md +199 -199
- package/framework/templates/infrastructure/azure/README.md +286 -286
- package/framework/templates/infrastructure/azure/deploy-checklist.md +426 -426
- package/framework/templates/infrastructure/azure/parameters.dev.json +29 -29
- package/framework/templates/infrastructure/azure/parameters.prod.json +29 -29
- package/framework/templates/infrastructure/azure/parameters.staging.json +29 -29
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -67
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/docker/easypanel.template.json +54 -54
- package/package.json +82 -82
- package/src/commands/agents/agent-metrics.js +174 -0
- package/src/commands/agents/audit-dispatch.js +82 -0
- package/src/commands/agents/detect-agents.js +275 -0
- package/src/commands/agents/dispatch-agents.js +41 -135
- package/src/commands/agents/index.js +13 -4
- package/src/commands/agents/manage-agents.js +352 -0
- package/src/commands/project/doctor.js +59 -0
- package/src/commands/project/install-plugin-cmd.js +28 -28
- package/src/commands/project/setup-infra-cmd.js +12 -12
- package/src/commands/project/update.js +1 -17
- package/src/commands/project/worktree.js +58 -2
- package/src/commands/state/advance-phase.js +11 -3
- package/src/commands/tasks/index.js +4 -4
- package/src/commands/templates/index.js +5 -5
- package/src/commands/utils/index.js +3 -3
- package/src/commands/validation/index.js +4 -4
- package/src/core/state/phase-state-machine.js +217 -217
- package/src/core/state/state-manager.js +81 -0
- package/src/lib/agents/agents-manager.js +349 -0
- package/src/lib/agents/metrics-calculator.js +125 -0
- package/src/lib/agents/output-collector.js +75 -0
- package/src/lib/generators/context-generator.js +8 -7
- package/src/lib/generators/design-system-generator.js +298 -298
- package/src/lib/generators/index.js +10 -10
- package/src/lib/generators/metadata-extractor.js +387 -387
- package/src/lib/stack-filter.js +65 -65
- package/src/lib/standards/index.js +7 -7
- package/src/lib/standards/standards-context-injector.js +302 -302
- package/src/lib/tasks/task-parser.js +94 -3
- package/src/lib/validators/architecture/architecture-validator.js +387 -387
- package/src/lib/validators/architecture/index.js +7 -7
- package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +316 -316
- package/src/lib/validators/blazor/blazor-state-validator.js +279 -279
- package/src/lib/validators/blazor/blazor-validator.js +369 -369
- package/src/lib/validators/blazor/index.js +9 -9
- package/src/lib/validators/checkpoint-persistence.js +39 -0
- package/src/lib/validators/content/content-validator.js +287 -279
- package/src/lib/validators/content/index.js +7 -7
- package/src/lib/validators/contracts/index.js +7 -7
- package/src/lib/validators/css/css-validator.js +352 -352
- package/src/lib/validators/css/index.js +7 -7
- package/src/lib/validators/design-system/design-system-validator.js +231 -231
- package/src/lib/validators/design-system/index.js +7 -7
- package/src/lib/validators/nextjs/index.js +6 -6
- package/src/lib/validators/nextjs/next-component-validator.js +183 -183
- package/src/lib/validators/packages/index.js +7 -7
- package/src/lib/validators/packages/package-validator.js +360 -360
- package/src/lib/validators/shared/index.js +12 -12
- package/src/lib/validators/shared/issue-counter.js +18 -18
- package/src/lib/validators/shared/result-formatter.js +124 -124
- package/src/lib/validators/spec-validator.js +2 -2
- package/src/lib/validators/ui/index.js +7 -7
- package/src/lib/validators/ui/ui-contrast-validator.js +422 -422
- package/src/lib/validators/validation-runner.js +20 -0
- package/src/scripts/global-install.js +58 -58
- package/src/scripts/install-plugin.js +126 -126
- package/src/scripts/setup-infra.js +1 -17
- package/src/utils/agent-id-mapper.js +11 -0
- package/src/utils/agents-installer.js +40 -8
- package/src/utils/claude-md-injector.js +90 -90
- package/src/utils/claude-settings-manager.js +1 -1
- package/src/utils/file-copier.js +200 -196
- package/src/utils/hooks-installer.js +556 -739
- package/src/utils/logger.js +32 -32
- package/src/utils/skills-installer.js +178 -178
- package/src/utils/tier-helpers.js +24 -0
- package/src/utils/version-checker.js +175 -175
- package/framework/agents/architecture/po-pm-advisor.md +0 -203
- package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +0 -68
- package/framework/skills/level-1-workflows/morph-phase-implement/.morph/logs/activity.json +0 -38
- package/framework/skills/level-1-workflows/morph-phase-tasks/.morph/logs/activity.json +0 -14
- package/framework/templates/.idea/morph-templates.xml +0 -92
- package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
|
@@ -199,6 +199,20 @@ async function doctorFullCommand(frameworkRoot) {
|
|
|
199
199
|
check('agents.json', false, false, 'file not found');
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
// ── 6. agents.json version freshness ──────────────────────────────────
|
|
203
|
+
const canonicalAgentsPath = join(frameworkRoot, 'framework/agents.json');
|
|
204
|
+
if (await pathExists(agentsPath) && await pathExists(canonicalAgentsPath)) {
|
|
205
|
+
try {
|
|
206
|
+
const installed = JSON.parse(await fs.readFile(agentsPath, 'utf8'));
|
|
207
|
+
const canonical = JSON.parse(await fs.readFile(canonicalAgentsPath, 'utf8'));
|
|
208
|
+
const installedVer = installed.version || 'unknown';
|
|
209
|
+
const canonicalVer = canonical.version || 'unknown';
|
|
210
|
+
const isFresh = installedVer === canonicalVer;
|
|
211
|
+
check(`agents.json version (${installedVer})`, isFresh, true,
|
|
212
|
+
isFresh ? '' : `stale — canonical is v${canonicalVer}, run 'morph-spec update' to sync`);
|
|
213
|
+
} catch { /* ignore parse errors — already caught above */ }
|
|
214
|
+
}
|
|
215
|
+
|
|
202
216
|
// ── 7. Workflow Configs ──────────────────────────────────────────────────
|
|
203
217
|
console.log(chalk.cyan('\n framework/workflows/ — Workflow Configs'));
|
|
204
218
|
const stdPath = join(frameworkRoot, 'framework/workflows/configs/standard.json');
|
|
@@ -599,6 +613,51 @@ export async function doctorCommand(options = {}) {
|
|
|
599
613
|
} else {
|
|
600
614
|
checks.push({ name: 'agents.json tier counts', status: 'ok' });
|
|
601
615
|
}
|
|
616
|
+
|
|
617
|
+
// Check 4: v4 schema validation
|
|
618
|
+
const version = agentsData.version || 'unknown';
|
|
619
|
+
const isV4 = version.startsWith('4.');
|
|
620
|
+
const v3Fields = [];
|
|
621
|
+
const missingV4Fields = [];
|
|
622
|
+
|
|
623
|
+
for (const [id, data] of agentEntries) {
|
|
624
|
+
if (data.role !== undefined) v3Fields.push(`${id}.role`);
|
|
625
|
+
if (data.always_active !== undefined) v3Fields.push(`${id}.always_active`);
|
|
626
|
+
if (data.relationships !== undefined) v3Fields.push(`${id}.relationships`);
|
|
627
|
+
if (!data.group) missingV4Fields.push(`${id}.group`);
|
|
628
|
+
if (!Array.isArray(data.active_phases)) missingV4Fields.push(`${id}.active_phases`);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (isV4) {
|
|
632
|
+
checks.push({ name: `agents.json schema (v${version})`, status: 'ok' });
|
|
633
|
+
} else {
|
|
634
|
+
checks.push({
|
|
635
|
+
name: `agents.json schema (v${version})`,
|
|
636
|
+
status: 'warn',
|
|
637
|
+
msg: 'expected v4.x — run agents migration'
|
|
638
|
+
});
|
|
639
|
+
hasWarnings = true;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (v3Fields.length > 0) {
|
|
643
|
+
const sample = v3Fields.slice(0, 3).join(', ');
|
|
644
|
+
checks.push({
|
|
645
|
+
name: 'agents.json deprecated fields',
|
|
646
|
+
status: 'warn',
|
|
647
|
+
msg: `${v3Fields.length} v3 field(s) found: ${sample}${v3Fields.length > 3 ? '...' : ''}`
|
|
648
|
+
});
|
|
649
|
+
hasWarnings = true;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (missingV4Fields.length > 0 && isV4) {
|
|
653
|
+
const sample = missingV4Fields.slice(0, 3).join(', ');
|
|
654
|
+
checks.push({
|
|
655
|
+
name: 'agents.json v4 required fields',
|
|
656
|
+
status: 'warn',
|
|
657
|
+
msg: `${missingV4Fields.length} missing: ${sample}${missingV4Fields.length > 3 ? '...' : ''}`
|
|
658
|
+
});
|
|
659
|
+
hasWarnings = true;
|
|
660
|
+
}
|
|
602
661
|
} catch {
|
|
603
662
|
checks.push({ name: 'agents.json', status: 'error', msg: 'invalid JSON' });
|
|
604
663
|
hasErrors = true;
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
// src/commands/project/install-plugin-cmd.js
|
|
2
|
-
import { installPlugin } from '../../scripts/install-plugin.js';
|
|
3
|
-
import { logger } from '../../utils/logger.js';
|
|
4
|
-
|
|
5
|
-
export async function installPluginCommand(pluginName, _options) {
|
|
6
|
-
if (!pluginName) {
|
|
7
|
-
logger.error('Plugin name required. Usage: morph-spec install-plugin <name>');
|
|
8
|
-
logger.dim(' Available: superpowers, context7');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
try {
|
|
12
|
-
const result = await installPlugin(pluginName);
|
|
13
|
-
if (result.alreadyInstalled) {
|
|
14
|
-
logger.dim(` ✓ ${pluginName} already installed (${result.version})`);
|
|
15
|
-
} else {
|
|
16
|
-
logger.success(` ✓ ${pluginName} installed (${result.version})`);
|
|
17
|
-
logger.dim(' Restart Claude Code to activate.');
|
|
18
|
-
}
|
|
19
|
-
} catch (err) {
|
|
20
|
-
logger.error(`Failed to install plugin "${pluginName}": ${err.message}`);
|
|
21
|
-
logger.blank();
|
|
22
|
-
logger.warn('Manual installation:');
|
|
23
|
-
logger.dim(' 1. Claude Code → Settings (Cmd/Ctrl+,) → Extensions');
|
|
24
|
-
logger.dim(` 2. Browse → search "${pluginName}" → Install`);
|
|
25
|
-
logger.dim(' 3. Restart Claude Code');
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
1
|
+
// src/commands/project/install-plugin-cmd.js
|
|
2
|
+
import { installPlugin } from '../../scripts/install-plugin.js';
|
|
3
|
+
import { logger } from '../../utils/logger.js';
|
|
4
|
+
|
|
5
|
+
export async function installPluginCommand(pluginName, _options) {
|
|
6
|
+
if (!pluginName) {
|
|
7
|
+
logger.error('Plugin name required. Usage: morph-spec install-plugin <name>');
|
|
8
|
+
logger.dim(' Available: superpowers, context7');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const result = await installPlugin(pluginName);
|
|
13
|
+
if (result.alreadyInstalled) {
|
|
14
|
+
logger.dim(` ✓ ${pluginName} already installed (${result.version})`);
|
|
15
|
+
} else {
|
|
16
|
+
logger.success(` ✓ ${pluginName} installed (${result.version})`);
|
|
17
|
+
logger.dim(' Restart Claude Code to activate.');
|
|
18
|
+
}
|
|
19
|
+
} catch (err) {
|
|
20
|
+
logger.error(`Failed to install plugin "${pluginName}": ${err.message}`);
|
|
21
|
+
logger.blank();
|
|
22
|
+
logger.warn('Manual installation:');
|
|
23
|
+
logger.dim(' 1. Claude Code → Settings (Cmd/Ctrl+,) → Extensions');
|
|
24
|
+
logger.dim(` 2. Browse → search "${pluginName}" → Install`);
|
|
25
|
+
logger.dim(' 3. Restart Claude Code');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { setupInfra } from '../../scripts/setup-infra.js';
|
|
2
|
-
import { logger } from '../../utils/logger.js';
|
|
3
|
-
|
|
4
|
-
export async function setupInfraCommand(options) {
|
|
5
|
-
const targetPath = options.path || process.cwd();
|
|
6
|
-
try {
|
|
7
|
-
await setupInfra(targetPath);
|
|
8
|
-
} catch (err) {
|
|
9
|
-
logger.error(`setup-infra failed: ${err.message}`);
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
1
|
+
import { setupInfra } from '../../scripts/setup-infra.js';
|
|
2
|
+
import { logger } from '../../utils/logger.js';
|
|
3
|
+
|
|
4
|
+
export async function setupInfraCommand(options) {
|
|
5
|
+
const targetPath = options.path || process.cwd();
|
|
6
|
+
try {
|
|
7
|
+
await setupInfra(targetPath);
|
|
8
|
+
} catch (err) {
|
|
9
|
+
logger.error(`setup-infra failed: ${err.message}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
getUpdateInstructions,
|
|
26
26
|
detectInstallMethod
|
|
27
27
|
} from '../../utils/version-checker.js';
|
|
28
|
-
import { installClaudeHooks, installGlobalStatusline
|
|
28
|
+
import { installClaudeHooks, installGlobalStatusline } from '../../utils/claude-settings-manager.js';
|
|
29
29
|
import { installSkills } from '../../utils/skills-installer.js';
|
|
30
30
|
import { installAgents, installDomainAgents } from '../../utils/agents-installer.js';
|
|
31
31
|
import { injectMorphImport } from '../../utils/claude-md-injector.js';
|
|
@@ -309,22 +309,6 @@ export async function updateCommand(options) {
|
|
|
309
309
|
updateSpinner.text = 'Updating Claude Code hooks...';
|
|
310
310
|
const hooksResult = await installClaudeHooks(targetPath);
|
|
311
311
|
|
|
312
|
-
// Install shell integration (terminal title watcher)
|
|
313
|
-
updateSpinner.text = 'Installing shell integration...';
|
|
314
|
-
try {
|
|
315
|
-
await installShellIntegration();
|
|
316
|
-
} catch {
|
|
317
|
-
logger.dim(' ⚠ Could not install shell integration (non-critical)');
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Configure VS Code terminal settings (enable OSC title sequences)
|
|
321
|
-
updateSpinner.text = 'Configuring VS Code terminal settings...';
|
|
322
|
-
try {
|
|
323
|
-
await installVSCodeTerminalSettings();
|
|
324
|
-
} catch {
|
|
325
|
-
logger.dim(' ⚠ Could not configure VS Code terminal settings (non-critical)');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
312
|
// Ensure root CLAUDE.md has morph-spec @import (preserves user content)
|
|
329
313
|
updateSpinner.text = 'Checking CLAUDE.md import...';
|
|
330
314
|
const claudeMdDest = join(targetPath, 'CLAUDE.md');
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { execSync } from 'child_process';
|
|
17
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
18
|
-
import { join } from 'path';
|
|
17
|
+
import { existsSync, mkdirSync, symlinkSync, linkSync, copyFileSync } from 'fs';
|
|
18
|
+
import { join, resolve, dirname } from 'path';
|
|
19
19
|
|
|
20
20
|
// ── Pure helpers (exported for tests) ──────────────────────────────────────
|
|
21
21
|
|
|
@@ -93,6 +93,59 @@ function getDateSuffix() {
|
|
|
93
93
|
return new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// ── Infrastructure linking ───────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Create symlinks/junctions in the worktree for shared infrastructure files
|
|
100
|
+
* that are gitignored (state.json, .claude/, .morph/framework/, node_modules/).
|
|
101
|
+
*
|
|
102
|
+
* Uses junctions for directories (no admin required on Windows).
|
|
103
|
+
* File symlinks fall back to copy if symlink fails.
|
|
104
|
+
* Fail-open: any error is silently ignored.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} worktreePath - Absolute path to the worktree
|
|
107
|
+
* @param {string} mainCwd - Absolute path to the main project root
|
|
108
|
+
*/
|
|
109
|
+
export function setupInfraLinks(worktreePath, mainCwd) {
|
|
110
|
+
const mainAbs = resolve(mainCwd);
|
|
111
|
+
const wtAbs = resolve(worktreePath);
|
|
112
|
+
|
|
113
|
+
// Directory junctions — shared across worktrees
|
|
114
|
+
const dirLinks = ['node_modules', '.claude'];
|
|
115
|
+
|
|
116
|
+
// .morph/framework/ — client projects (in framework repo, framework/ is tracked)
|
|
117
|
+
if (existsSync(join(mainAbs, '.morph', 'framework'))) {
|
|
118
|
+
dirLinks.push(join('.morph', 'framework'));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const rel of dirLinks) {
|
|
122
|
+
const target = join(mainAbs, rel);
|
|
123
|
+
const linkPath = join(wtAbs, rel);
|
|
124
|
+
if (!existsSync(target) || existsSync(linkPath)) continue;
|
|
125
|
+
try {
|
|
126
|
+
const parent = dirname(linkPath);
|
|
127
|
+
if (!existsSync(parent)) mkdirSync(parent, { recursive: true });
|
|
128
|
+
symlinkSync(target, linkPath, 'junction');
|
|
129
|
+
} catch { /* fail-open */ }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// state.json — shared state via hard link (works on Windows without admin,
|
|
133
|
+
// same NTFS volume). Falls back to symlink, then copy.
|
|
134
|
+
const stateTarget = join(mainAbs, '.morph', 'state.json');
|
|
135
|
+
const stateLink = join(wtAbs, '.morph', 'state.json');
|
|
136
|
+
if (existsSync(stateTarget) && !existsSync(stateLink)) {
|
|
137
|
+
const morphDir = join(wtAbs, '.morph');
|
|
138
|
+
if (!existsSync(morphDir)) {
|
|
139
|
+
try { mkdirSync(morphDir, { recursive: true }); } catch { /* */ }
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
linkSync(stateTarget, stateLink); // hard link — no admin, shared data
|
|
143
|
+
} catch {
|
|
144
|
+
try { copyFileSync(stateTarget, stateLink); } catch { /* fail-open */ }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
96
149
|
// ── Command handler ─────────────────────────────────────────────────────────
|
|
97
150
|
|
|
98
151
|
/**
|
|
@@ -133,6 +186,9 @@ export async function worktreeSetupCommand(feature, options = {}) {
|
|
|
133
186
|
// Add worktree
|
|
134
187
|
execSync(`git worktree add "${worktreePath}" ${branch}`, { cwd, stdio: 'pipe' });
|
|
135
188
|
|
|
189
|
+
// Set up infrastructure symlinks so the worktree has state.json, .claude/, etc.
|
|
190
|
+
setupInfraLinks(worktreePath, cwd);
|
|
191
|
+
|
|
136
192
|
// Persist in state (non-blocking — feature may not be in state yet)
|
|
137
193
|
try {
|
|
138
194
|
const { loadState, saveState } = await import('../../lib/state/state-manager.js');
|
|
@@ -269,9 +269,6 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
269
269
|
|
|
270
270
|
if (!specContentValidation.valid) {
|
|
271
271
|
console.log(chalk.red('\n✗ Spec content validation failed:'));
|
|
272
|
-
specContentValidation.missing.forEach(section => {
|
|
273
|
-
console.log(chalk.red(` - Missing section: ${section}`));
|
|
274
|
-
});
|
|
275
272
|
specContentValidation.errors.forEach(error => {
|
|
276
273
|
console.log(chalk.red(` - ${error}`));
|
|
277
274
|
});
|
|
@@ -441,6 +438,17 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
441
438
|
// Hook executor unavailable — non-blocking
|
|
442
439
|
}
|
|
443
440
|
|
|
441
|
+
// Agent detection refresh (fail-open)
|
|
442
|
+
try {
|
|
443
|
+
const { refreshAgents, displayDetectionDiff } = await import('../agents/detect-agents.js');
|
|
444
|
+
const refreshResult = await refreshAgents(process.cwd(), feature);
|
|
445
|
+
if (refreshResult.added.length > 0) {
|
|
446
|
+
displayDetectionDiff(refreshResult, currentPhase, nextPhase);
|
|
447
|
+
}
|
|
448
|
+
} catch {
|
|
449
|
+
// Refresh is diagnostic — fail-open, phase advance already completed
|
|
450
|
+
}
|
|
451
|
+
|
|
444
452
|
// Emit Tier-4 validator dispatch when advancing into implement or sync phase
|
|
445
453
|
const phasesNeedingValidation = ['implement', 'sync'];
|
|
446
454
|
if (phasesNeedingValidation.includes(nextPhase) || phasesNeedingValidation.includes(currentPhase)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task Management Commands
|
|
3
|
-
*/
|
|
4
|
-
export { taskCommand } from './task.js';
|
|
1
|
+
/**
|
|
2
|
+
* Task Management Commands
|
|
3
|
+
*/
|
|
4
|
+
export { taskCommand } from './task.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template Commands
|
|
3
|
-
*/
|
|
4
|
-
export { templateRenderCommand } from './template-render.js';
|
|
5
|
-
export { generateContractsCommand, parseSchemaAnalysisMd } from './generate-contracts.js';
|
|
1
|
+
/**
|
|
2
|
+
* Template Commands
|
|
3
|
+
*/
|
|
4
|
+
export { templateRenderCommand } from './template-render.js';
|
|
5
|
+
export { generateContractsCommand, parseSchemaAnalysisMd } from './generate-contracts.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility Commands — no active commands after CLI simplification
|
|
3
|
-
*/
|
|
1
|
+
/**
|
|
2
|
+
* Utility Commands — no active commands after CLI simplification
|
|
3
|
+
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validation Commands
|
|
3
|
-
*/
|
|
4
|
-
export { validateFeatureCommand } from './validate-feature.js';
|
|
1
|
+
/**
|
|
2
|
+
* Validation Commands
|
|
3
|
+
*/
|
|
4
|
+
export { validateFeatureCommand } from './validate-feature.js';
|