@polymorphism-tech/morph-spec 8.47.0 → 9.0.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 +48 -39
- package/README.md +3 -4
- package/bin/morph-spec.js +37 -51
- package/bin/validate.js +3 -111
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +41 -101
- package/framework/MORPH.md +95 -252
- package/framework/agents.json +75 -18
- package/framework/commands/morph-apply.md +5 -28
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-hotfix.md +8 -8
- package/framework/commands/morph-infra.md +1 -1
- package/framework/commands/morph-preflight.md +2 -3
- package/framework/commands/morph-proposal.md +2 -50
- package/framework/commands/morph-status.md +3 -3
- package/framework/docs/CLI.md +585 -286
- package/framework/evals/review-checklist.md +82 -41
- package/framework/hooks/README.md +10 -11
- package/framework/hooks/claude-code/core/comment-guard.js +1 -1
- package/framework/hooks/claude-code/core/denylist.json +33 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +16 -20
- package/framework/hooks/claude-code/core/gate-guard.js +2 -11
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +38 -0
- package/framework/hooks/claude-code/core/protect-spec-files.js +30 -242
- package/framework/hooks/claude-code/core/state-sync.js +7 -21
- package/framework/hooks/claude-code/core/telemetry-log.js +3 -3
- package/framework/hooks/claude-code/core/validate-completion.js +33 -97
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +31 -0
- package/framework/hooks/claude-code/core/worktree-context.js +5 -4
- package/framework/hooks/claude-code/statusline.py +55 -41
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/shared/activity-logger.js +1 -1
- package/framework/hooks/shared/build-check.js +10 -6
- package/framework/hooks/shared/command-tokens.js +169 -0
- package/framework/hooks/shared/comment-rules.js +1 -1
- package/framework/hooks/shared/comment-scanner.js +10 -23
- package/framework/hooks/shared/comment-stripper.js +1 -1
- package/framework/hooks/shared/e2e-check.js +64 -27
- package/framework/hooks/shared/errata.js +72 -0
- package/framework/hooks/shared/feature-locator.js +1 -1
- package/framework/hooks/shared/frontend-locations.js +6 -0
- package/framework/hooks/shared/gate-question.js +18 -0
- package/framework/hooks/shared/phase-utils.js +15 -32
- package/framework/hooks/shared/slice-progress.js +118 -0
- package/framework/hooks/shared/spawn-command.js +23 -0
- package/framework/hooks/shared/state-reader.js +61 -87
- package/framework/hooks/shared/state-writer.js +2 -3
- package/framework/mcp/registry.json +3 -4
- package/framework/phases.json +23 -39
- package/framework/schemas/config.schema.json +14 -9
- package/framework/schemas/feature.schema.json +15 -50
- package/framework/skills/README.md +3 -4
- 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 +149 -222
- package/framework/skills/core/morph-hotfix/SKILL.md +33 -42
- package/framework/skills/core/morph-machine/SKILL.md +2 -2
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +137 -299
- package/framework/skills/core/morph-review/SKILL.md +111 -136
- package/framework/skills/core/morph-standards/SKILL.md +27 -39
- package/framework/skills/core/morph-uiux/SKILL.md +77 -152
- package/framework/standards/STANDARDS.json +86 -1218
- package/framework/standards/STANDARDS.meta.json +1305 -0
- package/framework/standards/ai-agents/evals-with-cache.md +1 -2
- package/framework/standards/ai-agents/setup.md +1 -1
- package/framework/standards/architecture/code-comments.md +6 -6
- package/framework/standards/integration/mcp/mcp-tools.md +7 -7
- package/framework/templates/README.md +2 -3
- package/framework/templates/REGISTRY.json +6 -170
- package/framework/templates/docs/plan.md +72 -0
- package/framework/templates/dotnet/ai-kit/README.md +1 -9
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +2 -2
- package/src/commands/observability/cost.js +18 -60
- package/src/commands/project/doctor-procs.js +1 -1
- package/src/commands/project/doctor.js +9 -9
- package/src/commands/project/fleet.js +4 -4
- package/src/commands/project/heavy.js +3 -3
- package/src/commands/project/init.js +4 -0
- package/src/commands/project/setup-infra-cmd.js +2 -1
- package/src/commands/project/stack-scan.js +58 -0
- package/src/commands/project/standards.js +79 -25
- package/src/commands/project/status.js +29 -69
- package/src/commands/project/update.js +17 -1
- package/src/commands/project/worktree.js +1 -1
- package/src/commands/state/advance.js +62 -46
- package/src/commands/state/approve.js +81 -141
- package/src/commands/state/archive.js +20 -84
- package/src/commands/state/auto-approval.js +68 -0
- package/src/commands/state/create.js +28 -1
- package/src/commands/state/delete.js +1 -1
- package/src/commands/state/finish.js +11 -23
- package/src/commands/state/gate-check.js +85 -84
- package/src/commands/state/gate-decision.js +6 -4
- package/src/commands/state/handoff.js +1 -1
- package/src/commands/state/list.js +9 -9
- package/src/commands/state/report-check.js +157 -311
- package/src/commands/state/retype.js +9 -3
- package/src/commands/validation/mutate.js +77 -14
- package/src/commands/validation/plan-check.js +81 -0
- package/src/commands/validation/validate-feature.js +60 -135
- package/src/commands/validation/verify.js +40 -72
- package/src/core/paths/output-schema.js +19 -66
- package/src/core/state/gate-order.js +5 -6
- package/src/core/state/lifecycle-audit.js +2 -2
- package/src/core/state/state-manager.js +17 -98
- package/src/core/templates/template-registry.js +2 -2
- package/src/core/templates/template-seed.js +22 -0
- package/src/core/work-types.js +10 -10
- package/src/dashboard/app/components/ActivityFeed.jsx +2 -3
- package/src/dashboard/app/components/CommandPalette.jsx +5 -5
- package/src/dashboard/app/components/EntityLink.jsx +1 -1
- package/src/dashboard/app/hooks/useMorphQuery.js +1 -1
- package/src/dashboard/app/lib/phases.js +2 -4
- package/src/dashboard/app/pages/Activity.jsx +1 -1
- package/src/dashboard/app/pages/FeatureDetail.jsx +139 -129
- package/src/dashboard/app/pages/Features.jsx +9 -9
- package/src/dashboard/app/pages/Guide.jsx +2 -2
- package/src/dashboard/app/pages/PhasePipeline.jsx +3 -4
- package/src/dashboard/app/pages/Standards.jsx +1 -1
- package/src/dashboard/scanner/activity-scanner.js +5 -15
- package/src/dashboard/scanner/agents-scanner.js +1 -1
- package/src/dashboard/scanner/docs-scanner.js +2 -2
- package/src/dashboard/scanner/features-scanner.js +95 -60
- package/src/dashboard/scanner/project-api.js +1 -1
- package/src/dashboard/scanner/standards-scanner.js +2 -1
- package/src/lib/ci/ci-verify.js +17 -1
- package/src/lib/ci/github-ci.js +1 -1
- package/src/lib/detectors/index.js +3 -8
- package/src/lib/generators/handoff-generator.js +34 -65
- package/src/lib/generators/settings-generator.js +11 -89
- package/src/lib/git/evidence-staleness.js +1 -1
- package/src/lib/git/tree-fingerprint.js +19 -7
- package/src/lib/git/tree-state.js +2 -2
- package/src/lib/heavy/cleanup.js +1 -5
- package/src/lib/installers/memory-installer.js +6 -8
- package/src/lib/mutation/commands.js +3 -2
- package/src/lib/{tasks/dotnet-test-introspection.js → mutation/dotnet-introspection.js} +17 -282
- package/src/lib/mutation/plan.js +14 -6
- package/src/lib/mutation/runner.js +1 -1
- package/src/lib/mutation/subset.js +46 -9
- package/src/lib/plan/artifact-vocabulary.js +60 -0
- package/src/lib/plan/checks.js +234 -0
- package/src/lib/plan/plan-parser.js +209 -0
- package/src/lib/plan/plan-template.js +18 -0
- package/src/lib/review-reports.js +222 -0
- package/src/lib/risk-detector.js +131 -140
- package/src/lib/specs/adr-index.js +50 -69
- package/src/lib/specs/design-seed.js +18 -0
- package/src/lib/specs/frontmatter.js +44 -0
- package/src/lib/specs/gfm-table.js +17 -0
- package/src/lib/specs/old-format.js +68 -0
- package/src/lib/specs/revocations.js +37 -95
- package/src/lib/specs/screen-checklist.js +18 -17
- package/src/lib/stack/dotnet-build-ignores.js +47 -0
- package/src/lib/stack/stack-scan.js +267 -0
- package/src/lib/standards/registry.js +43 -0
- package/src/lib/standards/sections.js +58 -0
- package/src/lib/tasks/eval-node.js +4 -12
- package/src/lib/tasks/test-nodes.js +1 -74
- package/src/lib/tasks/test-runner.js +75 -117
- package/src/lib/telemetry/metrics.js +8 -69
- package/src/lib/telemetry/telemetry-reader.js +5 -118
- package/src/lib/telemetry/verify-event.js +5 -7
- package/src/lib/validators/code-budget/code-budget-validator.js +1 -1
- package/src/lib/validators/contracts/contract-compliance-validator.js +2 -2
- package/src/lib/validators/reuse/reuse-validator.js +22 -45
- package/src/lib/validators/traceability-check.js +85 -129
- package/src/lib/validators/verify-runner.js +118 -235
- package/src/lib/worktree/docker-audit.js +1 -2
- package/src/lib/worktree/fleet-scanner.js +25 -38
- package/src/scripts/setup-infra.js +9 -0
- package/src/utils/agents-installer.js +76 -9
- package/src/utils/claude-settings-manager.js +0 -35
- package/src/utils/file-copier.js +27 -1
- package/src/utils/hooks-installer.js +16 -9
- package/src/utils/skills-installer.js +1 -2
- package/framework/evals/trace-schema.md +0 -67
- package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
- package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
- package/framework/hooks/git/pre-commit/specs.sh +0 -50
- package/framework/hooks/shared/tasks-validator.js +0 -111
- package/framework/rules/morph-task-tracking.md +0 -54
- package/framework/rules/morph-workflow.md +0 -244
- package/framework/schemas/tasks.schema.json +0 -79
- package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
- package/framework/skills/core/morph-implement/SKILL.md +0 -194
- package/framework/skills/core/morph-proposal/SKILL.md +0 -152
- package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
- package/framework/templates/docs/proposal.md +0 -192
- package/framework/templates/docs/spec.md +0 -57
- package/framework/templates/docs/ui-components.md +0 -52
- package/framework/templates/docs/ui-design-system.md +0 -76
- package/framework/templates/docs/ui-flows.md +0 -167
- package/framework/templates/examples/spec-examples.md +0 -91
- package/framework/templates/feature/decisions.md +0 -124
- package/framework/templates/feature/recap.md +0 -145
- package/framework/templates/tasks.template.json +0 -17
- package/src/commands/state/usecase.js +0 -143
- package/src/commands/tasks/dag.js +0 -181
- package/src/lib/agents/output-collector.js +0 -76
- package/src/lib/evaluator-report.js +0 -104
- package/src/lib/specs/acervo-format.js +0 -70
- package/src/lib/specs/acervo-lifecycle.js +0 -264
- package/src/lib/specs/done-criteria-check.js +0 -200
- package/src/lib/specs/usecase-check.js +0 -301
- package/src/lib/specs/usecase-promoter.js +0 -301
- package/src/lib/specs/usecase-registry.js +0 -237
- package/src/lib/tasks/dispatch-planner.js +0 -319
- package/src/lib/tasks/mermaid-renderer.js +0 -132
- package/src/lib/tasks/task-classifier.js +0 -30
- package/src/lib/tasks/task-parser.js +0 -209
- package/src/lib/tasks/tasks-json-parser.js +0 -296
- package/src/lib/tasks/test-scope.js +0 -597
|
@@ -23,25 +23,12 @@ export async function generateSettings(targetPath, detectedConfig, morphConfig =
|
|
|
23
23
|
const claudeDir = join(targetPath, '.claude');
|
|
24
24
|
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const existing = await readSettingsSafe(settingsPath);
|
|
28
|
-
|
|
29
|
-
// Build stack-based permissions
|
|
30
|
-
const stack = morphConfig?.project?.architecture || 'unknown';
|
|
31
|
-
const permissions = buildPermissions(stack, detectedConfig);
|
|
32
|
-
|
|
33
|
-
// Build generated settings
|
|
26
|
+
const existing = withoutLegacyPermissions(await readSettingsSafe(settingsPath));
|
|
34
27
|
const generated = {};
|
|
35
28
|
|
|
36
|
-
if (permissions.length > 0) {
|
|
37
|
-
generated.permissions = permissions;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Track what we manage
|
|
41
29
|
const managed = {
|
|
42
|
-
permissions_added: permissions,
|
|
43
30
|
mcps_detected: detectedConfig.mcpServers.map(s => s.name),
|
|
44
|
-
plugins_detected: detectedConfig.plugins.map(p => p
|
|
31
|
+
plugins_detected: detectedConfig.plugins.map(p => (typeof p === 'string' ? p : p?.name)),
|
|
45
32
|
generated_at: new Date().toISOString()
|
|
46
33
|
};
|
|
47
34
|
|
|
@@ -58,44 +45,10 @@ export async function generateSettings(targetPath, detectedConfig, morphConfig =
|
|
|
58
45
|
|
|
59
46
|
return {
|
|
60
47
|
settingsPath,
|
|
61
|
-
permissionsAdded: permissions.length,
|
|
62
48
|
managed
|
|
63
49
|
};
|
|
64
50
|
}
|
|
65
51
|
|
|
66
|
-
/**
|
|
67
|
-
* Build permission rules based on detected stack
|
|
68
|
-
* @param {string} stack - Detected project stack
|
|
69
|
-
* @param {Object} detectedConfig - Detected Claude config
|
|
70
|
-
* @returns {Array<string>} Permission patterns
|
|
71
|
-
*/
|
|
72
|
-
export function buildPermissions(stack, detectedConfig = {}) {
|
|
73
|
-
const permissions = [];
|
|
74
|
-
|
|
75
|
-
// Stack-based permissions
|
|
76
|
-
const stackPermissions = {
|
|
77
|
-
nodejs: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
|
|
78
|
-
typescript: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)', 'Bash(tsc:*)'],
|
|
79
|
-
nextjs: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
|
|
80
|
-
react: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
|
|
81
|
-
vue: ['Bash(node:*)', 'Bash(npm:*)', 'Bash(npx:*)'],
|
|
82
|
-
dotnet: ['Bash(dotnet:*)', 'Bash(nuget:*)'],
|
|
83
|
-
python: ['Bash(python:*)', 'Bash(pip:*)', 'Bash(pytest:*)'],
|
|
84
|
-
go: ['Bash(go:*)']
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
if (stackPermissions[stack]) {
|
|
88
|
-
permissions.push(...stackPermissions[stack]);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// morph-spec CLI always needs node/npx
|
|
92
|
-
if (!permissions.includes('Bash(npx:*)')) {
|
|
93
|
-
permissions.push('Bash(npx:*)');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return permissions;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
52
|
/**
|
|
100
53
|
* Deep merge settings without overwriting user entries
|
|
101
54
|
* @param {Object} existing - Current settings.local.json
|
|
@@ -127,46 +80,6 @@ export function mergeSettings(existing, generated) {
|
|
|
127
80
|
return result;
|
|
128
81
|
}
|
|
129
82
|
|
|
130
|
-
/**
|
|
131
|
-
* Remove only morph-spec managed entries from settings
|
|
132
|
-
* @param {string} settingsPath - Path to settings.local.json
|
|
133
|
-
* @returns {Promise<Object>} Summary of what was removed
|
|
134
|
-
*/
|
|
135
|
-
export async function resetMorphSettings(settingsPath) {
|
|
136
|
-
if (!existsSync(settingsPath)) {
|
|
137
|
-
return { removed: false, reason: 'file not found' };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const settings = await readSettingsSafe(settingsPath);
|
|
141
|
-
const managed = settings[MORPH_MANAGED_KEY];
|
|
142
|
-
|
|
143
|
-
if (!managed) {
|
|
144
|
-
return { removed: false, reason: 'no _morph_managed section found' };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Remove managed permissions
|
|
148
|
-
if (managed.permissions_added && Array.isArray(settings.permissions)) {
|
|
149
|
-
settings.permissions = settings.permissions.filter(
|
|
150
|
-
p => !managed.permissions_added.includes(p)
|
|
151
|
-
);
|
|
152
|
-
if (settings.permissions.length === 0) {
|
|
153
|
-
delete settings.permissions;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Remove the managed marker itself
|
|
158
|
-
delete settings[MORPH_MANAGED_KEY];
|
|
159
|
-
|
|
160
|
-
// Write back
|
|
161
|
-
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
removed: true,
|
|
165
|
-
permissionsRemoved: managed.permissions_added || [],
|
|
166
|
-
previouslyGenerated: managed.generated_at
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
83
|
/**
|
|
171
84
|
* Save integrations.json with detected config
|
|
172
85
|
* @param {string} targetPath - Project root directory
|
|
@@ -198,6 +111,15 @@ export async function saveIntegrations(targetPath, detectedConfig) {
|
|
|
198
111
|
// Helpers
|
|
199
112
|
// ============================================================================
|
|
200
113
|
|
|
114
|
+
// Claude Code reads only `permissions: { allow, deny }`; a bare array (older generator) is ignored.
|
|
115
|
+
// Versões antigas gravavam regras curinga (node:*, npm:*, npx:*…) como array, forma que o
|
|
116
|
+
// Claude Code ignora: nunca valeram. Converter para { allow } as ligaria em silêncio.
|
|
117
|
+
function withoutLegacyPermissions(settings) {
|
|
118
|
+
if (!Array.isArray(settings.permissions)) return settings;
|
|
119
|
+
const { permissions, ...rest } = settings;
|
|
120
|
+
return rest;
|
|
121
|
+
}
|
|
122
|
+
|
|
201
123
|
async function readSettingsSafe(settingsPath) {
|
|
202
124
|
try {
|
|
203
125
|
if (!existsSync(settingsPath)) return {};
|
|
@@ -7,7 +7,7 @@ const CONFIG_PATH = '.morph/config/config.json';
|
|
|
7
7
|
|
|
8
8
|
const gitOut = (cwd, args) => execFileSync('git', args, { cwd, stdio: 'pipe', maxBuffer: 64 * 1024 * 1024 }).toString();
|
|
9
9
|
|
|
10
|
-
function withoutBaseline(text) {
|
|
10
|
+
export function withoutBaseline(text) {
|
|
11
11
|
const config = JSON.parse(text);
|
|
12
12
|
if (Array.isArray(config?.project?.tests)) {
|
|
13
13
|
for (const node of config.project.tests) delete node?.expectedCount;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A hash of what a verify run reads: the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* runs over the same code look different.
|
|
2
|
+
* A hash of what a verify run reads: the committed tree, the uncommitted changes and the
|
|
3
|
+
* untracked files, plus `config.json` without `expectedCount` (it names the test commands).
|
|
4
|
+
* The rest of `.morph/` stays out, as in `treeMovedSince`: committing verify's own
|
|
5
|
+
* bookkeeping must not make the same code look different.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
import { execFileSync } from 'child_process';
|
|
10
9
|
import { createHash } from 'crypto';
|
|
11
10
|
import { existsSync, readFileSync, statSync } from 'fs';
|
|
12
11
|
import { join } from 'path';
|
|
12
|
+
import { withoutBaseline } from './evidence-staleness.js';
|
|
13
13
|
|
|
14
14
|
/** Pathspec for "the project minus its `.morph/` bookkeeping". */
|
|
15
15
|
export const OUTSIDE_MORPH = ['--', '.', ':(exclude).morph'];
|
|
@@ -31,7 +31,11 @@ export function treeFingerprint(projectPath) {
|
|
|
31
31
|
const hash = createHash('sha256');
|
|
32
32
|
let head = null;
|
|
33
33
|
try { head = git(projectPath, ['rev-parse', 'HEAD']).toString().trim(); } catch { /* no commit yet */ }
|
|
34
|
-
|
|
34
|
+
// Tree ids are content-addressed: the top-level entries minus .morph change only with code.
|
|
35
|
+
const tree = head
|
|
36
|
+
? git(projectPath, ['ls-tree', '-z', 'HEAD']).toString().split('\0').filter((e) => e && e.split('\t')[1] !== '.morph')
|
|
37
|
+
: ['no-commit'];
|
|
38
|
+
hash.update(`tree\0${tree.join('\0')}\0`);
|
|
35
39
|
// Before the first commit there is no HEAD to diff against: every file is
|
|
36
40
|
// untracked, and the listing below covers them.
|
|
37
41
|
if (head) hash.update(git(projectPath, ['diff', 'HEAD', '--binary', ...OUTSIDE_MORPH]));
|
|
@@ -50,9 +54,17 @@ export function treeFingerprint(projectPath) {
|
|
|
50
54
|
}
|
|
51
55
|
const config = join(projectPath, '.morph', 'config', 'config.json');
|
|
52
56
|
hash.update('\0config\0');
|
|
53
|
-
if (existsSync(config)) hash.update(readFileSync(config));
|
|
57
|
+
if (existsSync(config)) hash.update(normalizedConfig(readFileSync(config, 'utf8')));
|
|
54
58
|
return hash.digest('hex');
|
|
55
59
|
} catch {
|
|
56
60
|
return null;
|
|
57
61
|
}
|
|
58
62
|
}
|
|
63
|
+
|
|
64
|
+
function normalizedConfig(text) {
|
|
65
|
+
try {
|
|
66
|
+
return JSON.stringify(withoutBaseline(text));
|
|
67
|
+
} catch {
|
|
68
|
+
return text;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -11,7 +11,7 @@ import { OUTSIDE_MORPH, treeFingerprint, git as gitBuffer } from './tree-fingerp
|
|
|
11
11
|
import { detectDefaultBranch } from './default-branch.js';
|
|
12
12
|
import { resolveBaseRef } from './branch-classifier.js';
|
|
13
13
|
|
|
14
|
-
/** What
|
|
14
|
+
/** What the verifier writes next to a mutation it has not reverted yet. */
|
|
15
15
|
export const MUTATION_MARKER = 'MUTACAO';
|
|
16
16
|
const MAX_LISTED = 50;
|
|
17
17
|
const MAX_COMMITS = 10;
|
|
@@ -50,7 +50,7 @@ function commitBlobs(cwd, commit, paths) {
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* What the tree is before a dispatch whose work must leave it unchanged (the
|
|
53
|
-
*
|
|
53
|
+
* verifier mutates and reverts): HEAD plus the blob of every file that
|
|
54
54
|
* differs from it. Kept on disk, so a session that resumes after the agent
|
|
55
55
|
* died compares against the tree before the dispatch, not its own start.
|
|
56
56
|
* @returns {{ at: string, head: string|null, files: Object<string, string|null> }|null}
|
package/src/lib/heavy/cleanup.js
CHANGED
|
@@ -6,7 +6,6 @@ import { heavyDir, runExclusive } from '../../../framework/hooks/shared/heavy-sl
|
|
|
6
6
|
|
|
7
7
|
const DOTNET_ACTIVE = /\bdotnet(?:\.exe)?["']?\s+(?:build|test|publish|pack|msbuild|restore|run|watch|vstest)\b/i;
|
|
8
8
|
const IDLE_WORKER = /\/nodemode:\d|vbcscompiler|razorserver/i;
|
|
9
|
-
const SHUTDOWN_SCOPES = new Set(['feature', 'e2e-down', 'prune']);
|
|
10
9
|
const SHUTDOWN_TIMEOUT_MS = 30_000;
|
|
11
10
|
const TAIL_CHARS = 400;
|
|
12
11
|
|
|
@@ -33,16 +32,13 @@ export function dotnetBusy(procs) {
|
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
export function afterHeavyRun({ projectPath, config,
|
|
35
|
+
export function afterHeavyRun({ projectPath, config, env = process.env, deps = {} }) {
|
|
37
36
|
const {
|
|
38
37
|
exec = defaultProcExec, list = listProcesses, dotnet = hasDotnet, exclusive = runExclusive,
|
|
39
38
|
} = deps;
|
|
40
39
|
|
|
41
40
|
if (!config.enabled) return { status: 'skipped', reason: 'semáforo desligado: sem ele nada prova que outra sessão não está compilando' };
|
|
42
41
|
if (!config.shutdownBuildServer) return { status: 'skipped', reason: 'desligado em heavy.shutdownBuildServer' };
|
|
43
|
-
if (!SHUTDOWN_SCOPES.has(scope)) {
|
|
44
|
-
return { status: 'skipped', reason: 'escopo de task: o servidor de compilação segue quente para a próxima task' };
|
|
45
|
-
}
|
|
46
42
|
if (!dotnet(projectPath)) return { status: 'skipped', reason: 'projeto sem .NET' };
|
|
47
43
|
|
|
48
44
|
const guarded = exclusive({
|
|
@@ -41,8 +41,7 @@ metadata:
|
|
|
41
41
|
- \`.morph/framework/MORPH.md\` — NLH charter (read once per session)
|
|
42
42
|
- \`.morph/framework/agents.json\` — 8 agents: 7 domain personas + 1 stage persona (\`scout\`, read-only)
|
|
43
43
|
- \`.morph/framework/standards/STANDARDS.json\` — standards index (load on demand)
|
|
44
|
-
- \`.morph/
|
|
45
|
-
- \`.morph/features/{feature}/\` — feature artifacts: 0-proposal / 1-design / 2-plan / 3-implement / 4-review
|
|
44
|
+
- \`.morph/features/{feature}/\` — feature artifacts: 2-plan / 1-design / 3-implement / 4-review
|
|
46
45
|
- \`.morph/context/\` — long-lived architectural context (design-system, decisions)
|
|
47
46
|
- \`.morph/state.json\` — feature state (managed by state-sync hook; Edit fallback allowed)
|
|
48
47
|
|
|
@@ -50,8 +49,8 @@ metadata:
|
|
|
50
49
|
|
|
51
50
|
| Command | Skill invoked |
|
|
52
51
|
|---------|---------------|
|
|
53
|
-
| \`/morph-proposal {feature}\` | \`Skill(morph-
|
|
54
|
-
| \`/morph-apply {feature}\` | \`Skill(morph-apply)\` —
|
|
52
|
+
| \`/morph-proposal {feature}\` | \`Skill(morph-plan)\` — entrevista → plan.md → plan-check → gate do plano |
|
|
53
|
+
| \`/morph-apply {feature}\` | \`Skill(morph-apply)\` — fatias do plano → verify → review → Gate 3 |
|
|
55
54
|
| \`/morph-status [feature]\` | inspect state.json |
|
|
56
55
|
| \`/morph-archive {feature}\` | move completed feature to .morph/archive/ |
|
|
57
56
|
| \`/morph-preflight\` | pre-deploy validation |
|
|
@@ -59,13 +58,13 @@ metadata:
|
|
|
59
58
|
|
|
60
59
|
## Core skills
|
|
61
60
|
|
|
62
|
-
\`morph-
|
|
61
|
+
\`morph-plan\`, \`morph-apply\`, \`morph-uiux\`, \`morph-review\`, \`morph-hotfix\`, \`morph-standards\`
|
|
63
62
|
|
|
64
63
|
**Why:** This project is managed by morph-spec — spec-driven autonomous development with trust-aware gates.
|
|
65
64
|
|
|
66
65
|
**How to apply:**
|
|
67
66
|
- When user mentions a feature, check \`.morph/features/\` first.
|
|
68
|
-
- When user types \`/morph-proposal\`, invoke \`Skill(morph-
|
|
67
|
+
- When user types \`/morph-proposal\`, invoke \`Skill(morph-plan)\` directly.
|
|
69
68
|
- In \`trust: "auto"\`, gates auto-pass; only AskUserQuestion on risk signals.
|
|
70
69
|
`;
|
|
71
70
|
}
|
|
@@ -83,10 +82,9 @@ metadata:
|
|
|
83
82
|
- \`.morph/context/design-system.md\` — design tokens and components (source of truth)
|
|
84
83
|
- \`.morph/framework/MORPH.md\` — NLH charter, Trust Mode rules, gates, skills table
|
|
85
84
|
- \`.morph/framework/standards/STANDARDS.json\` — index; load specific standard via \`path\` field
|
|
86
|
-
- \`.morph/framework/schemas/tasks.schema.json\` — tasks.json schema reference
|
|
87
85
|
- \`.morph/framework/phases.json\` — phase folder mapping and skill associations
|
|
88
86
|
- \`.morph/framework/agents.json\` — domain persona definitions (dotnet-senior, ef-modeler, etc.)
|
|
89
|
-
- \`.morph/framework/evals/review-checklist.md\` — what the Gate 3
|
|
87
|
+
- \`.morph/framework/evals/review-checklist.md\` — what the Gate 3 verifier, reviewer and security check (verdict SHIP/FIX + evidence-typed blockers)
|
|
90
88
|
`;
|
|
91
89
|
|
|
92
90
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { discoverDotnetBuildTargets, dotnetBuildCommandFor } from '../tasks/test-runner.js';
|
|
2
3
|
|
|
3
4
|
const FILTER = /--filter(?:[ =:])(?:"([^"]*)"|'([^']*)'|(\S+))/;
|
|
4
5
|
const quote = (s) => `"${String(s).replace(/"/g, '\\"')}"`;
|
|
@@ -32,7 +33,7 @@ const VERBOSITY = /\s(?:-v|--verbosity)[ =:]?\S+/g;
|
|
|
32
33
|
export function dotnetBuildCommands(node, projectPath) {
|
|
33
34
|
const configuration = CONFIGURATION.exec(node.command ?? '');
|
|
34
35
|
const flag = configuration ? ` -c ${configuration[1] ?? configuration[2]}` : '';
|
|
35
|
-
return
|
|
36
|
+
return discoverDotnetBuildTargets(node, resolve(projectPath || '.', node.cwd || '.'))
|
|
36
37
|
.map((target) => dotnetBuildCommandFor(target, projectPath))
|
|
37
38
|
.filter(Boolean)
|
|
38
39
|
.map((command) => `${command.replace(VERBOSITY, '')} -v m${flag}`);
|