@polymorphism-tech/morph-spec 8.41.0 → 8.43.0
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 +14 -4
- package/README.md +3 -3
- package/bin/morph-spec.js +48 -2
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +6 -5
- package/framework/MORPH.md +10 -9
- package/framework/agents.json +7 -7
- package/framework/docs/CLI.md +10 -3
- package/framework/evals/proof-rubrics/mutation-proof.md +43 -13
- package/framework/hooks/README.md +1 -0
- package/framework/hooks/claude-code/core/chain.js +2 -0
- package/framework/hooks/claude-code/core/comment-guard.js +107 -0
- package/framework/hooks/claude-code/core/heavy-gate.js +72 -0
- package/framework/hooks/claude-code/core/heavy-release.js +34 -0
- package/framework/hooks/claude-code/core/worktree-context.js +21 -20
- package/framework/hooks/claude-code/core/worktree-create.js +4 -4
- package/framework/hooks/shared/agent-reap.js +89 -0
- package/framework/hooks/shared/comment-rules.js +171 -0
- package/{src/lib/validators/code-budget → framework/hooks/shared}/comment-scanner.js +2 -2
- package/{src/lib/ai → framework/hooks/shared}/comment-stripper.js +2 -1
- package/framework/hooks/shared/e2e-check.js +3 -1
- package/framework/hooks/shared/graph-refresh.js +1 -9
- package/framework/hooks/shared/heavy-command.js +128 -0
- package/framework/hooks/shared/heavy-config.js +65 -0
- package/framework/hooks/shared/heavy-holders.js +85 -0
- package/framework/hooks/shared/heavy-slots.js +207 -0
- package/framework/hooks/shared/process-alive.js +8 -0
- package/framework/hooks/shared/source-files.js +34 -0
- package/framework/hooks/shared/worktree-root.js +93 -0
- package/framework/schemas/config.schema.json +80 -0
- 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 +11 -4
- 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 +12 -5
- package/framework/skills/core/morph-machine/SKILL.md +46 -0
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +1 -1
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +45 -16
- 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/PROVENANCE.json +10 -10
- package/framework/standards/STANDARDS.json +1 -1
- package/framework/standards/architecture/code-comments.md +9 -2
- package/framework/standards/frontend/design-system/ai-video-generation.md +2 -0
- package/framework/standards/frontend/scroll-driven/frame-scrub.md +11 -1
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +27 -8
- package/src/commands/mcp/mcp-setup.js +10 -9
- package/src/commands/project/doctor-procs.js +162 -0
- package/src/commands/project/doctor.js +42 -4
- package/src/commands/project/heavy.js +61 -0
- package/src/commands/project/init.js +1 -1
- package/src/commands/project/update.js +4 -0
- package/src/commands/project/worktree-reap.js +34 -0
- package/src/commands/project/worktree.js +78 -27
- package/src/commands/validation/mutate.js +200 -0
- package/src/commands/validation/verify.js +26 -1
- package/src/dashboard/scanner/features-scanner.js +4 -4
- package/src/dashboard/scanner/project-api.js +4 -4
- package/src/lib/ai/code-audit.js +1 -1
- package/src/lib/ai/registry-audit.js +1 -1
- package/src/lib/detectors/claude-config-detector.js +30 -1
- package/src/lib/heavy/cleanup.js +70 -0
- package/src/lib/heavy/gate.js +96 -0
- package/src/lib/installers/mcp-installer.js +15 -2
- package/src/lib/mutation/adapters.js +90 -0
- package/src/lib/mutation/commands.js +60 -0
- package/src/lib/mutation/manifest.js +138 -0
- package/src/lib/mutation/plan.js +36 -0
- package/src/lib/mutation/report.js +66 -0
- package/src/lib/mutation/runner.js +351 -0
- package/src/lib/mutation/schemata.js +60 -0
- package/src/lib/mutation/snapshot.js +69 -0
- package/src/lib/mutation/subset.js +75 -0
- package/src/lib/mutation/trx.js +51 -0
- package/src/lib/procs/classify.js +91 -0
- package/src/lib/procs/list.js +124 -0
- package/src/lib/procs/mcp-config.js +103 -0
- package/src/lib/procs/prune.js +25 -0
- package/src/lib/procs/wslconfig.js +70 -0
- package/src/lib/projects/registry.js +6 -2
- package/src/lib/tasks/dotnet-test-introspection.js +1 -1
- package/src/lib/tasks/linux-runner.js +30 -3
- package/src/lib/tasks/test-runner.js +1 -1
- package/src/lib/validators/code-budget/code-budget-validator.js +4 -6
- package/src/lib/validators/code-budget/index.js +1 -1
- package/src/lib/validators/reuse/symbol-scanner.js +1 -28
- package/src/lib/validators/verify-runner.js +26 -8
- package/src/lib/worktree/agent-reaper.js +247 -0
- package/src/lib/worktree/dirs.js +3 -32
- package/src/lib/worktree/vscode-settings.js +113 -0
- package/src/lib/worktree/worktree-audit.js +49 -5
- package/src/lib/worktree/worktree-include.js +46 -0
- package/src/scripts/setup-infra.js +4 -0
- package/src/utils/hooks-installer.js +14 -6
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { copyFileSync, existsSync, lstatSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { isDisposableBuildArtifact } from './ignored-triage.js';
|
|
5
|
+
|
|
6
|
+
const INCLUDE_FILE = '.worktreeinclude';
|
|
7
|
+
const NESTED_GIT = /(^|\/)\.git(\/|$)/;
|
|
8
|
+
|
|
9
|
+
const gitOut = (cwd, args, input) => execFileSync('git', args, { cwd, stdio: ['pipe', 'pipe', 'ignore'], encoding: 'utf8', input });
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Claude Code's `.worktreeinclude` for a worktree morph-spec creates (a WorktreeCreate hook replaces
|
|
13
|
+
* the native creation, so the native copy never runs): files matching a pattern AND gitignored in the
|
|
14
|
+
* tree are copied when the tree lacks them. Real files only; build artifacts and `node_modules` never.
|
|
15
|
+
*
|
|
16
|
+
* @returns {string[]} relative paths copied
|
|
17
|
+
*/
|
|
18
|
+
export function copyWorktreeIncludes(worktreePath, root) {
|
|
19
|
+
const file = join(root, INCLUDE_FILE);
|
|
20
|
+
if (!existsSync(file)) return [];
|
|
21
|
+
try {
|
|
22
|
+
// No --exclude-standard: with --ignored it would list every gitignored file, not just the pattern matches.
|
|
23
|
+
const matched = gitOut(root, ['ls-files', '--others', '--ignored', '--exclude-from', file, '-z'])
|
|
24
|
+
.split('\0').filter(Boolean).map((p) => p.replace(/\\/g, '/'))
|
|
25
|
+
.filter((p) => !NESTED_GIT.test(p) && !isDisposableBuildArtifact(p));
|
|
26
|
+
if (!matched.length) return [];
|
|
27
|
+
|
|
28
|
+
const ignoredThere = new Set(gitOut(worktreePath, ['check-ignore', '--stdin', '-z'], `${matched.join('\0')}\0`).split('\0').filter(Boolean));
|
|
29
|
+
const copied = [];
|
|
30
|
+
for (const rel of matched) {
|
|
31
|
+
if (!ignoredThere.has(rel)) continue;
|
|
32
|
+
const src = join(root, rel);
|
|
33
|
+
const dst = join(worktreePath, rel);
|
|
34
|
+
try {
|
|
35
|
+
if (!lstatSync(src).isFile()) continue;
|
|
36
|
+
try { lstatSync(dst); continue; } catch { /* absent, and not a dangling link either */ }
|
|
37
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
38
|
+
copyFileSync(src, dst);
|
|
39
|
+
copied.push(rel);
|
|
40
|
+
} catch { /* unreadable or unwritable — leave it out */ }
|
|
41
|
+
}
|
|
42
|
+
return copied;
|
|
43
|
+
} catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ensureGitattributes
|
|
26
26
|
} from '../utils/file-copier.js';
|
|
27
27
|
import { parseStacks, getProjectTags, shouldInstall } from '../lib/stack-filter.js';
|
|
28
|
+
import { applyEditorSettings } from '../lib/worktree/vscode-settings.js';
|
|
28
29
|
import { injectMorphImport } from '../utils/claude-md-injector.js';
|
|
29
30
|
import { saveProjectMorphVersion, getInstalledCLIVersion, getProjectMorphVersion } from '../utils/version-checker.js';
|
|
30
31
|
import { installClaudeHooks, installGlobalStatusline } from '../utils/claude-settings-manager.js';
|
|
@@ -440,6 +441,9 @@ export async function setupInfra(targetPath, {
|
|
|
440
441
|
await updateGitignore(targetPath);
|
|
441
442
|
await ensureGitattributes(targetPath);
|
|
442
443
|
|
|
444
|
+
log('Step 18a: Editor excludes for worktrees...');
|
|
445
|
+
try { applyEditorSettings(targetPath); } catch { /* fail-open */ }
|
|
446
|
+
|
|
443
447
|
// --- 18b. Codebase graph (graphify) ---
|
|
444
448
|
// Fail-open por inteiro (ADR-002): sem Python, sem uv e sem pipx, o step
|
|
445
449
|
// registra e segue. O wrapper de CLI mata o processo em qualquer throw
|
|
@@ -52,8 +52,11 @@ import { realEffects } from '../lib/installers/effects.js';
|
|
|
52
52
|
* 3.11.0 writes every `timeout` in seconds, the unit Claude Code reads: the
|
|
53
53
|
* values were milliseconds, so a hung hook held the session for hours (120000
|
|
54
54
|
* on WorktreeCreate is 33 h) instead of the seconds they meant.
|
|
55
|
+
*
|
|
56
|
+
* 3.12.0 adds heavy-gate to the Bash PreToolUse chain and heavy-release to the
|
|
57
|
+
* PostToolUse and PostToolUseFailure chains: the opt-in `heavy.gateBash`.
|
|
55
58
|
*/
|
|
56
|
-
const HOOKS_VERSION = '3.
|
|
59
|
+
const HOOKS_VERSION = '3.12.0';
|
|
57
60
|
|
|
58
61
|
/** Marker for old dispatch.js (v1) */
|
|
59
62
|
const OLD_DISPATCH_COMMAND = 'node framework/hooks/agent-teams/dispatch.js';
|
|
@@ -165,6 +168,8 @@ const MORPH_HOOKS = [
|
|
|
165
168
|
// on someone having read MORPH.md. block-raw-worktree-add is its way-IN
|
|
166
169
|
// counterpart (a raw `git worktree add` builds a tree with no junctions, no
|
|
167
170
|
// ports, no identity) — static, so it costs nothing after the first two.
|
|
171
|
+
// heavy-gate comes after every guard — it takes a slot, and a command a guard
|
|
172
|
+
// blocks must not hold one — and before the rewriter.
|
|
168
173
|
// worktree-env-inject is LAST: it rewrites launcher commands (updatedInput)
|
|
169
174
|
// with the worktree's port block, and a command a previous link blocked must
|
|
170
175
|
// never be rewritten. Block-first-wins guarantees it never sees one.
|
|
@@ -174,7 +179,7 @@ const MORPH_HOOKS = [
|
|
|
174
179
|
hooks: [{
|
|
175
180
|
type: 'command',
|
|
176
181
|
command: 'node framework/hooks/claude-code/core/chain.js',
|
|
177
|
-
args: ['pre-bash-denylist', 'block-destructive-worktree-removal', 'block-raw-worktree-add', 'worktree-env-inject']
|
|
182
|
+
args: ['pre-bash-denylist', 'block-destructive-worktree-removal', 'block-raw-worktree-add', 'heavy-gate', 'worktree-env-inject']
|
|
178
183
|
}]
|
|
179
184
|
},
|
|
180
185
|
|
|
@@ -216,14 +221,15 @@ const MORPH_HOOKS = [
|
|
|
216
221
|
// order as before. post-edit-typecheck declared no timeout of its own (it
|
|
217
222
|
// can legitimately spend up to its internal TSC_TIMEOUT_MS=30000 running
|
|
218
223
|
// `npx tsc --noEmit`), so the chain declares none rather than under-
|
|
219
|
-
// provisioning it with just the sum of the other two links' 3000ms each.
|
|
224
|
+
// provisioning it with just the sum of the other two links' 3000ms each.
|
|
225
|
+
// comment-guard is LAST: it blocks, and a block ends the chain. ===
|
|
220
226
|
{
|
|
221
227
|
event: 'PostToolUse',
|
|
222
228
|
matcher: 'Write|Edit',
|
|
223
229
|
hooks: [{
|
|
224
230
|
type: 'command',
|
|
225
231
|
command: 'node framework/hooks/claude-code/core/chain.js',
|
|
226
|
-
args: ['post-edit-typecheck', 'tasks-json-guard', 'trace-autogen']
|
|
232
|
+
args: ['post-edit-typecheck', 'tasks-json-guard', 'trace-autogen', 'comment-guard']
|
|
227
233
|
}]
|
|
228
234
|
},
|
|
229
235
|
|
|
@@ -263,19 +269,21 @@ const MORPH_HOOKS = [
|
|
|
263
269
|
hooks: [{
|
|
264
270
|
type: 'command',
|
|
265
271
|
command: 'node framework/hooks/claude-code/core/chain.js',
|
|
266
|
-
args: ['telemetry-log', 'loop-detect', 'graph-refresh-kick'],
|
|
272
|
+
args: ['telemetry-log', 'loop-detect', 'graph-refresh-kick', 'heavy-release'],
|
|
267
273
|
timeout: 10
|
|
268
274
|
}]
|
|
269
275
|
},
|
|
270
276
|
|
|
271
277
|
// === PostToolUseFailure: All — telemetry of the failed call (exit code,
|
|
272
278
|
// duration). loop-detect stays out: its warning is shaped for PostToolUse.
|
|
279
|
+
// heavy-release gives back the slot of a heavy Bash call that failed.
|
|
273
280
|
{
|
|
274
281
|
event: 'PostToolUseFailure',
|
|
275
282
|
matcher: null,
|
|
276
283
|
hooks: [{
|
|
277
284
|
type: 'command',
|
|
278
|
-
command: 'node framework/hooks/claude-code/core/
|
|
285
|
+
command: 'node framework/hooks/claude-code/core/chain.js',
|
|
286
|
+
args: ['telemetry-log', 'heavy-release'],
|
|
279
287
|
timeout: 5,
|
|
280
288
|
async: true
|
|
281
289
|
}]
|