@polymorphism-tech/morph-spec 8.47.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 +51 -43
- package/README.md +39 -38
- package/bin/morph-spec.js +41 -113
- package/bin/validate.js +1 -147
- 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 +86 -21
- 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-status.md +4 -4
- package/framework/docs/CLI.md +574 -286
- package/framework/evals/review-checklist.md +82 -41
- package/framework/hooks/README.md +10 -11
- 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 +3 -17
- package/framework/hooks/claude-code/core/denylist.json +33 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +15 -63
- package/framework/hooks/claude-code/core/gate-guard.js +9 -78
- 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 +36 -2
- package/framework/hooks/claude-code/core/protect-spec-files.js +25 -297
- package/framework/hooks/claude-code/core/state-sync.js +15 -85
- package/framework/hooks/claude-code/core/telemetry-log.js +15 -96
- package/framework/hooks/claude-code/core/validate-completion.js +37 -147
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +23 -0
- package/framework/hooks/claude-code/core/worktree-context.js +15 -114
- 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/claude-code/statusline.py +55 -41
- package/framework/hooks/package.json +3 -0
- 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 +11 -76
- package/framework/hooks/shared/claim-registry.js +9 -119
- package/framework/hooks/shared/command-tokens.js +168 -44
- package/framework/hooks/shared/comment-rules.js +5 -20
- package/framework/hooks/shared/comment-scanner.js +11 -43
- package/framework/hooks/shared/comment-stripper.js +11 -85
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/errata.js +59 -0
- package/framework/hooks/shared/feature-locator.js +11 -95
- package/framework/hooks/shared/frontend-locations.js +4 -0
- package/framework/hooks/shared/gate-question.js +12 -0
- 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 +14 -72
- 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 +99 -0
- package/framework/hooks/shared/source-files.js +4 -17
- package/framework/hooks/shared/spawn-command.js +23 -0
- package/framework/hooks/shared/state-reader.js +51 -247
- package/framework/hooks/shared/state-writer.js +9 -54
- 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/mcp/registry.json +3 -4
- package/framework/phases.json +23 -39
- 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/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 +94 -152
- package/framework/standards/STANDARDS.json +109 -1219
- package/framework/standards/STANDARDS.meta.json +1319 -0
- 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/evals-with-cache.md +1 -2
- 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 +3 -3
- 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 +7 -7
- 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/standards/integration/mcp/mcp-tools.md +7 -7
- package/framework/templates/CLAUDE.md.core.template +3 -3
- package/framework/templates/README.md +2 -3
- package/framework/templates/REGISTRY.json +15 -179
- package/framework/templates/docs/plan.md +72 -0
- package/framework/templates/docs/ui-mockups.md +4 -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/context/context-refresh.js +0 -16
- package/src/commands/dashboard/dashboard.js +2 -8
- package/src/commands/e2e/e2e.js +18 -105
- 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 +17 -111
- 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-procs.js +1 -1
- package/src/commands/project/doctor.js +53 -307
- package/src/commands/project/env.js +1 -27
- package/src/commands/project/fleet.js +6 -35
- package/src/commands/project/heavy.js +3 -3
- package/src/commands/project/init.js +8 -68
- package/src/commands/project/install-plugin-cmd.js +0 -1
- 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 +65 -72
- package/src/commands/project/status.js +28 -121
- package/src/commands/project/update.js +31 -223
- package/src/commands/project/worktree.js +109 -883
- package/src/commands/scaffold/scaffold.js +0 -25
- package/src/commands/state/advance.js +65 -120
- package/src/commands/state/approve.js +87 -229
- package/src/commands/state/archive.js +23 -139
- package/src/commands/state/auto-approval.js +65 -0
- package/src/commands/state/create.js +49 -109
- package/src/commands/state/delete.js +11 -63
- package/src/commands/state/finish.js +105 -494
- package/src/commands/state/gate-check.js +74 -183
- package/src/commands/state/gate-decision.js +8 -42
- package/src/commands/state/handoff.js +4 -31
- package/src/commands/state/list.js +21 -91
- package/src/commands/state/report-check.js +134 -338
- package/src/commands/state/retype.js +12 -28
- package/src/commands/validation/index.js +0 -3
- package/src/commands/validation/mutate.js +79 -19
- package/src/commands/validation/plan-check.js +81 -0
- package/src/commands/validation/validate-feature.js +52 -216
- package/src/commands/validation/verify.js +45 -160
- package/src/core/paths/output-schema.js +9 -155
- package/src/core/state/feature-identity.js +1 -25
- package/src/core/state/gate-order.js +2 -30
- package/src/core/state/lifecycle-audit.js +8 -100
- package/src/core/state/state-manager.js +32 -395
- 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 +21 -0
- package/src/core/work-types.js +10 -45
- package/src/dashboard/app/App.jsx +1 -8
- package/src/dashboard/app/components/ActivityFeed.jsx +2 -8
- package/src/dashboard/app/components/CommandPalette.jsx +4 -11
- 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 +3 -9
- package/src/dashboard/app/lib/project.js +0 -12
- package/src/dashboard/app/pages/Activity.jsx +1 -1
- package/src/dashboard/app/pages/AgentMap.jsx +1 -8
- package/src/dashboard/app/pages/FeatureDetail.jsx +139 -133
- package/src/dashboard/app/pages/Features.jsx +9 -16
- package/src/dashboard/app/pages/Guide.jsx +2 -3
- package/src/dashboard/app/pages/HookInspector.jsx +2 -23
- package/src/dashboard/app/pages/PhasePipeline.jsx +3 -7
- 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 +14 -83
- package/src/dashboard/scanner/agents-scanner.js +1 -23
- package/src/dashboard/scanner/docs-scanner.js +1 -7
- package/src/dashboard/scanner/feature-status.js +2 -5
- package/src/dashboard/scanner/features-scanner.js +92 -113
- 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 +4 -7
- 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 +14 -13
- 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 +8 -59
- 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 +37 -112
- package/src/lib/generators/scaffold-generator.js +5 -101
- package/src/lib/generators/settings-generator.js +11 -122
- 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 +2 -1
- 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 +17 -17
- 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 +2 -6
- package/src/lib/installers/effects.js +8 -93
- package/src/lib/installers/mcp-installer.js +9 -169
- package/src/lib/installers/memory-installer.js +8 -33
- package/src/lib/installers/templates-reconcile.js +5 -60
- package/src/lib/mutation/commands.js +3 -2
- package/src/lib/mutation/dotnet-introspection.js +281 -0
- package/src/lib/mutation/plan.js +14 -6
- package/src/lib/mutation/runner.js +1 -1
- package/src/lib/mutation/subset.js +47 -13
- package/src/lib/plan/artifact-vocabulary.js +40 -0
- package/src/lib/plan/checks.js +208 -0
- package/src/lib/plan/plan-parser.js +204 -0
- package/src/lib/plan/plan-template.js +18 -0
- package/src/lib/projects/registry.js +7 -44
- package/src/lib/review-reports.js +204 -0
- package/src/lib/risk-detector.js +131 -274
- package/src/lib/specs/adr-index.js +38 -85
- package/src/lib/specs/design-seed.js +18 -0
- package/src/lib/specs/frontmatter.js +31 -0
- package/src/lib/specs/gfm-table.js +11 -0
- package/src/lib/specs/revocations.js +31 -102
- package/src/lib/specs/screen-checklist.js +56 -132
- package/src/lib/stack/dotnet-build-ignores.js +43 -0
- package/src/lib/stack/stack-profile.js +1 -28
- package/src/lib/stack/stack-scan.js +260 -0
- package/src/lib/stack-filter.js +4 -27
- package/src/lib/standards/registry.js +37 -0
- package/src/lib/standards/sections.js +47 -0
- package/src/lib/standards/verified-against.js +19 -191
- package/src/lib/tasks/eval-node.js +23 -179
- package/src/lib/tasks/linux-runner.js +18 -142
- package/src/lib/tasks/test-nodes.js +43 -313
- package/src/lib/tasks/test-runner.js +107 -447
- package/src/lib/telemetry/metrics.js +13 -103
- package/src/lib/telemetry/telemetry-reader.js +13 -238
- package/src/lib/telemetry/verify-event.js +4 -34
- package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
- package/src/lib/validators/code-budget/index.js +0 -7
- package/src/lib/validators/contracts/contract-compliance-validator.js +4 -26
- 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 +24 -137
- package/src/lib/validators/reuse/symbol-scanner.js +6 -62
- package/src/lib/validators/traceability-check.js +54 -156
- package/src/lib/validators/validation-runner.js +20 -125
- package/src/lib/validators/verify-runner.js +152 -575
- package/src/lib/work-type-detector.js +5 -67
- package/src/lib/worktree/docker-audit.js +17 -137
- 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 +31 -126
- 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 -138
- package/src/utils/agents-installer.js +92 -272
- package/src/utils/banner.js +4 -25
- package/src/utils/claude-md-injector.js +1 -37
- package/src/utils/claude-settings-manager.js +1 -87
- package/src/utils/file-copier.js +32 -90
- package/src/utils/hooks-installer.js +26 -296
- package/src/utils/skills-installer.js +4 -102
- package/src/utils/version-checker.js +4 -83
- package/framework/commands/morph-proposal.md +0 -57
- 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/commands/utils/index.js +0 -3
- package/src/lib/agents/output-collector.js +0 -76
- package/src/lib/detectors/design-system-detector.js +0 -188
- package/src/lib/evaluator-report.js +0 -104
- package/src/lib/generators/design-system-generator.js +0 -508
- 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/dotnet-test-introspection.js +0 -632
- 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
- package/src/utils/agent-id-mapper.js +0 -11
|
@@ -1,26 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* O graphify 0.9.50 não implementa escopo hierárquico de namespace em C#
|
|
5
|
-
* (graphify/extractors/csharp.py:322-335): um filho que usa um tipo do
|
|
6
|
-
* namespace pai sem `using` explícito vira um STUB por arquivo, e o blast
|
|
7
|
-
* radius do nó real devolve zero consumidores onde existem dois. É falso
|
|
8
|
-
* negativo silencioso — o pior modo de falha possível antes de um hotfix.
|
|
9
|
-
*
|
|
10
|
-
* Três categorias de stub, medidas no MORPH_GHLBrain em 2026-08-27:
|
|
11
|
-
*
|
|
12
|
-
* label com 1 nó real (60 labels, 226 arestas) => coalesce no real
|
|
13
|
-
* label com 0 nós reais (126 labels, 2.479 arestas) => externo (BCL/NuGet)
|
|
14
|
-
* label com 2+ nós reais (22 labels, 93 arestas) => AMBÍGUO
|
|
15
|
-
*
|
|
16
|
-
* O terceiro grupo são símbolos REAIS do projeto (CatalogSchema, CatalogItem,
|
|
17
|
-
* Result, Error, KillSwitch — declarados em CatalogContracts.cs e vizinhos),
|
|
18
|
-
* não BCL. Filtrar "o que sobrou depois de coalescer" os descartaria em
|
|
19
|
-
* silêncio, reintroduzindo o falso negativo que este módulo existe para matar.
|
|
20
|
-
* Por isso o critério de externo é `real.length === 0`, nunca "remanescente".
|
|
21
|
-
*
|
|
22
|
-
* @module graph-sanitize
|
|
23
|
-
*/
|
|
1
|
+
// O graphify não resolve escopo hierárquico de namespace em C#: tipo do namespace pai vira stub por arquivo.
|
|
2
|
+
// Label com 1 nó real coalesce; 0 reais é externo; 2+ reais é ambíguo e são símbolos do projeto, por isso
|
|
3
|
+
// externo é `real.length === 0`, nunca "o que sobrou".
|
|
24
4
|
|
|
25
5
|
/** Arestas que contam como dependência para blast radius. */
|
|
26
6
|
export const USE_RELATIONS = new Set([
|
|
@@ -28,10 +8,7 @@ export const USE_RELATIONS = new Set([
|
|
|
28
8
|
'inherits', 'implements', 'extends', 'dispatches_to', 'indirect_call',
|
|
29
9
|
]);
|
|
30
10
|
|
|
31
|
-
/**
|
|
32
|
-
* Herança não é uso. No ProspectPRO, `IHandler` aparece em 193 arquivos no
|
|
33
|
-
* grep e tem 2 usos reais: é implementada por 98.
|
|
34
|
-
*/
|
|
11
|
+
/** Herança não é uso: uma interface muito implementada tem poucos usos reais. */
|
|
35
12
|
export const INHERITANCE_RELATIONS = new Set(['inherits', 'implements', 'extends']);
|
|
36
13
|
|
|
37
14
|
const LANG_BY_EXT = {
|
|
@@ -40,31 +17,15 @@ const LANG_BY_EXT = {
|
|
|
40
17
|
sql: 'sql', py: 'python', go: 'go', rs: 'rust', java: 'jvm', kt: 'jvm',
|
|
41
18
|
};
|
|
42
19
|
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
* validador de reuso. Pasta de projeto de teste em qualquer nível, em três
|
|
46
|
-
* formas, e só três, porque `[^/]*[Tt]ests?/` genérico também casaria
|
|
47
|
-
* `latest/` e `contests/`:
|
|
48
|
-
* - o segmento inteiro é `test`/`tests` (qualquer caixa)
|
|
49
|
-
* - termina em `.Test`/`.Tests` — a convenção .NET (ProspectPRO.Tests/)
|
|
50
|
-
* - termina em `Test`/`Tests` com T maiúsculo — PascalCase (AlvoTests/)
|
|
51
|
-
* mais o teste colocado ao lado do código em JS/TS: `__tests__/`,
|
|
52
|
-
* `*.test.*` e `*.spec.*`.
|
|
53
|
-
*/
|
|
20
|
+
// O predicado único de teste do grafo e do validador de reuso. Só três formas de pasta, porque
|
|
21
|
+
// `[^/]*[Tt]ests?/` genérico também casaria `latest/` e `contests/`.
|
|
54
22
|
const TEST_PATH = /(^|\/)__tests__\/|\.(test|spec)\.[jt]sx?$|(^|\/)(?:[Tt]ests?|[^/]*\.[Tt]ests?|[^/]*[a-z0-9_]Tests?)\//;
|
|
55
23
|
|
|
56
|
-
/**
|
|
57
|
-
* @param {string} sourceFile
|
|
58
|
-
* @returns {boolean} o arquivo é código de teste (dublê, fixture ou o teste em si)
|
|
59
|
-
*/
|
|
60
24
|
export function isTestPath(sourceFile) {
|
|
61
25
|
return TEST_PATH.test(String(sourceFile || '').replace(/\\/g, '/'));
|
|
62
26
|
}
|
|
63
27
|
|
|
64
|
-
/**
|
|
65
|
-
* @param {string} sourceFile
|
|
66
|
-
* @returns {string} família de linguagem do arquivo, ou '' quando desconhecida
|
|
67
|
-
*/
|
|
28
|
+
/** Família de linguagem do arquivo, ou '' quando desconhecida. */
|
|
68
29
|
export function languageOf(sourceFile) {
|
|
69
30
|
const m = /\.([a-z0-9]+)$/i.exec(sourceFile || '');
|
|
70
31
|
if (!m) return '';
|
|
@@ -73,29 +34,9 @@ export function languageOf(sourceFile) {
|
|
|
73
34
|
|
|
74
35
|
const normOf = (node) => node.norm_label ?? String(node.label ?? '').toLowerCase();
|
|
75
36
|
|
|
76
|
-
|
|
77
|
-
* Label sem os parênteses de chamada. O graphify rotula função como `tchau()`
|
|
78
|
-
* em JS/TS, mas quem consulta digita `tchau` — e em C# o mesmo símbolo aparece
|
|
79
|
-
* sem parênteses. Sem esta normalização, `graph affected tchau` devolve
|
|
80
|
-
* not-found num grafo que tem o símbolo.
|
|
81
|
-
*/
|
|
37
|
+
// O graphify rotula função como `tchau()` em JS/TS, mas quem consulta digita `tchau`, e em C# não há parênteses.
|
|
82
38
|
const baseOf = (norm) => norm.replace(/\(\s*\)$/, '');
|
|
83
39
|
|
|
84
|
-
/**
|
|
85
|
-
* @typedef {object} GraphIndex
|
|
86
|
-
* @property {Map<string, object>} byId
|
|
87
|
-
* @property {Map<string, {real: object[], stub: object[]}>} byLabel
|
|
88
|
-
* @property {Map<string, object[]>} byBaseLabel label sem `()` -> nós reais
|
|
89
|
-
* @property {Map<string, string>} coalesce stubId -> id do nó real
|
|
90
|
-
* @property {object[]} recovered `dispatches_to` recuperados (ver recoverDispatch)
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Índice por id e por label + mapa de coalescência. Uma passada pelos nós.
|
|
95
|
-
*
|
|
96
|
-
* @param {{nodes: object[], links: object[]}} graph
|
|
97
|
-
* @returns {GraphIndex}
|
|
98
|
-
*/
|
|
99
40
|
export function buildIndex(graph) {
|
|
100
41
|
const byId = new Map();
|
|
101
42
|
const byLabel = new Map();
|
|
@@ -121,7 +62,7 @@ export function buildIndex(graph) {
|
|
|
121
62
|
}
|
|
122
63
|
if (entry.real.length === 0) continue;
|
|
123
64
|
const base = baseOf(key);
|
|
124
|
-
if (base === key) continue;
|
|
65
|
+
if (base === key) continue;
|
|
125
66
|
const bucket = byBaseLabel.get(base);
|
|
126
67
|
if (bucket) bucket.push(...entry.real);
|
|
127
68
|
else byBaseLabel.set(base, [...entry.real]);
|
|
@@ -137,21 +78,8 @@ const isCsharp = (node) => Boolean(node?.source_file) && /\.cs$/i.test(node.sour
|
|
|
137
78
|
/** Nome do método sem o ponto inicial e sem a assinatura, como o graphify casa. */
|
|
138
79
|
const methodName = (node) => String(node.label ?? '').trim().replace(/^\./, '').split('(')[0];
|
|
139
80
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* teste. O resolvedor dele (graphify/csharp_dispatch.py) liga o método da
|
|
143
|
-
* interface ao da implementação só quando há EXATAMENTE um implementador — e
|
|
144
|
-
* um `FakeX : IX` no grafo é o segundo. Este é o mesmo algoritmo, com o guard
|
|
145
|
-
* contando só implementadores de produção. Medido no MORPH_GHLBrain: com os
|
|
146
|
-
* dublês no grafo o graphify cai de 122 para 5 arestas, e esta função devolve
|
|
147
|
-
* as 122 do grafo sem testes, nenhuma a mais.
|
|
148
|
-
*
|
|
149
|
-
* Aditivo: um par que o graphify já emitiu não é repetido.
|
|
150
|
-
*
|
|
151
|
-
* @param {GraphIndex} index
|
|
152
|
-
* @param {{links?: object[]}} graph
|
|
153
|
-
* @returns {object[]} arestas sintéticas, marcadas `_recovered: true`
|
|
154
|
-
*/
|
|
81
|
+
// O resolvedor do graphify liga interface a implementação só com EXATAMENTE um implementador, e um
|
|
82
|
+
// dublê `FakeX : IX` é o segundo. Mesmo algoritmo contando só produção; aditivo, nunca repete um par.
|
|
155
83
|
function recoverDispatch(index, graph) {
|
|
156
84
|
const implementers = new Map();
|
|
157
85
|
const methodsOf = new Map();
|
|
@@ -204,24 +132,12 @@ function recoverDispatch(index, graph) {
|
|
|
204
132
|
return recovered;
|
|
205
133
|
}
|
|
206
134
|
|
|
207
|
-
/**
|
|
208
|
-
* As arestas do grafo mais as recuperadas pelo saneamento — o conjunto que
|
|
209
|
-
* todo consumidor deve percorrer.
|
|
210
|
-
*
|
|
211
|
-
* @param {GraphIndex} index
|
|
212
|
-
* @param {{links?: object[]}} graph
|
|
213
|
-
* @returns {object[]}
|
|
214
|
-
*/
|
|
135
|
+
/** As arestas do grafo mais as recuperadas pelo saneamento: o conjunto que todo consumidor percorre. */
|
|
215
136
|
export function linksOf(index, graph) {
|
|
216
137
|
const own = graph.links ?? [];
|
|
217
138
|
return index.recovered?.length ? own.concat(index.recovered) : own;
|
|
218
139
|
}
|
|
219
140
|
|
|
220
|
-
/**
|
|
221
|
-
* @param {GraphIndex} index
|
|
222
|
-
* @param {string} normLabel label já normalizado (minúsculo)
|
|
223
|
-
* @returns {'resolved'|'coalescible'|'external'|'ambiguous'|'unknown'}
|
|
224
|
-
*/
|
|
225
141
|
export function classifyLabel(index, normLabel) {
|
|
226
142
|
const entry = index.byLabel.get(normLabel);
|
|
227
143
|
if (!entry) return 'unknown';
|
|
@@ -230,13 +146,6 @@ export function classifyLabel(index, normLabel) {
|
|
|
230
146
|
return entry.stub.length > 0 ? 'coalescible' : 'resolved';
|
|
231
147
|
}
|
|
232
148
|
|
|
233
|
-
/**
|
|
234
|
-
* Para onde uma aresta REALMENTE aponta depois do saneamento.
|
|
235
|
-
*
|
|
236
|
-
* @param {GraphIndex} index
|
|
237
|
-
* @param {object} link
|
|
238
|
-
* @returns {{id: string|null, kind: 'direct'|'coalesced'|'language-disambiguated'|'external'|'ambiguous'|'unknown'}}
|
|
239
|
-
*/
|
|
240
149
|
export function resolveEdgeTarget(index, link) {
|
|
241
150
|
const target = index.byId.get(link.target);
|
|
242
151
|
if (!target) return { id: null, kind: 'unknown' };
|
|
@@ -248,10 +157,8 @@ export function resolveEdgeTarget(index, link) {
|
|
|
248
157
|
const entry = index.byLabel.get(normOf(target));
|
|
249
158
|
if (!entry || entry.real.length === 0) return { id: null, kind: 'external' };
|
|
250
159
|
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
// a alternativa (b) rejeitada na ADR-003 por errar justamente nas interfaces
|
|
254
|
-
// muito referenciadas.
|
|
160
|
+
// Uma aresta nascida num .cs só pode apontar para o candidato .cs: desambigua sem heurística de grau,
|
|
161
|
+
// que erra justamente nas interfaces muito referenciadas.
|
|
255
162
|
const originLang = languageOf(link.source_file);
|
|
256
163
|
if (originLang) {
|
|
257
164
|
const matches = entry.real.filter((n) => languageOf(n.source_file) === originLang);
|
|
@@ -261,13 +168,7 @@ export function resolveEdgeTarget(index, link) {
|
|
|
261
168
|
return { id: null, kind: 'ambiguous' };
|
|
262
169
|
}
|
|
263
170
|
|
|
264
|
-
/**
|
|
265
|
-
* label -> id. Empate real devolve as opções em vez de escolher (ADR-003).
|
|
266
|
-
*
|
|
267
|
-
* @param {GraphIndex} index
|
|
268
|
-
* @param {string} label
|
|
269
|
-
* @returns {{ok: true, id: string, node: object}|{ok: false, reason: 'not-found'|'ambiguous', options: Array<{id: string, source_file: string}>}}
|
|
270
|
-
*/
|
|
171
|
+
/** Empate real devolve as opções em vez de escolher. */
|
|
271
172
|
export function resolveLabel(index, label) {
|
|
272
173
|
const key = String(label).toLowerCase();
|
|
273
174
|
const exact = index.byLabel.get(key);
|
|
@@ -290,19 +191,6 @@ export function resolveLabel(index, label) {
|
|
|
290
191
|
};
|
|
291
192
|
}
|
|
292
193
|
|
|
293
|
-
/**
|
|
294
|
-
* Blast radius saneado: quem depende de `id`.
|
|
295
|
-
*
|
|
296
|
-
* O valor medido não é recall — contra o grep, o grafo achou ZERO arquivos a
|
|
297
|
-
* mais. É precisão: 58% menos ruído em 12 símbolos do ProspectPRO (1.092
|
|
298
|
-
* arquivos no grep, 266 usos reais) e a classificação da relação.
|
|
299
|
-
*
|
|
300
|
-
* @param {GraphIndex} index
|
|
301
|
-
* @param {{links: object[]}} graph
|
|
302
|
-
* @param {string} id
|
|
303
|
-
* @param {{prod?: boolean, excludeInheritance?: boolean}} [opts]
|
|
304
|
-
* @returns {Array<{id: string, label: string, source_file: string, source_location: string, relation: string, test: boolean}>}
|
|
305
|
-
*/
|
|
306
194
|
export function affected(index, graph, id, opts = {}) {
|
|
307
195
|
const seen = new Set();
|
|
308
196
|
const out = [];
|
|
@@ -334,15 +222,7 @@ export function affected(index, graph, id, opts = {}) {
|
|
|
334
222
|
return out;
|
|
335
223
|
}
|
|
336
224
|
|
|
337
|
-
/**
|
|
338
|
-
* Vizinhança de um nó, para `graph explain`. Cada aresta carrega a procedência
|
|
339
|
-
* (`via`), então dá para ver o que o saneamento recuperou, e `test` diz se a
|
|
340
|
-
* outra ponta é código de teste.
|
|
341
|
-
*
|
|
342
|
-
* @param {GraphIndex} index
|
|
343
|
-
* @param {{links: object[]}} graph
|
|
344
|
-
* @param {string} id
|
|
345
|
-
*/
|
|
225
|
+
/** Cada aresta carrega a procedência (`via`); `test` diz se a outra ponta é código de teste. */
|
|
346
226
|
export function neighborhood(index, graph, id) {
|
|
347
227
|
const incoming = [];
|
|
348
228
|
const outgoing = [];
|
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
|
|
|
@@ -15,7 +14,7 @@ function hasDotnet(projectPath) {
|
|
|
15
14
|
const stack = config?.project?.stack;
|
|
16
15
|
try {
|
|
17
16
|
if (stack && getBuildSteps(stack, { cwd: projectPath }).some((s) => /\bdotnet\b/.test(s.command))) return true;
|
|
18
|
-
} catch {
|
|
17
|
+
} catch {}
|
|
19
18
|
try {
|
|
20
19
|
return readdirSync(projectPath).some((n) => /\.(sln|slnx|csproj)$/i.test(n));
|
|
21
20
|
} catch {
|
|
@@ -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({
|
|
@@ -1,70 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* A propriedade que faz o `--dry-run` ser honesto está numa frase:
|
|
5
|
-
*
|
|
6
|
-
* > **o caminho real também emite.**
|
|
7
|
-
*
|
|
8
|
-
* Em modo normal cada verbo EXECUTA e registra; em `dryRun`, só registra. O
|
|
9
|
-
* resumo impresso ao fim de uma execução real sai de `list()`, não de
|
|
10
|
-
* contadores paralelos. A consequência é o ponto: um ponto de emissão
|
|
11
|
-
* esquecido some das DUAS saídas ao mesmo tempo, e o resumo de uma execução
|
|
12
|
-
* real fica visivelmente incompleto — o defeito aparece sem sequer usar o
|
|
13
|
-
* `--dry-run`.
|
|
14
|
-
*
|
|
15
|
-
* **Não há segunda travessia.** Nenhum filtro, walker ou lista de payload é
|
|
16
|
-
* reimplementado aqui. Os filtros que decidem o que instalar
|
|
17
|
-
* (`shouldInstallSkill`, `agentEligible`, `shouldInstall`) já são puros e
|
|
18
|
-
* continuam sendo os únicos. O anti-exemplar tem nome e mora neste
|
|
19
|
-
* repositório: `checkAgentsDrift` funciona como preditor porque re-deriva o
|
|
20
|
-
* conjunto elegível por conta própria e porque os dois lados chamam o mesmo
|
|
21
|
-
* renderer puro. Estender essa forma para 9 payloads + hooks + merge de
|
|
22
|
-
* settings + gitignore + índice do git é reimplementar o instalador inteiro e
|
|
23
|
-
* depender de disciplina humana para mantê-los sincronizados.
|
|
24
|
-
*
|
|
25
|
-
* **Os verbos são SÍNCRONOS de propósito.** Metade dos instaladores que eles
|
|
26
|
-
* atravessam (`installSkills`, `installAgents`, `installRulesForStack`) é
|
|
27
|
-
* síncrona; um coletor assíncrono obrigaria a tornar `installRulesForStack`
|
|
28
|
-
* async e a mudar a assinatura que `setup-infra`, `init` e os testes já usam.
|
|
29
|
-
*
|
|
30
|
-
* **O registro é a IDENTIDADE do efeito, nunca o conteúdo.** `writeFile` grava
|
|
31
|
-
* `{ verb, target }`, não os bytes: `installClaudeHooks` carimba um
|
|
32
|
-
* `generated_at` a cada execução, e comparar conteúdo faria o canário de
|
|
33
|
-
* igualdade dry × real reprovar por causa do relógio.
|
|
34
|
-
*/
|
|
1
|
+
// O caminho real também emite: o resumo de uma execução real sai de `list()`, então um ponto de
|
|
2
|
+
// emissão esquecido some das duas saídas. Registra-se a identidade do efeito, nunca o conteúdo:
|
|
3
|
+
// `installClaudeHooks` carimba `generated_at`, e comparar bytes reprovaria a igualdade dry × real.
|
|
35
4
|
|
|
36
5
|
import fs from 'fs-extra';
|
|
37
6
|
import { spawnSync } from 'node:child_process';
|
|
38
7
|
import { dirname } from 'node:path';
|
|
39
8
|
|
|
40
|
-
/**
|
|
41
|
-
* @typedef {Object} Effect
|
|
42
|
-
* @property {string} verb - ensureDir | remove | copyDir | copyFile | writeFile | writeJson | mergeJson | spawn | gitIndex
|
|
43
|
-
* @property {string} target - o caminho (ou comando) sobre o qual o efeito age
|
|
44
|
-
* @property {string} [from] - origem, para os verbos de cópia
|
|
45
|
-
* @property {string} [detail] - qualificador estável (argumentos do spawn, operação do git)
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Cria um coletor de efeitos.
|
|
50
|
-
*
|
|
51
|
-
* @param {{ dryRun?: boolean }} [options]
|
|
52
|
-
* @returns {{
|
|
53
|
-
* dryRun: boolean,
|
|
54
|
-
* ensureDir: (path: string) => void,
|
|
55
|
-
* remove: (path: string) => void,
|
|
56
|
-
* copyDir: (from: string, to: string) => void,
|
|
57
|
-
* copyFile: (from: string, to: string) => void,
|
|
58
|
-
* writeFile: (path: string, content: string) => void,
|
|
59
|
-
* writeJson: (path: string, data: object) => void,
|
|
60
|
-
* mergeJson: (path: string, patch: object) => void,
|
|
61
|
-
* spawn: (cmd: string, args: string[], options?: object) => object|null,
|
|
62
|
-
* gitIndex: (op: string, path: string, options?: object) => boolean,
|
|
63
|
-
* list: () => Effect[],
|
|
64
|
-
* }}
|
|
65
|
-
*/
|
|
66
9
|
export function createEffects({ dryRun = false } = {}) {
|
|
67
|
-
/** @type {Effect[]} */
|
|
68
10
|
const effects = [];
|
|
69
11
|
|
|
70
12
|
const record = (verb, target, extra = {}) => {
|
|
@@ -118,13 +60,7 @@ export function createEffects({ dryRun = false } = {}) {
|
|
|
118
60
|
}
|
|
119
61
|
},
|
|
120
62
|
|
|
121
|
-
|
|
122
|
-
* Leitura + fusão rasa + escrita, como UM efeito.
|
|
123
|
-
*
|
|
124
|
-
* A leitura acontece nos dois modos (ler não muda nada); só a escrita é
|
|
125
|
-
* suprimida em dry. É assim que `~/.claude/settings.json` — um arquivo do
|
|
126
|
-
* usuário, FORA do projeto — é atualizado sem que o dry o toque.
|
|
127
|
-
*/
|
|
63
|
+
// A leitura acontece nos dois modos; só a escrita é suprimida em dry.
|
|
128
64
|
mergeJson(path, patch) {
|
|
129
65
|
record('mergeJson', path);
|
|
130
66
|
if (dryRun) return;
|
|
@@ -138,21 +74,9 @@ export function createEffects({ dryRun = false } = {}) {
|
|
|
138
74
|
fs.writeJsonSync(path, { ...current, ...patch }, { spaces: 2 });
|
|
139
75
|
},
|
|
140
76
|
|
|
141
|
-
|
|
142
|
-
* @param {string} cmd
|
|
143
|
-
* @param {string[]} args
|
|
144
|
-
* @param {{ cwd?: string, dryRunArgs?: string[] }} [options]
|
|
145
|
-
* `dryRunArgs` é a variante SÓ-LEITURA do mesmo comando (por exemplo
|
|
146
|
-
* `--check`). Em dry ela é executada no lugar; sem ela, nada roda.
|
|
147
|
-
* O REGISTRO é o mesmo nos dois modos: o efeito previsto é o comando
|
|
148
|
-
* real, não a sua sonda.
|
|
149
|
-
*/
|
|
77
|
+
// `dryRunArgs`: variante só-leitura do comando, executada no lugar em dry; o registro é o comando real.
|
|
150
78
|
spawn(cmd, args = [], options = {}) {
|
|
151
|
-
// `args` viaja
|
|
152
|
-
// humano; quebrá-lo por espaço para descobrir onde o spawn escreve é o
|
|
153
|
-
// bug que um caminho como `R:\Polymorphism Tech\...` produz em silêncio,
|
|
154
|
-
// e que o relatório mostrou pondo um efeito do PACOTE da CLI no grupo
|
|
155
|
-
// "no projeto".
|
|
79
|
+
// `args` viaja além do `detail`: quebrar o `detail` por espaço erra caminhos com espaço.
|
|
156
80
|
record('spawn', cmd, { detail: args.join(' '), args: [...args] });
|
|
157
81
|
const { cwd, dryRunArgs } = options;
|
|
158
82
|
if (dryRun) {
|
|
@@ -162,11 +86,7 @@ export function createEffects({ dryRun = false } = {}) {
|
|
|
162
86
|
return spawnSync(cmd, args, { cwd, encoding: 'utf8' });
|
|
163
87
|
},
|
|
164
88
|
|
|
165
|
-
|
|
166
|
-
* Mutação do índice do git (`git rm --cached`, etc.). A SONDA que decide
|
|
167
|
-
* se há o que fazer fica fora daqui de propósito: sondar é ler, e ler
|
|
168
|
-
* acontece nos dois modos.
|
|
169
|
-
*/
|
|
89
|
+
// A sonda que decide se há o que fazer fica fora daqui: sondar é ler, e ler acontece nos dois modos.
|
|
170
90
|
gitIndex(op, path, options = {}) {
|
|
171
91
|
record('gitIndex', path, { detail: op });
|
|
172
92
|
if (dryRun) return true;
|
|
@@ -182,12 +102,7 @@ export function createEffects({ dryRun = false } = {}) {
|
|
|
182
102
|
};
|
|
183
103
|
}
|
|
184
104
|
|
|
185
|
-
|
|
186
|
-
* Coletor no-op-de-registro para chamadores que não passam um: executa
|
|
187
|
-
* normalmente e registra numa lista descartada. Existe para que assinaturas
|
|
188
|
-
* novas de `installSkills`/`installAgents`/`installRulesForStack` continuem
|
|
189
|
-
* funcionando para `setup-infra` e `init` sem mudança de comportamento.
|
|
190
|
-
*/
|
|
105
|
+
// Executa e registra numa lista descartada, para chamadores que não passam um coletor.
|
|
191
106
|
export function realEffects() {
|
|
192
107
|
return createEffects({ dryRun: false });
|
|
193
108
|
}
|