@polymorphism-tech/morph-spec 9.0.0 → 9.1.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 +8 -9
- package/README.md +38 -36
- package/bin/morph-spec.js +4 -62
- package/bin/validate.js +1 -39
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +1 -1
- package/framework/MORPH.md +1 -1
- package/framework/agents.json +12 -4
- package/framework/commands/morph-apply.md +1 -1
- package/framework/commands/morph-status.md +1 -1
- package/framework/docs/CLI.md +6 -17
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
- package/framework/hooks/claude-code/core/chain.js +4 -65
- package/framework/hooks/claude-code/core/comment-guard.js +2 -16
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +6 -50
- package/framework/hooks/claude-code/core/gate-guard.js +7 -67
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
- package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
- package/framework/hooks/claude-code/core/heavy-release.js +2 -13
- package/framework/hooks/claude-code/core/loop-detect.js +2 -31
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +0 -4
- package/framework/hooks/claude-code/core/protect-spec-files.js +7 -67
- package/framework/hooks/claude-code/core/state-sync.js +11 -67
- package/framework/hooks/claude-code/core/telemetry-log.js +12 -93
- package/framework/hooks/claude-code/core/validate-completion.js +11 -57
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +1 -9
- package/framework/hooks/claude-code/core/worktree-context.js +10 -110
- package/framework/hooks/claude-code/core/worktree-create.js +6 -70
- package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
- package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
- package/framework/hooks/shared/activity-logger.js +9 -89
- package/framework/hooks/shared/agent-reap.js +2 -17
- package/framework/hooks/shared/build-check.js +6 -75
- package/framework/hooks/shared/claim-registry.js +9 -119
- package/framework/hooks/shared/command-tokens.js +6 -51
- package/framework/hooks/shared/comment-rules.js +5 -20
- package/framework/hooks/shared/comment-scanner.js +6 -25
- package/framework/hooks/shared/comment-stripper.js +11 -85
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/errata.js +2 -15
- package/framework/hooks/shared/feature-locator.js +11 -95
- package/framework/hooks/shared/frontend-locations.js +1 -3
- package/framework/hooks/shared/gate-question.js +1 -7
- package/framework/hooks/shared/git-exclude.js +3 -20
- package/framework/hooks/shared/git-paths.js +8 -104
- package/framework/hooks/shared/graph-freshness.js +22 -166
- package/framework/hooks/shared/graph-refresh.js +21 -149
- package/framework/hooks/shared/heavy-command.js +4 -12
- package/framework/hooks/shared/hook-response.js +8 -83
- package/framework/hooks/shared/morph-cli.js +8 -52
- package/framework/hooks/shared/payload-utils.js +10 -132
- package/framework/hooks/shared/phase-utils.js +1 -42
- package/framework/hooks/shared/redact-secrets.js +4 -15
- package/framework/hooks/shared/reparse-scan.js +6 -66
- package/framework/hooks/shared/slice-progress.js +4 -23
- package/framework/hooks/shared/source-files.js +4 -17
- package/framework/hooks/shared/state-reader.js +13 -183
- package/framework/hooks/shared/state-writer.js +8 -52
- package/framework/hooks/shared/stdin-reader.js +1 -11
- package/framework/hooks/shared/telemetry-logger.js +7 -67
- package/framework/hooks/shared/transcript-usage.js +7 -29
- package/framework/hooks/shared/worktree-root.js +7 -29
- package/framework/rules/csharp-standards.md +1 -1
- package/framework/rules/frontend-standards.md +1 -0
- package/framework/rules/hangfire-standards.md +1 -1
- package/framework/rules/neon-standards.md +1 -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 +2 -2
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-machine/SKILL.md +1 -1
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +2 -2
- package/framework/skills/core/morph-review/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +29 -12
- package/framework/standards/STANDARDS.json +34 -12
- package/framework/standards/STANDARDS.meta.json +16 -2
- package/framework/standards/ai-agents/agent-archetypes.md +2 -2
- package/framework/standards/ai-agents/agent-session.md +1 -1
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
- package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
- package/framework/standards/ai-agents/guardrails.md +1 -1
- package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
- package/framework/standards/ai-agents/observability-patterns.md +1 -1
- package/framework/standards/ai-agents/production.md +1 -1
- package/framework/standards/ai-agents/prompt-sources.md +2 -2
- package/framework/standards/ai-agents/providers/model-registry.md +1 -1
- package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
- package/framework/standards/ai-agents/setup.md +2 -2
- package/framework/standards/ai-agents/sweet-spot.md +2 -2
- package/framework/standards/ai-agents/tool-adapters.md +0 -2
- package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
- package/framework/standards/ai-agents/workflows.md +1 -1
- package/framework/standards/architecture/code-comments.md +1 -1
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
- package/framework/standards/backend/api/validation.md +1 -1
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
- package/framework/standards/data/nosql/cache/redis.md +1 -1
- package/framework/standards/data/nosql/cosmos-db.md +3 -3
- package/framework/standards/frontend/admin-app/forms.md +1 -1
- package/framework/standards/frontend/design-system/art-direction.md +88 -0
- package/framework/standards/frontend/design-system/premium-finish.md +77 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
- package/framework/templates/CLAUDE.md.core.template +3 -3
- package/framework/templates/REGISTRY.json +9 -9
- package/framework/templates/docs/ui-mockups.md +4 -0
- package/package.json +1 -1
- package/src/commands/context/context-refresh.js +0 -16
- package/src/commands/dashboard/dashboard.js +2 -8
- package/src/commands/e2e/e2e.js +17 -104
- package/src/commands/graph/affected.js +0 -14
- package/src/commands/graph/build.js +11 -50
- package/src/commands/graph/explain.js +0 -16
- package/src/commands/graph/status.js +1 -12
- package/src/commands/mcp/mcp-setup.js +4 -62
- package/src/commands/observability/cost.js +5 -57
- package/src/commands/observability/telemetry.js +1 -14
- package/src/commands/project/branch.js +4 -45
- package/src/commands/project/claim.js +4 -48
- package/src/commands/project/doctor.js +48 -302
- package/src/commands/project/env.js +1 -27
- package/src/commands/project/fleet.js +3 -32
- package/src/commands/project/init.js +4 -68
- package/src/commands/project/install-plugin-cmd.js +0 -1
- package/src/commands/project/standards.js +1 -62
- package/src/commands/project/status.js +0 -53
- package/src/commands/project/update.js +31 -239
- package/src/commands/project/worktree.js +108 -882
- package/src/commands/scaffold/scaffold.js +0 -25
- package/src/commands/state/advance.js +14 -85
- package/src/commands/state/approve.js +14 -96
- package/src/commands/state/archive.js +12 -64
- package/src/commands/state/auto-approval.js +2 -5
- package/src/commands/state/create.js +22 -109
- package/src/commands/state/delete.js +11 -63
- package/src/commands/state/finish.js +98 -475
- package/src/commands/state/gate-check.js +22 -132
- package/src/commands/state/gate-decision.js +3 -39
- package/src/commands/state/handoff.js +3 -30
- package/src/commands/state/list.js +14 -84
- package/src/commands/state/report-check.js +8 -58
- package/src/commands/state/retype.js +4 -26
- package/src/commands/validation/index.js +0 -3
- package/src/commands/validation/mutate.js +2 -5
- package/src/commands/validation/validate-feature.js +5 -94
- package/src/commands/validation/verify.js +15 -98
- package/src/core/paths/output-schema.js +2 -101
- package/src/core/state/feature-identity.js +1 -25
- package/src/core/state/gate-order.js +0 -27
- package/src/core/state/lifecycle-audit.js +8 -100
- package/src/core/state/state-manager.js +22 -304
- package/src/core/templates/template-registry.js +2 -97
- package/src/core/templates/template-renderer.js +13 -93
- package/src/core/templates/template-seed.js +0 -1
- package/src/core/work-types.js +1 -36
- package/src/dashboard/app/App.jsx +1 -8
- package/src/dashboard/app/components/ActivityFeed.jsx +0 -5
- package/src/dashboard/app/components/CommandPalette.jsx +0 -7
- package/src/dashboard/app/components/DetailPanel.jsx +1 -5
- package/src/dashboard/app/components/EntityLink.jsx +0 -12
- package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
- package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
- package/src/dashboard/app/components/Markdown.jsx +0 -9
- package/src/dashboard/app/components/PhaseRail.jsx +0 -11
- package/src/dashboard/app/components/SearchFilter.jsx +0 -4
- package/src/dashboard/app/components/Sidebar.jsx +0 -5
- package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
- package/src/dashboard/app/hooks/usePref.js +1 -5
- package/src/dashboard/app/lib/format.js +0 -2
- package/src/dashboard/app/lib/phases.js +1 -5
- package/src/dashboard/app/lib/project.js +0 -12
- package/src/dashboard/app/pages/AgentMap.jsx +1 -8
- package/src/dashboard/app/pages/FeatureDetail.jsx +1 -5
- package/src/dashboard/app/pages/Features.jsx +1 -8
- package/src/dashboard/app/pages/Guide.jsx +0 -1
- package/src/dashboard/app/pages/HookInspector.jsx +2 -23
- package/src/dashboard/app/pages/PhasePipeline.jsx +0 -3
- package/src/dashboard/app/pages/Portfolio.jsx +0 -1
- package/src/dashboard/app/pages/RulesMap.jsx +1 -16
- package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
- package/src/dashboard/app/pages/Standards.jsx +2 -17
- package/src/dashboard/scanner/activity-scanner.js +10 -69
- package/src/dashboard/scanner/agents-scanner.js +1 -23
- package/src/dashboard/scanner/docs-scanner.js +0 -6
- package/src/dashboard/scanner/feature-status.js +2 -5
- package/src/dashboard/scanner/features-scanner.js +10 -66
- package/src/dashboard/scanner/hooks-scanner.js +5 -28
- package/src/dashboard/scanner/index.js +0 -4
- package/src/dashboard/scanner/portfolio.js +5 -29
- package/src/dashboard/scanner/project-api.js +8 -54
- package/src/dashboard/scanner/rules-scanner.js +1 -2
- package/src/dashboard/scanner/skills-scanner.js +2 -12
- package/src/dashboard/scanner/standards-scanner.js +2 -6
- package/src/dashboard/vite-plugin-morph-data.js +5 -19
- package/src/lib/ai/ai-checks.js +7 -52
- package/src/lib/ai/ai-project-scan.js +14 -108
- package/src/lib/ai/code-audit.js +7 -63
- package/src/lib/ai/pin-drift.js +8 -51
- package/src/lib/ai/registry-audit.js +11 -90
- package/src/lib/ci/ci-verify.js +4 -19
- package/src/lib/ci/github-ci.js +9 -37
- package/src/lib/ci/workflow-scaffold.js +2 -10
- package/src/lib/detectors/claude-config-detector.js +13 -74
- package/src/lib/detectors/index.js +4 -50
- package/src/lib/e2e/compose-env.js +5 -66
- package/src/lib/e2e/stack-teardown.js +6 -40
- package/src/lib/generators/architecture-scanner.js +18 -156
- package/src/lib/generators/handoff-generator.js +9 -53
- package/src/lib/generators/scaffold-generator.js +5 -101
- package/src/lib/generators/settings-generator.js +4 -37
- package/src/lib/git/branch-classifier.js +11 -84
- package/src/lib/git/default-branch.js +14 -169
- package/src/lib/git/evidence-staleness.js +1 -0
- package/src/lib/git/gh.js +2 -17
- package/src/lib/git/pending-prs.js +6 -37
- package/src/lib/git/pr-files.js +3 -28
- package/src/lib/git/pr-index.js +3 -34
- package/src/lib/git/tree-fingerprint.js +3 -15
- package/src/lib/git/tree-state.js +6 -33
- package/src/lib/graph/god-nodes.js +2 -22
- package/src/lib/graph/graph-health.js +3 -24
- package/src/lib/graph/graph-loader.js +5 -56
- package/src/lib/graph/graphify-runtime.js +7 -37
- package/src/lib/graph/graphifyignore.js +8 -74
- package/src/lib/graph/sanitize.js +16 -136
- package/src/lib/heavy/cleanup.js +1 -1
- package/src/lib/installers/effects.js +8 -93
- package/src/lib/installers/mcp-installer.js +9 -169
- package/src/lib/installers/memory-installer.js +4 -27
- package/src/lib/installers/templates-reconcile.js +5 -60
- package/src/lib/mutation/dotnet-introspection.js +20 -106
- package/src/lib/mutation/subset.js +1 -4
- package/src/lib/plan/artifact-vocabulary.js +5 -25
- package/src/lib/plan/checks.js +5 -31
- package/src/lib/plan/plan-parser.js +1 -6
- package/src/lib/projects/registry.js +7 -44
- package/src/lib/review-reports.js +5 -23
- package/src/lib/risk-detector.js +39 -173
- package/src/lib/specs/adr-index.js +6 -34
- package/src/lib/specs/frontmatter.js +2 -15
- package/src/lib/specs/gfm-table.js +1 -7
- package/src/lib/specs/revocations.js +1 -14
- package/src/lib/specs/screen-checklist.js +47 -124
- package/src/lib/stack/dotnet-build-ignores.js +2 -6
- package/src/lib/stack/stack-profile.js +1 -28
- package/src/lib/stack/stack-scan.js +1 -8
- package/src/lib/stack-filter.js +4 -27
- package/src/lib/standards/registry.js +1 -7
- package/src/lib/standards/sections.js +2 -13
- package/src/lib/standards/verified-against.js +19 -191
- package/src/lib/tasks/eval-node.js +21 -169
- package/src/lib/tasks/linux-runner.js +18 -142
- package/src/lib/tasks/test-nodes.js +43 -240
- package/src/lib/tasks/test-runner.js +43 -341
- package/src/lib/telemetry/metrics.js +7 -36
- package/src/lib/telemetry/telemetry-reader.js +13 -125
- package/src/lib/telemetry/verify-event.js +2 -30
- package/src/lib/validators/code-budget/code-budget-validator.js +3 -43
- package/src/lib/validators/code-budget/index.js +0 -7
- package/src/lib/validators/contracts/contract-compliance-validator.js +2 -24
- package/src/lib/validators/contracts/index.js +0 -6
- package/src/lib/validators/nextjs/index.js +0 -5
- package/src/lib/validators/nextjs/next-component-validator.js +4 -81
- package/src/lib/validators/packages/index.js +0 -6
- package/src/lib/validators/packages/package-validator.js +6 -56
- package/src/lib/validators/reuse/index.js +0 -8
- package/src/lib/validators/reuse/reuse-validator.js +11 -101
- package/src/lib/validators/reuse/symbol-scanner.js +6 -62
- package/src/lib/validators/traceability-check.js +5 -63
- package/src/lib/validators/validation-runner.js +20 -125
- package/src/lib/validators/verify-runner.js +52 -358
- package/src/lib/work-type-detector.js +5 -67
- package/src/lib/worktree/docker-audit.js +17 -136
- package/src/lib/worktree/env-allocator.js +10 -98
- package/src/lib/worktree/feature-truth.js +12 -115
- package/src/lib/worktree/finish-backup.js +32 -242
- package/src/lib/worktree/fleet-scanner.js +13 -95
- package/src/lib/worktree/ignored-triage.js +15 -91
- package/src/lib/worktree/vscode-settings.js +2 -3
- package/src/lib/worktree/worktree-audit.js +21 -213
- package/src/lib/worktree/worktree-include.js +3 -5
- package/src/scripts/global-install.js +3 -9
- package/src/scripts/install-plugin.js +1 -13
- package/src/scripts/setup-infra.js +17 -147
- package/src/utils/agents-installer.js +28 -275
- package/src/utils/banner.js +4 -25
- package/src/utils/claude-md-injector.js +1 -37
- package/src/utils/claude-settings-manager.js +1 -52
- package/src/utils/file-copier.js +11 -95
- package/src/utils/hooks-installer.js +21 -298
- package/src/utils/skills-installer.js +4 -101
- package/src/utils/version-checker.js +4 -83
- package/framework/commands/morph-proposal.md +0 -9
- package/src/commands/utils/index.js +0 -3
- package/src/lib/detectors/design-system-detector.js +0 -188
- package/src/lib/generators/design-system-generator.js +0 -508
- package/src/lib/specs/old-format.js +0 -68
- package/src/utils/agent-id-mapper.js +0 -11
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/scripts/install-plugin.js
|
|
2
1
|
import { join } from 'path';
|
|
3
2
|
import { homedir } from 'os';
|
|
4
3
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
@@ -10,7 +9,6 @@ const CACHE_DIR = join(PLUGINS_DIR, 'cache', 'claude-plugins-official');
|
|
|
10
9
|
const INSTALLED_FILE = join(PLUGINS_DIR, 'installed_plugins.json');
|
|
11
10
|
const GH_REPO = 'anthropics/claude-plugins-official';
|
|
12
11
|
|
|
13
|
-
/** Fetch JSON from GitHub API (no auth — public repo) */
|
|
14
12
|
async function fetchGitHub(path) {
|
|
15
13
|
return new Promise((resolve, reject) => {
|
|
16
14
|
const opts = {
|
|
@@ -29,7 +27,6 @@ async function fetchGitHub(path) {
|
|
|
29
27
|
});
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
/** Download raw file content from a URL, following one redirect */
|
|
33
30
|
async function downloadFile(rawUrl) {
|
|
34
31
|
return new Promise((resolve, reject) => {
|
|
35
32
|
const doGet = (url) => {
|
|
@@ -51,25 +48,21 @@ async function downloadFile(rawUrl) {
|
|
|
51
48
|
});
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
/** Read installed_plugins.json safely */
|
|
55
51
|
export function readInstalledPlugins() {
|
|
56
52
|
if (!existsSync(INSTALLED_FILE)) return { version: 2, plugins: {} };
|
|
57
53
|
try { return JSON.parse(readFileSync(INSTALLED_FILE, 'utf8')); }
|
|
58
54
|
catch { return { version: 2, plugins: {} }; }
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
/** Check if plugin key exists in the plugins map */
|
|
62
57
|
export function isPluginInstalled(plugins, name) {
|
|
63
58
|
return `${name}@claude-plugins-official` in plugins;
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
/** Build an installed_plugins.json entry */
|
|
67
61
|
export function buildInstallEntry(pluginName, installPath, gitCommitSha, version) {
|
|
68
62
|
const now = new Date().toISOString();
|
|
69
63
|
return { scope: 'user', installPath, version, installedAt: now, lastUpdated: now, gitCommitSha };
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
/** Resolve latest commit SHA for a plugin path in the repo */
|
|
73
66
|
export async function resolvePluginVersion(pluginName) {
|
|
74
67
|
const commits = await fetchGitHub(`/repos/${GH_REPO}/commits?path=${pluginName}&per_page=1`);
|
|
75
68
|
if (!Array.isArray(commits) || commits.length === 0) {
|
|
@@ -79,7 +72,6 @@ export async function resolvePluginVersion(pluginName) {
|
|
|
79
72
|
return { sha, shortSha: sha.slice(0, 12) };
|
|
80
73
|
}
|
|
81
74
|
|
|
82
|
-
/** Download all files for a plugin from the repo tree */
|
|
83
75
|
async function downloadPluginFiles(pluginName, sha, destDir) {
|
|
84
76
|
const tree = await fetchGitHub(`/repos/${GH_REPO}/git/trees/${sha}?recursive=1`);
|
|
85
77
|
if (!tree.tree) throw new Error('GitHub tree API returned unexpected shape');
|
|
@@ -98,11 +90,7 @@ async function downloadPluginFiles(pluginName, sha, destDir) {
|
|
|
98
90
|
}
|
|
99
91
|
}
|
|
100
92
|
|
|
101
|
-
/**
|
|
102
|
-
* Install a Claude Code plugin from GitHub.
|
|
103
|
-
* @param {string} pluginName - e.g. "context7"
|
|
104
|
-
* @returns {{ installed: boolean, version: string, alreadyInstalled: boolean }}
|
|
105
|
-
*/
|
|
93
|
+
/** @returns {{ installed: boolean, version: string, alreadyInstalled: boolean }} */
|
|
106
94
|
export async function installPlugin(pluginName) {
|
|
107
95
|
const data = readInstalledPlugins();
|
|
108
96
|
if (isPluginInstalled(data.plugins, pluginName)) {
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* setup-infra.js
|
|
3
|
-
*
|
|
4
|
-
* Headless infrastructure setup for MORPH-SPEC.
|
|
5
|
-
* Extracted from init.js (steps 1-10) so it can run as
|
|
6
|
-
* `morph-spec setup-infra` without interactive prompts or stack detection.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* import { setupInfra } from './setup-infra.js';
|
|
10
|
-
* await setupInfra('/path/to/project');
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
1
|
import { join, dirname, resolve } from 'path';
|
|
14
2
|
import { fileURLToPath } from 'url';
|
|
15
3
|
import { execSync } from 'child_process';
|
|
@@ -32,7 +20,6 @@ import { installClaudeHooks, installGlobalStatusline } from '../utils/claude-set
|
|
|
32
20
|
import { installSkills } from '../utils/skills-installer.js';
|
|
33
21
|
import { installAgents, installDomainAgents } from '../utils/agents-installer.js';
|
|
34
22
|
import { resolvePrimaryRoot } from '../commands/project/worktree.js';
|
|
35
|
-
import { findOldFormatFeatures, oldFormatGuardLines } from '../lib/specs/old-format.js';
|
|
36
23
|
import { reconcileLegacyTemplatesCopy } from '../lib/installers/templates-reconcile.js';
|
|
37
24
|
import { realEffects } from '../lib/installers/effects.js';
|
|
38
25
|
|
|
@@ -54,14 +41,7 @@ async function installRequiredPlugins(log, exec) {
|
|
|
54
41
|
}
|
|
55
42
|
}
|
|
56
43
|
|
|
57
|
-
/**
|
|
58
|
-
* Install only stack-matching rules from rulesSrc to rulesDest.
|
|
59
|
-
* Also removes orphan rules in rulesDest that are no longer in the install set.
|
|
60
|
-
*
|
|
61
|
-
* @param {string} rulesSrc - Source rules directory (framework/rules/)
|
|
62
|
-
* @param {string} rulesDest - Destination rules directory (.claude/rules/)
|
|
63
|
-
* @param {string[]} projectTags - Stack tags from config (e.g., ['dotnet', 'blazor'])
|
|
64
|
-
*/
|
|
44
|
+
/** Also removes orphan rules in rulesDest that are no longer in the install set. */
|
|
65
45
|
export function installRulesForStack(rulesSrc, rulesDest, projectTags, fx = realEffects()) {
|
|
66
46
|
const sourceFiles = readdirSync(rulesSrc).filter(f => f.endsWith('.md'));
|
|
67
47
|
const installed = new Set();
|
|
@@ -75,9 +55,7 @@ export function installRulesForStack(rulesSrc, rulesDest, projectTags, fx = real
|
|
|
75
55
|
}
|
|
76
56
|
}
|
|
77
57
|
|
|
78
|
-
//
|
|
79
|
-
// skills-installer.js e agents-installer.js (D6): `cleanFrameworkDirs()` já
|
|
80
|
-
// apagou `.claude/rules/` inteiro antes de este código rodar de verdade.
|
|
58
|
+
// Calado em `dryRun`: `cleanFrameworkDirs()` já apagou `.claude/rules/` inteiro antes da execução real.
|
|
81
59
|
if (!fx.dryRun) {
|
|
82
60
|
for (const file of readdirSync(rulesDest).filter(f => f.endsWith('.md'))) {
|
|
83
61
|
if (!installed.has(file)) {
|
|
@@ -89,11 +67,7 @@ export function installRulesForStack(rulesSrc, rulesDest, projectTags, fx = real
|
|
|
89
67
|
return { installed: installed.size };
|
|
90
68
|
}
|
|
91
69
|
|
|
92
|
-
/**
|
|
93
|
-
* Slash commands filtered by `stacks:` frontmatter. Clean-slate like the
|
|
94
|
-
* skills: removes only a framework command that the stack filtered out, never
|
|
95
|
-
* a command the user wrote into `.claude/commands/`.
|
|
96
|
-
*/
|
|
70
|
+
/** Clean-slate: removes only a framework command the stack filtered out, never one the user wrote. */
|
|
97
71
|
export function installCommandsForStack(commandsSrc, commandsDest, projectTags, fx = realEffects()) {
|
|
98
72
|
const sourceFiles = readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
|
|
99
73
|
let installed = 0;
|
|
@@ -109,22 +83,13 @@ export function installCommandsForStack(commandsSrc, commandsDest, projectTags,
|
|
|
109
83
|
return { installed };
|
|
110
84
|
}
|
|
111
85
|
|
|
112
|
-
/**
|
|
113
|
-
* Re-install only stack-aware assets (commands, rules, skills, agents) using current config.json.
|
|
114
|
-
* Skips infrastructure steps (dirs, framework copy, hooks).
|
|
115
|
-
*
|
|
116
|
-
* @param {string} targetPath - Absolute path to the target project directory
|
|
117
|
-
* @param {Function} log - Logging function
|
|
118
|
-
* @returns {{ agentCounts: object, domainCounts: object, projectTags: string[] }}
|
|
119
|
-
*/
|
|
120
86
|
async function installStackAwareAssets(targetPath, log) {
|
|
121
87
|
const configPath = join(targetPath, '.morph', 'config', 'config.json');
|
|
122
88
|
let projectTags = [];
|
|
123
89
|
if (await pathExists(configPath)) {
|
|
124
90
|
try {
|
|
125
|
-
// BOM-tolerant: a config.json
|
|
126
|
-
//
|
|
127
|
-
// and only universal personas get installed.
|
|
91
|
+
// BOM-tolerant: a config.json written by PS 5.1 Out-File carries a BOM, and a failed parse
|
|
92
|
+
// here silently installs only the universal personas.
|
|
128
93
|
const config = JSON.parse(readFileSync(configPath, 'utf-8').replace(/^/, ''));
|
|
129
94
|
projectTags = getProjectTags(config);
|
|
130
95
|
} catch { /* ignore malformed config */ }
|
|
@@ -160,20 +125,8 @@ async function installStackAwareAssets(targetPath, log) {
|
|
|
160
125
|
}
|
|
161
126
|
|
|
162
127
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* No markers / no file → no-op (fail-open).
|
|
166
|
-
* Exported so `morph-spec update` derives the same block on upgrades.
|
|
167
|
-
*
|
|
168
|
-
* @param {string} claudeMdPath - Absolute path to the installed .claude/CLAUDE.md
|
|
169
|
-
* @param {Array<{ name: string, title: string, domains: string[] }>} agents
|
|
170
|
-
* @param {object} [options]
|
|
171
|
-
* @param {ReturnType<import('../lib/installers/effects.js').createEffects>} [options.fx]
|
|
172
|
-
* @param {string} [options.readFrom] - De onde LER o conteúdo-base.
|
|
173
|
-
* Num `--dry-run` o arquivo de destino ainda não recebeu a cópia que o passo
|
|
174
|
-
* anterior previu, então ler o destino diria "sem marcadores" e o efeito de
|
|
175
|
-
* escrita sumiria da previsão — divergindo da execução real. Lendo a MESMA
|
|
176
|
-
* origem que seria copiada, previsão e execução decidem igual.
|
|
128
|
+
* No markers or no file is a no-op. `readFrom`: on `--dry-run` the destination has not received
|
|
129
|
+
* the predicted copy yet, so read the copy's source and let preview and real run decide alike.
|
|
177
130
|
*/
|
|
178
131
|
export async function updateClaudeMdAgentsBlock(claudeMdPath, agents = [], options = {}) {
|
|
179
132
|
const { fx = realEffects(), readFrom = claudeMdPath } = options;
|
|
@@ -196,20 +149,8 @@ export async function updateClaudeMdAgentsBlock(claudeMdPath, agents = [], optio
|
|
|
196
149
|
}
|
|
197
150
|
|
|
198
151
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* @param {string} targetPath - Absolute path to the target project directory
|
|
203
|
-
* @param {object} options
|
|
204
|
-
* @param {Function} options._exec - exec function (for testing)
|
|
205
|
-
* @param {Function} [options._detectGraphifyVersion] - graphify probe (for testing: the
|
|
206
|
-
* step-18b branches differ with graphify installed or not, and CI has no Python)
|
|
207
|
-
* @param {Function} [options._log] - log sink (for testing: replaces stdout, which the test
|
|
208
|
-
* runner itself reports through — stubbing it swallows test results)
|
|
209
|
-
* @param {boolean} options.reinstall - If true, only re-install stack-aware assets (rules, skills, agents)
|
|
210
|
-
* @param {boolean} options.force - Bypass the secondary-worktree guard (see below). Callers
|
|
211
|
-
* (e.g. `initCommand`) that already performed their own equivalent check pass this so the
|
|
212
|
-
* check isn't redundantly re-applied here.
|
|
152
|
+
* Headless install: no prompts, no stack detection. `force` skips the secondary-worktree guard
|
|
153
|
+
* for callers that already ran an equivalent check.
|
|
213
154
|
*/
|
|
214
155
|
export async function setupInfra(targetPath, {
|
|
215
156
|
_exec = execSync, _detectGraphifyVersion = null, _log = null, reinstall = false, force = false,
|
|
@@ -221,16 +162,9 @@ export async function setupInfra(targetPath, {
|
|
|
221
162
|
else if (!quiet) process.stdout.write(msg + '\n');
|
|
222
163
|
}
|
|
223
164
|
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
// `.morph/memory/`, `.morph/archive/` and `.morph/state.json` are NOT — a
|
|
228
|
-
// full install would scaffold a second, disconnected config/state tree
|
|
229
|
-
// inside the worktree. `reinstall` mode is exempt: it only touches
|
|
230
|
-
// .claude/* stack-aware assets, which are the junctioned (safe) subset.
|
|
231
|
-
// `resolvePrimaryRoot` fails open to `targetPath` itself outside a git repo
|
|
232
|
-
// (or on any git error), so non-git projects and the primary root are
|
|
233
|
-
// never blocked.
|
|
165
|
+
// In a linked worktree only .claude/ and .morph/framework/ are junctions to the root: a full
|
|
166
|
+
// install would scaffold a second, disconnected config/state tree. `reinstall` touches only
|
|
167
|
+
// the junctioned subset.
|
|
234
168
|
if (!reinstall && !force) {
|
|
235
169
|
const target = resolve(targetPath).replace(/\\/g, '/');
|
|
236
170
|
const root = resolvePrimaryRoot(targetPath);
|
|
@@ -242,20 +176,9 @@ export async function setupInfra(targetPath, {
|
|
|
242
176
|
}
|
|
243
177
|
}
|
|
244
178
|
|
|
245
|
-
// Same refusal as `update`, and neither `force` nor `reinstall` waives it:
|
|
246
|
-
// `init --force` and `setup-infra` overwrite `.morph/` without passing through it.
|
|
247
|
-
const oldFormat = findOldFormatFeatures(targetPath);
|
|
248
|
-
if (oldFormat.length) {
|
|
249
|
-
for (const line of oldFormatGuardLines(oldFormat, targetPath)) log(line);
|
|
250
|
-
return { refused: true, reason: 'old-format-features', features: oldFormat };
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// --- Reinstall mode: only re-install stack-aware assets ---
|
|
254
179
|
if (reinstall) {
|
|
255
180
|
log('setup-infra (reinstall): re-installing stack-aware assets...');
|
|
256
181
|
const { agentCounts, domainCounts } = await installStackAwareAssets(targetPath, log);
|
|
257
|
-
// Keep the derived personas list in .claude/CLAUDE.md in sync with what
|
|
258
|
-
// was actually (re)installed.
|
|
259
182
|
await updateClaudeMdAgentsBlock(join(targetPath, '.claude', 'CLAUDE.md'), agentCounts?.agents ?? []);
|
|
260
183
|
log('setup-infra (reinstall): complete.');
|
|
261
184
|
return {
|
|
@@ -267,17 +190,14 @@ export async function setupInfra(targetPath, {
|
|
|
267
190
|
};
|
|
268
191
|
}
|
|
269
192
|
|
|
270
|
-
// --- 0. Install required Claude Code plugins ---
|
|
271
193
|
await installRequiredPlugins(log, _exec);
|
|
272
194
|
|
|
273
|
-
// --- 1. Inject @import into root CLAUDE.md (preserves user content) ---
|
|
274
195
|
log('Step 1: Setting up CLAUDE.md...');
|
|
275
196
|
const claudeMdSrc = join(FRAMEWORK_DIR, 'CLAUDE.md');
|
|
276
197
|
const claudeMdDest = join(targetPath, 'CLAUDE.md');
|
|
277
198
|
const importResult = await injectMorphImport(claudeMdDest);
|
|
278
199
|
log(` ✓ Root CLAUDE.md: ${importResult}`);
|
|
279
200
|
|
|
280
|
-
// --- 2. Create .morph directory structure ---
|
|
281
201
|
log('Step 2: Creating .morph structure...');
|
|
282
202
|
const morphPath = join(targetPath, '.morph');
|
|
283
203
|
const configDir = join(morphPath, 'config');
|
|
@@ -296,7 +216,6 @@ export async function setupInfra(targetPath, {
|
|
|
296
216
|
await ensureDir(memoryDir);
|
|
297
217
|
await ensureDir(archiveDir);
|
|
298
218
|
|
|
299
|
-
// --- 3. Write minimal config.json (only if not exists) ---
|
|
300
219
|
log('Step 3: Writing config.json...');
|
|
301
220
|
const configPath = join(configDir, 'config.json');
|
|
302
221
|
if (!(await pathExists(configPath))) {
|
|
@@ -312,7 +231,6 @@ export async function setupInfra(targetPath, {
|
|
|
312
231
|
await writeJson(configPath, config);
|
|
313
232
|
}
|
|
314
233
|
|
|
315
|
-
// --- 4. Write placeholder context/README.md (only if not exists) ---
|
|
316
234
|
log('Step 4: Writing context/README.md...');
|
|
317
235
|
const contextReadmePath = join(contextDir, 'README.md');
|
|
318
236
|
if (!(await pathExists(contextReadmePath))) {
|
|
@@ -321,27 +239,9 @@ export async function setupInfra(targetPath, {
|
|
|
321
239
|
await writeFile(contextReadmePath, readmeContent);
|
|
322
240
|
}
|
|
323
241
|
|
|
324
|
-
// --- 5. framework/templates is intentionally NOT copied to
|
|
325
|
-
// .morph/framework/templates anymore (R3 perf plan, Task 2). Template
|
|
326
|
-
// resolution is layered (template-registry.js, architecture-scanner.js
|
|
327
|
-
// resolveTemplatePath): a project-local .morph/framework/templates/{path}
|
|
328
|
-
// is still checked FIRST as an explicit override, then falls back to the
|
|
329
|
-
// npm package's own framework/templates/ — which is what every template
|
|
330
|
-
// actually rendered from until now anyway, since the installed copy was
|
|
331
|
-
// never read as anything but that override. Pre-populating it was a
|
|
332
|
-
// byte-for-byte redundant 348KB copy on every install/update.
|
|
333
242
|
log('Step 5: Skipping framework templates copy (resolved from package; local override still supported)...');
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
// checkProjectOutdated() já leu a versão anterior do projeto antes de
|
|
337
|
-
// chamar update. Aqui (init/setup-infra) fazemos o mesmo QUANDO a mesma
|
|
338
|
-
// fonte está disponível: getProjectMorphVersion() lê .morph/.morphversion
|
|
339
|
-
// — o MESMO arquivo/campo que checkProjectOutdated().current usa — e essa
|
|
340
|
-
// leitura acontece ANTES do Passo 17 (saveProjectMorphVersion) sobrescrever
|
|
341
|
-
// esse arquivo com a versão atual, então "versão anterior" aqui é real, não
|
|
342
|
-
// a que este próprio run está prestes a gravar. Sem esse registro (projeto
|
|
343
|
-
// nunca rastreado antes, ou greenfield), não há fonte segura — mantém o
|
|
344
|
-
// aviso como fallback, igual ao comportamento anterior.
|
|
243
|
+
// A cópia legada SOMBREIA os templates do pacote (override-first). A versão anterior é lida
|
|
244
|
+
// aqui, antes de o passo 17 regravar .morph/.morphversion; sem ela, não há fonte segura e só avisa.
|
|
345
245
|
const legacyTemplatesDir = join(frameworkDestDir, 'templates');
|
|
346
246
|
if (await pathExists(legacyTemplatesDir)) {
|
|
347
247
|
const priorVersionInfo = await getProjectMorphVersion(targetPath);
|
|
@@ -357,7 +257,6 @@ export async function setupInfra(targetPath, {
|
|
|
357
257
|
}
|
|
358
258
|
}
|
|
359
259
|
|
|
360
|
-
// --- 6. Copy framework/standards → .morph/framework/standards ---
|
|
361
260
|
log('Step 6: Copying framework standards...');
|
|
362
261
|
const frameworkStandardsSrc = join(FRAMEWORK_DIR, 'standards');
|
|
363
262
|
const frameworkStandardsDest = join(frameworkDestDir, 'standards');
|
|
@@ -365,7 +264,6 @@ export async function setupInfra(targetPath, {
|
|
|
365
264
|
await copyDirectory(frameworkStandardsSrc, frameworkStandardsDest);
|
|
366
265
|
}
|
|
367
266
|
|
|
368
|
-
// --- 7. Copy framework/hooks → .morph/framework/hooks ---
|
|
369
267
|
log('Step 7: Copying hooks...');
|
|
370
268
|
const hooksSrc = join(FRAMEWORK_DIR, 'hooks');
|
|
371
269
|
const hooksDest = join(frameworkDestDir, 'hooks');
|
|
@@ -373,7 +271,6 @@ export async function setupInfra(targetPath, {
|
|
|
373
271
|
await copyDirectory(hooksSrc, hooksDest);
|
|
374
272
|
}
|
|
375
273
|
|
|
376
|
-
// --- 7c. Copy framework/evals → .morph/framework/evals ---
|
|
377
274
|
log('Step 7c: Copying evals (review checklist + trace schema)...');
|
|
378
275
|
const evalsSrc = join(FRAMEWORK_DIR, 'evals');
|
|
379
276
|
const evalsDest = join(frameworkDestDir, 'evals');
|
|
@@ -381,7 +278,6 @@ export async function setupInfra(targetPath, {
|
|
|
381
278
|
await copyDirectory(evalsSrc, evalsDest);
|
|
382
279
|
}
|
|
383
280
|
|
|
384
|
-
// --- 8. Copy framework/agents.json → .morph/framework/agents.json ---
|
|
385
281
|
log('Step 8: Copying agents.json...');
|
|
386
282
|
const agentsSrc = join(FRAMEWORK_DIR, 'agents.json');
|
|
387
283
|
const agentsDest = join(frameworkDestDir, 'agents.json');
|
|
@@ -389,7 +285,6 @@ export async function setupInfra(targetPath, {
|
|
|
389
285
|
await copyFile(agentsSrc, agentsDest);
|
|
390
286
|
}
|
|
391
287
|
|
|
392
|
-
// --- 8b. Copy framework/MORPH.md → .morph/framework/MORPH.md ---
|
|
393
288
|
log('Step 8b: Copying MORPH.md (NLH charter)...');
|
|
394
289
|
const morphMdSrc = join(FRAMEWORK_DIR, 'MORPH.md');
|
|
395
290
|
const morphMdDest = join(frameworkDestDir, 'MORPH.md');
|
|
@@ -397,9 +292,6 @@ export async function setupInfra(targetPath, {
|
|
|
397
292
|
await copyFile(morphMdSrc, morphMdDest);
|
|
398
293
|
}
|
|
399
294
|
|
|
400
|
-
// --- 8b2. Copy framework/docs/CLI.md → .morph/framework/CLI.md ---
|
|
401
|
-
// Referência completa dos comandos (flags, semântica, exemplos) — o
|
|
402
|
-
// CLAUDE.md residente carrega só a tabela compacta e aponta para cá.
|
|
403
295
|
log('Step 8b2: Copying CLI.md (command reference)...');
|
|
404
296
|
const cliMdSrc = join(FRAMEWORK_DIR, 'docs', 'CLI.md');
|
|
405
297
|
const cliMdDest = join(frameworkDestDir, 'CLI.md');
|
|
@@ -407,7 +299,6 @@ export async function setupInfra(targetPath, {
|
|
|
407
299
|
await copyFile(cliMdSrc, cliMdDest);
|
|
408
300
|
}
|
|
409
301
|
|
|
410
|
-
// --- 8c. Copy framework/phases.json → .morph/framework/phases.json ---
|
|
411
302
|
log('Step 8c: Copying phases.json...');
|
|
412
303
|
const phasesSrc = join(FRAMEWORK_DIR, 'phases.json');
|
|
413
304
|
const phasesDest = join(frameworkDestDir, 'phases.json');
|
|
@@ -415,7 +306,6 @@ export async function setupInfra(targetPath, {
|
|
|
415
306
|
await copyFile(phasesSrc, phasesDest);
|
|
416
307
|
}
|
|
417
308
|
|
|
418
|
-
// --- 8d. Copy framework/schemas → .morph/framework/schemas (JSON schemas) ---
|
|
419
309
|
log('Step 8d: Copying schemas...');
|
|
420
310
|
const schemasSrc = join(FRAMEWORK_DIR, 'schemas');
|
|
421
311
|
const schemasDest = join(frameworkDestDir, 'schemas');
|
|
@@ -425,20 +315,16 @@ export async function setupInfra(targetPath, {
|
|
|
425
315
|
|
|
426
316
|
const claudeDest = join(targetPath, '.claude');
|
|
427
317
|
|
|
428
|
-
// --- 9-13. Install stack-aware assets (commands, rules, skills, agents) ---
|
|
429
318
|
log('Steps 10-13: Installing stack-aware assets...');
|
|
430
319
|
const { agentCounts, domainCounts, projectTags } = await installStackAwareAssets(targetPath, log);
|
|
431
320
|
|
|
432
|
-
// --- 14. Copy framework/CLAUDE.md → .claude/CLAUDE.md (morph-owned, gitignored) ---
|
|
433
321
|
log('Step 14: Installing .claude/CLAUDE.md...');
|
|
434
322
|
const runtimeClaudeMdDest = join(claudeDest, 'CLAUDE.md');
|
|
435
323
|
if (await pathExists(claudeMdSrc)) {
|
|
436
324
|
await copyFile(claudeMdSrc, runtimeClaudeMdDest);
|
|
437
|
-
// Derive the personas section from what step 10-13 actually installed.
|
|
438
325
|
await updateClaudeMdAgentsBlock(runtimeClaudeMdDest, agentCounts?.agents ?? []);
|
|
439
326
|
}
|
|
440
327
|
|
|
441
|
-
// --- 15. installGlobalStatusline (non-critical) ---
|
|
442
328
|
log('Step 15: Installing global statusline...');
|
|
443
329
|
const HOOKS_SRC = join(FRAMEWORK_DIR, 'hooks', 'claude-code');
|
|
444
330
|
try {
|
|
@@ -447,16 +333,13 @@ export async function setupInfra(targetPath, {
|
|
|
447
333
|
// Non-critical — global ~/.claude may not be writable
|
|
448
334
|
}
|
|
449
335
|
|
|
450
|
-
// --- 16. installClaudeHooks ---
|
|
451
336
|
log('Step 16: Installing Claude Code hooks...');
|
|
452
337
|
await installClaudeHooks(targetPath);
|
|
453
338
|
|
|
454
|
-
// --- 17. saveProjectMorphVersion ---
|
|
455
339
|
log('Step 17: Saving version info...');
|
|
456
340
|
const cliVersion = getInstalledCLIVersion();
|
|
457
341
|
await saveProjectMorphVersion(targetPath, cliVersion);
|
|
458
342
|
|
|
459
|
-
// --- 18. updateGitignore + .gitattributes ---
|
|
460
343
|
log('Step 18: Updating .gitignore + .gitattributes...');
|
|
461
344
|
await updateGitignore(targetPath);
|
|
462
345
|
await ensureGitattributes(targetPath);
|
|
@@ -464,10 +347,7 @@ export async function setupInfra(targetPath, {
|
|
|
464
347
|
log('Step 18a: Editor excludes for worktrees...');
|
|
465
348
|
try { applyEditorSettings(targetPath); } catch { /* fail-open */ }
|
|
466
349
|
|
|
467
|
-
//
|
|
468
|
-
// Fail-open por inteiro (ADR-002): sem Python, sem uv e sem pipx, o step
|
|
469
|
-
// registra e segue. O wrapper de CLI mata o processo em qualquer throw
|
|
470
|
-
// (setup-infra-cmd.js), então nada aqui pode escapar do try.
|
|
350
|
+
// Fail-open por inteiro: o wrapper de CLI mata o processo em qualquer throw.
|
|
471
351
|
log('Step 18b: Codebase graph (graphify)...');
|
|
472
352
|
try {
|
|
473
353
|
const { writeGraphifyignore, describeOutdatedIgnore } = await import('../lib/graph/graphifyignore.js');
|
|
@@ -495,7 +375,6 @@ export async function setupInfra(targetPath, {
|
|
|
495
375
|
} else {
|
|
496
376
|
const { kind } = detectInstaller();
|
|
497
377
|
if (!kind) {
|
|
498
|
-
// Registra e segue: o framework funciona sem grafo, por grep.
|
|
499
378
|
log(` ⚠ Sem uv/pipx/python — grafo indisponível. Depois: uv tool install ${GRAPHIFY_PACKAGE}==${GRAPHIFY_VERSION}`);
|
|
500
379
|
} else {
|
|
501
380
|
// Sem o extra [sql] os arquivos .sql são ignorados em silêncio.
|
|
@@ -510,16 +389,8 @@ export async function setupInfra(targetPath, {
|
|
|
510
389
|
}
|
|
511
390
|
}
|
|
512
391
|
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
// `graphify hook install` ficou de fora por três defeitos medidos no 0.9.50:
|
|
516
|
-
// sai sem fazer nada em worktree vinculada, não tem post-merge (merge e pull
|
|
517
|
-
// nunca rebuildam) e, num commit depois de um fast-forward, carimba o HEAD
|
|
518
|
-
// num grafo sem os arquivos do merge. E nunca `graphify claude install`:
|
|
519
|
-
// escreveria no CLAUDE.md e um PreToolUse próprio.
|
|
520
|
-
//
|
|
521
|
-
// A linha só sai com o graphify presente, e diz o que dispara de fato: um
|
|
522
|
-
// commit feito no terminal não dispara nada até o próximo desses.
|
|
392
|
+
// Sem hook git do graphify: o refresh mora nos hooks do Claude (step 16). O `graphify hook install`
|
|
393
|
+
// 0.9.50 não roda em worktree vinculada, não tem post-merge e carimba HEAD num grafo sem o merge.
|
|
523
394
|
if (probe()) {
|
|
524
395
|
log(' ✓ refresh automático do grafo da raiz: depois dos comandos git/gh/morph-spec do agente e no início de cada sessão');
|
|
525
396
|
}
|
|
@@ -527,7 +398,6 @@ export async function setupInfra(targetPath, {
|
|
|
527
398
|
log(` ⚠ Step do grafo pulado: ${err.message}`);
|
|
528
399
|
}
|
|
529
400
|
|
|
530
|
-
// --- 19. Initialize state.json (only if not exists) ---
|
|
531
401
|
log('Step 19: Initializing state.json...');
|
|
532
402
|
const statePath = join(morphPath, 'state.json');
|
|
533
403
|
if (!(await pathExists(statePath))) {
|