@polymorphism-tech/morph-spec 8.33.0 → 8.34.2
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/README.md +2 -2
- package/bin/morph-spec.js +25 -1
- package/bin/validate.js +379 -379
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +2 -2
- package/framework/MORPH.md +4 -5
- package/framework/agents.json +1 -0
- package/framework/docs/CLI.md +5 -2
- package/framework/hooks/README.md +11 -1
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +5 -8
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +79 -0
- package/framework/hooks/claude-code/core/chain.js +27 -7
- package/framework/hooks/claude-code/core/worktree-context.js +83 -14
- package/framework/hooks/claude-code/core/worktree-create.js +206 -0
- package/framework/hooks/claude-code/core/worktree-env-inject.js +87 -0
- package/framework/hooks/claude-code/core/worktree-remove.js +81 -0
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
- package/framework/hooks/git/pre-commit/agents.sh +25 -25
- package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
- package/framework/hooks/git/pre-commit/specs.sh +50 -50
- package/framework/hooks/git/pre-push/run-tests.sh +44 -44
- package/framework/hooks/shared/command-tokens.js +23 -0
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/git-paths.js +25 -0
- package/framework/hooks/shared/hook-response.js +17 -0
- package/framework/hooks/shared/morph-cli.js +134 -0
- package/framework/hooks/shared/stdin-reader.js +26 -26
- package/framework/rules/infrastructure-standards.md +3 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +3 -3
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +3 -1
- package/framework/skills/core/morph-plan/SKILL.md +6 -3
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +1 -1
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +30 -0
- package/framework/standards/ai-agents/agent-session.md +160 -160
- package/framework/standards/ai-agents/batching.md +193 -193
- package/framework/standards/ai-agents/context-providers.md +188 -188
- package/framework/standards/ai-agents/mcp-server.md +250 -250
- package/framework/standards/ai-agents/mcp-tools.md +197 -197
- package/framework/standards/ai-agents/middleware-patterns.md +207 -207
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -173
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -171
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -181
- package/framework/standards/ai-agents/modalities-vision.md +201 -201
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -155
- package/framework/standards/ai-agents/production.md +231 -231
- package/framework/standards/ai-agents/prompts-in-db.md +214 -214
- package/framework/standards/ai-agents/providers/model-registry.md +158 -158
- package/framework/standards/ai-agents/service-tier-flex.md +135 -135
- package/framework/standards/ai-agents/structured-output.md +249 -249
- package/framework/standards/ai-agents/sweet-spot.md +109 -109
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +88 -0
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/REGISTRY.json +1 -1
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
- package/framework/templates/code/dotnet/database/migration.cs +83 -83
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/code/typescript/contracts.ts +167 -167
- package/framework/templates/docs/clarifications.md +253 -253
- package/framework/templates/docs/schema-analysis.md +119 -119
- package/framework/templates/docs/ui-components.md +52 -52
- package/framework/templates/docs/ui-design-system.md +76 -76
- package/framework/templates/docs/ui-flows.md +167 -167
- package/framework/templates/docs/ui-mockups.md +98 -98
- package/framework/templates/feature/decisions.md +122 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +24 -14
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/integrations/asaas-client.cs +387 -387
- package/framework/templates/integrations/asaas-webhook.cs +351 -351
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
- package/framework/templates/project/validate.js +120 -120
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/dashboard/dashboard.js +53 -53
- package/src/commands/e2e/e2e.js +77 -39
- package/src/commands/index.js +13 -13
- package/src/commands/project/checkpoint.js +209 -209
- package/src/commands/project/doctor.js +8 -6
- package/src/commands/project/env.js +95 -0
- package/src/commands/project/worktree.js +266 -52
- package/src/commands/state/delete.js +8 -0
- package/src/commands/state/finish.js +29 -34
- package/src/core/state/phase-state-machine.js +197 -197
- package/src/core/templates/template-renderer.js +477 -477
- package/src/dashboard/app/components/DetailPanel.jsx +11 -11
- package/src/dashboard/app/components/FlowGraph.jsx +17 -17
- package/src/dashboard/app/components/SearchFilter.jsx +22 -22
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/AgentMap.jsx +370 -370
- package/src/dashboard/app/pages/HookInspector.jsx +430 -418
- package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
- package/src/dashboard/app/pages/RulesMap.jsx +273 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
- package/src/dashboard/app/pages/Standards.jsx +332 -332
- package/src/dashboard/app/styles/index.css +47 -47
- package/src/dashboard/index.html +12 -12
- package/src/dashboard/package.json +24 -24
- package/src/dashboard/scanner/hooks-scanner.js +5 -1
- package/src/dashboard/scanner/phases-scanner.js +15 -15
- package/src/dashboard/scanner/rubrics-scanner.js +12 -12
- package/src/dashboard/scanner/rules-scanner.js +37 -37
- package/src/dashboard/scanner/skills-scanner.js +43 -43
- package/src/dashboard/scanner/squads-scanner.js +13 -13
- package/src/dashboard/vite-plugin-morph-data.js +17 -17
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/detectors/design-system-detector.js +188 -188
- package/src/lib/detectors/index.js +217 -217
- package/src/lib/e2e/compose-env.js +6 -11
- package/src/lib/e2e/stack-teardown.js +115 -0
- package/src/lib/generators/architecture-scanner.js +2 -1
- package/src/lib/generators/design-system-generator.js +508 -508
- package/src/lib/generators/settings-generator.js +209 -209
- package/src/lib/graph/graphifyignore.js +2 -1
- package/src/lib/hooks/hook-executor.js +167 -167
- package/src/lib/installers/mcp-installer.js +719 -719
- package/src/lib/tasks/task-classifier.js +30 -30
- package/src/lib/tasks/task-parser.js +209 -209
- package/src/lib/tasks/test-runner.js +21 -4
- package/src/lib/validators/checkpoint-persistence.js +39 -39
- package/src/lib/validators/css/css-validator.js +340 -340
- package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
- package/src/lib/validators/shared/issue-counter.js +14 -14
- package/src/lib/validators/verify-runner.js +7 -0
- package/src/lib/worktree/dirs.js +32 -0
- package/src/lib/worktree/env-allocator.js +45 -11
- package/src/lib/worktree/worktree-audit.js +40 -2
- package/src/utils/agent-id-mapper.js +11 -11
- package/src/utils/claude-settings-manager.js +300 -300
- package/src/utils/file-copier.js +18 -13
- package/src/utils/hooks-installer.js +46 -3
- package/src/utils/skills-installer.js +187 -187
- package/framework/templates/.idea/morph-templates.xml +0 -92
- package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Stub: validation dispatch was driven by tier-4 agents in v4.
|
|
3
|
-
* In v5, validation is handled by morph-eval skill invoked directly
|
|
4
|
-
* by the Evaluator role. This function is kept for call-site compatibility.
|
|
5
|
-
*
|
|
6
|
-
* @module emit-validator-dispatch
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* No-op in v5. Validation dispatch is now handled by morph-eval skill.
|
|
11
|
-
*/
|
|
12
|
-
export async function emitValidatorDispatch(_featureName, _phase, _cwd) {
|
|
13
|
-
// v5: evaluation driven by morph-eval skill, not CLI dispatch
|
|
14
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Stub: validation dispatch was driven by tier-4 agents in v4.
|
|
3
|
+
* In v5, validation is handled by morph-eval skill invoked directly
|
|
4
|
+
* by the Evaluator role. This function is kept for call-site compatibility.
|
|
5
|
+
*
|
|
6
|
+
* @module emit-validator-dispatch
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* No-op in v5. Validation dispatch is now handled by morph-eval skill.
|
|
11
|
+
*/
|
|
12
|
+
export async function emitValidatorDispatch(_featureName, _phase, _cwd) {
|
|
13
|
+
// v5: evaluation driven by morph-eval skill, not CLI dispatch
|
|
14
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared issue counting utility for validators
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* @param {Array} issues - Array of validation issues with type property
|
|
6
|
-
* @returns {{errors: number, warnings: number, infos: number}} Count by type
|
|
7
|
-
*/
|
|
8
|
-
export function countIssues(issues) {
|
|
9
|
-
return {
|
|
10
|
-
errors: issues.filter((i) => i.type === 'error').length,
|
|
11
|
-
warnings: issues.filter((i) => i.type === 'warning').length,
|
|
12
|
-
infos: issues.filter((i) => i.type === 'info').length,
|
|
13
|
-
};
|
|
14
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Shared issue counting utility for validators
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* @param {Array} issues - Array of validation issues with type property
|
|
6
|
+
* @returns {{errors: number, warnings: number, infos: number}} Count by type
|
|
7
|
+
*/
|
|
8
|
+
export function countIssues(issues) {
|
|
9
|
+
return {
|
|
10
|
+
errors: issues.filter((i) => i.type === 'error').length,
|
|
11
|
+
warnings: issues.filter((i) => i.type === 'warning').length,
|
|
12
|
+
infos: issues.filter((i) => i.type === 'info').length,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -354,10 +354,17 @@ async function runE2eNode({ projectPath, featureName, taskId, skipE2e, freshE2e,
|
|
|
354
354
|
durationMs,
|
|
355
355
|
reason: result.reason ?? null,
|
|
356
356
|
output: result.output || '',
|
|
357
|
+
// Non-fatal findings (e.g. a compose with fixed ports at the ROOT, where
|
|
358
|
+
// nothing collides yet). Surfaced so the same compose does not fail
|
|
359
|
+
// unannounced the day the feature moves into a worktree.
|
|
360
|
+
warnings: Array.isArray(result.warnings) ? result.warnings : [],
|
|
357
361
|
};
|
|
358
362
|
}
|
|
359
363
|
|
|
360
364
|
function appendE2eFeedback(feedback, e2eNode) {
|
|
365
|
+
for (const warning of e2eNode.warnings || []) {
|
|
366
|
+
feedback.push(`[e2e] warning: ${warning}`);
|
|
367
|
+
}
|
|
361
368
|
if (e2eNode.status !== 'fail') return;
|
|
362
369
|
if (e2eNode.reason) feedback.push(`[e2e] ${e2eNode.reason}`);
|
|
363
370
|
for (const line of linesOf(e2eNode.output)) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dirs.js — the ONE place the worktree container directory is named.
|
|
3
|
+
*
|
|
4
|
+
* Every reader that resolves worktrees BY CONVENTION (test discovery, graph
|
|
5
|
+
* ignore list, the installed .gitignore, the architecture scanner, the
|
|
6
|
+
* dashboard scanner) imports from here. Duplicating the string is how the
|
|
7
|
+
* C1 bug comes back: a reader keeps the old name and silently goes blind.
|
|
8
|
+
*
|
|
9
|
+
* Readers that go through `git worktree list` (fleet, finish, worktree list)
|
|
10
|
+
* never depended on this — git records absolute paths.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The directory new worktrees are created under, relative to the primary root.
|
|
15
|
+
*
|
|
16
|
+
* NO leading dot, deliberately (C1). Jest escapes the `.` when it interpolates
|
|
17
|
+
* an absolute `rootDir` into the `testMatch` glob, so `<root>/.worktrees/...`
|
|
18
|
+
* stops matching and an entire frontend suite reports **0 tests without an
|
|
19
|
+
* error** — the suite "passes" having tested nothing. The dot bought nothing:
|
|
20
|
+
* the directory is gitignored either way.
|
|
21
|
+
*/
|
|
22
|
+
export const WORKTREES_DIR = 'worktrees';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The pre-C1 directory name. New worktrees never land here, but every reader
|
|
26
|
+
* that resolves worktrees BY CONVENTION must still accept it, so a machine
|
|
27
|
+
* that already had `.worktrees/{f}` keeps working with no manual migration.
|
|
28
|
+
*/
|
|
29
|
+
export const LEGACY_WORKTREES_DIR = '.worktrees';
|
|
30
|
+
|
|
31
|
+
/** Both names, new first — the read order for convention-based lookups. */
|
|
32
|
+
export const WORKTREE_DIR_NAMES = [WORKTREES_DIR, LEGACY_WORKTREES_DIR];
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
|
|
23
23
|
import { join } from 'path';
|
|
24
|
+
// src/ → hooks/shared/ is the allowed direction (hooks are installed standalone).
|
|
25
|
+
import { composeProjectName } from '../../../framework/hooks/shared/e2e-check.js';
|
|
24
26
|
|
|
25
27
|
const DEFAULT_BASE_PORT = 4000;
|
|
26
28
|
const DEFAULT_BLOCK_SIZE = 10;
|
|
@@ -124,9 +126,46 @@ export function releaseEnvBlock(feature, { gitCommonDir }) {
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
129
|
+
* Fixed offsets inside a block. The block has 10 ports; four are named, the
|
|
130
|
+
* rest (+4..+9) are the project's to use. A new offset added here MUST also be
|
|
131
|
+
* published by the compose template (`${VAR:-default}:container`), or it is a
|
|
132
|
+
* port nobody listens on.
|
|
133
|
+
*/
|
|
134
|
+
export const PORT_OFFSETS = Object.freeze({ web: 0, api: 1, postgres: 2, redis: 3 });
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* The ONE port-layout contract. Two writers derive from it — the
|
|
138
|
+
* `.morph/worktree.env` manifest (`buildEnvFileContent`) and the env handed to
|
|
139
|
+
* `docker compose` (`src/lib/e2e/compose-env.js`) — so a worktree's file and
|
|
140
|
+
* its running stack can never describe different worlds.
|
|
141
|
+
*
|
|
142
|
+
* `COMPOSE_PROJECT_NAME` is part of the layout on purpose: a hand-run
|
|
143
|
+
* `docker compose up` inside the worktree must land in the isolated project,
|
|
144
|
+
* not in the root's. Every value is a string (env-safe); key order is stable.
|
|
145
|
+
*
|
|
146
|
+
* @param {{ base: number, range: [number, number] }} block
|
|
147
|
+
* @param {{ stack?: string, feature?: string }} [opts]
|
|
148
|
+
* @returns {Record<string,string>}
|
|
149
|
+
*/
|
|
150
|
+
export function portLayout(block, { stack = '', feature = '' } = {}) {
|
|
151
|
+
const env = {};
|
|
152
|
+
if (feature) env.COMPOSE_PROJECT_NAME = composeProjectName(feature);
|
|
153
|
+
env.MORPH_PORT_BASE = String(block.base);
|
|
154
|
+
env.MORPH_PORT_RANGE = `${block.range[0]}-${block.range[1]}`;
|
|
155
|
+
env.PORT = String(block.base + PORT_OFFSETS.web);
|
|
156
|
+
env.API_PORT = String(block.base + PORT_OFFSETS.api);
|
|
157
|
+
env.POSTGRES_PORT = String(block.base + PORT_OFFSETS.postgres);
|
|
158
|
+
env.REDIS_PORT = String(block.base + PORT_OFFSETS.redis);
|
|
159
|
+
if (/\bdotnet\b/i.test(String(stack))) {
|
|
160
|
+
env.ASPNETCORE_URLS = `http://localhost:${block.base + PORT_OFFSETS.api}`;
|
|
161
|
+
}
|
|
162
|
+
return env;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Render the `.morph/worktree.env` contents for a block: a header, the
|
|
167
|
+
* feature, and exactly the `portLayout()` pairs — nothing else, so the file
|
|
168
|
+
* cannot drift from what compose receives.
|
|
130
169
|
*
|
|
131
170
|
* @param {string} feature
|
|
132
171
|
* @param {{ base: number, range: [number, number] }} block
|
|
@@ -135,15 +174,10 @@ export function releaseEnvBlock(feature, { gitCommonDir }) {
|
|
|
135
174
|
*/
|
|
136
175
|
export function buildEnvFileContent(feature, block, stack = '') {
|
|
137
176
|
const lines = [
|
|
138
|
-
`# Managed by morph-spec —
|
|
139
|
-
'# Derivado
|
|
177
|
+
`# Managed by morph-spec — ambiente dedicado desta worktree (feature: ${feature}).`,
|
|
178
|
+
'# Derivado, git-invisível, regenerado por `worktree setup|link`; nunca editar nem commitar.',
|
|
140
179
|
`MORPH_FEATURE=${feature}`,
|
|
141
|
-
|
|
142
|
-
`MORPH_PORT_RANGE=${block.range[0]}-${block.range[1]}`,
|
|
143
|
-
`PORT=${block.base}`,
|
|
180
|
+
...Object.entries(portLayout(block, { stack, feature })).map(([k, v]) => `${k}=${v}`),
|
|
144
181
|
];
|
|
145
|
-
if (/\bdotnet\b/i.test(String(stack))) {
|
|
146
|
-
lines.push(`ASPNETCORE_URLS=http://localhost:${block.base + 1}`);
|
|
147
|
-
}
|
|
148
182
|
return `${lines.join('\n')}\n`;
|
|
149
183
|
}
|
|
@@ -247,9 +247,47 @@ export function auditWorktrees(cwd = process.cwd()) {
|
|
|
247
247
|
|
|
248
248
|
const feature = entry.branch?.match(/^refs\/heads\/morph\/(.+)$/)?.[1] || null;
|
|
249
249
|
if (!feature) {
|
|
250
|
-
// Only worth reporting when it sits in morph's own worktree container —
|
|
251
|
-
// a worktree the user keeps elsewhere is none of morph's business.
|
|
252
250
|
const inContainer = WORKTREE_DIR_NAMES.some((d) => path.startsWith(`${rootNorm}/${d}/`));
|
|
251
|
+
const task = entry.branch?.match(/^refs\/heads\/morph-task\/(.+)$/)?.[1] || null;
|
|
252
|
+
|
|
253
|
+
if (!inContainer) {
|
|
254
|
+
// A worktree OUTSIDE morph's container was created behind morph's back
|
|
255
|
+
// (a native Claude Code run before the WorktreeCreate hook, a raw
|
|
256
|
+
// `git worktree add ../x`, another skill). It has no junctions, no port
|
|
257
|
+
// block, and nothing morph runs there — the exact shape that let a
|
|
258
|
+
// root's `.claude/` be emptied. Reported as `warn` (never a failure,
|
|
259
|
+
// NEVER pruned): the work inside may be the only copy.
|
|
260
|
+
const work = unintegratedWork(root, entry.branch, prIndex);
|
|
261
|
+
issues.push({
|
|
262
|
+
type: 'out-of-container',
|
|
263
|
+
severity: 'warn',
|
|
264
|
+
path,
|
|
265
|
+
detail: `${path} é um worktree fora de worktrees/ (${entry.branch || 'HEAD destacado'}) — criado sem o morph: sem junctions, sem portas, invisível ao \`fleet\`${work.unintegrated ? `; carrega trabalho NÃO integrado (${work.evidence})` : ''}`,
|
|
266
|
+
fix: work.unintegrated
|
|
267
|
+
? `integre a branch primeiro; depois \`morph-spec worktree remove --target "${path}"\`. Novos worktrees: \`morph-spec worktree setup <f>\` ou \`worktree provision <n>\``
|
|
268
|
+
: `morph-spec worktree remove --target "${path}" — e crie os próximos por \`morph-spec worktree setup <f>\` / \`worktree provision <n>\``,
|
|
269
|
+
});
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (task) {
|
|
274
|
+
// `morph-task/*`: a task-isolation tree provisioned by the WorktreeCreate
|
|
275
|
+
// hook. Clean → nothing to say (the orchestrator removes it after the
|
|
276
|
+
// merge). With commits the default does not have → report, never
|
|
277
|
+
// suggest removal.
|
|
278
|
+
const work = unintegratedWork(root, entry.branch, prIndex);
|
|
279
|
+
if (work.unintegrated) {
|
|
280
|
+
issues.push({
|
|
281
|
+
type: 'unintegrated-work',
|
|
282
|
+
severity: 'info',
|
|
283
|
+
path,
|
|
284
|
+
detail: `${path} é um worktree de isolamento de task (${entry.branch}) com trabalho NÃO integrado (${work.evidence})`,
|
|
285
|
+
fix: `integre a branch (\`git merge --no-ff morph-task/${task}\` no orquestrador) e depois \`morph-spec worktree remove --target "${path}"\``,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
253
291
|
if (inContainer) {
|
|
254
292
|
// Same hazard as `no-feature` below, and it needs the same guard:
|
|
255
293
|
// "invisible to fleet" says nothing about whether the WORK is safe
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Map an agents.json ID to the Claude Code subagent_type.
|
|
3
|
-
*
|
|
4
|
-
* @param {string} id - Agent ID from agents.json (e.g., "nextjs-expert")
|
|
5
|
-
* @param {number} [tier] - Agent tier (1-4). Defaults to non-validator.
|
|
6
|
-
* @returns {string} subagent_type matching .claude/agents/ filename stem
|
|
7
|
-
*/
|
|
8
|
-
export function agentIdToSubagentType(id, tier) {
|
|
9
|
-
const prefix = tier === 4 ? 'morph-validator-' : 'morph-';
|
|
10
|
-
return `${prefix}${id}`;
|
|
11
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Map an agents.json ID to the Claude Code subagent_type.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} id - Agent ID from agents.json (e.g., "nextjs-expert")
|
|
5
|
+
* @param {number} [tier] - Agent tier (1-4). Defaults to non-validator.
|
|
6
|
+
* @returns {string} subagent_type matching .claude/agents/ filename stem
|
|
7
|
+
*/
|
|
8
|
+
export function agentIdToSubagentType(id, tier) {
|
|
9
|
+
const prefix = tier === 4 ? 'morph-validator-' : 'morph-';
|
|
10
|
+
return `${prefix}${id}`;
|
|
11
|
+
}
|