@chemx/starter-kit 26.10.8-344 → 26.10.10-75
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/AGENTS.md +135 -32
- package/README.md +253 -199
- package/blueprints/atoms/a-button.svelte +11 -9
- package/blueprints/atoms/a-button.vue +2 -1
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.svelte +8 -4
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.tsx +8 -4
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.vue +8 -4
- package/blueprints/molecule-capsule/m-sample-card.svelte +2 -1
- package/blueprints/molecule-capsule/m-sample-card.tsx +2 -1
- package/blueprints/molecule-capsule/m-sample-card.vue +4 -2
- package/blueprints/workflows/chemx-audit.yml +15 -46
- package/cli/agent-json.js +40 -0
- package/cli/apply-edits.js +195 -0
- package/cli/audit/ai-slop-detector.js +62 -35
- package/cli/audit/ast-passes.js +52 -0
- package/cli/audit/ast-visitors.js +142 -83
- package/cli/audit/audit-plain.js +26 -0
- package/cli/audit/audit-summary.js +16 -3
- package/cli/audit/autofix-content.js +122 -0
- package/cli/audit/autofix.js +74 -159
- package/cli/audit/budget-rules.js +84 -0
- package/cli/audit/catch-predicates.js +51 -0
- package/cli/audit/chemx-dir.js +76 -0
- package/cli/audit/clone-detector.js +4 -2
- package/cli/audit/comment-regions.js +83 -0
- package/cli/audit/coverage.js +48 -0
- package/cli/audit/csharp-analyzer.js +47 -22
- package/cli/audit/discussion-store.js +9 -4
- package/cli/audit/extended-text-patterns.js +104 -54
- package/cli/audit/extended-visitors.js +26 -12
- package/cli/audit/feed.d.ts +77 -0
- package/cli/audit/feed.js +146 -0
- package/cli/audit/gate-delta.js +91 -0
- package/cli/audit/gate-verdict.js +25 -3
- package/cli/audit/history.d.ts +14 -2
- package/cli/audit/history.js +89 -101
- package/cli/audit/hook-shape-validator.js +18 -9
- package/cli/audit/lexicon-predicates.js +125 -0
- package/cli/audit/lifecycle-predicates.js +106 -0
- package/cli/audit/line-budgets.js +154 -0
- package/cli/audit/metrics.js +56 -37
- package/cli/audit/mutable-ref-predicate.js +54 -0
- package/cli/audit/parseable-code.js +11 -0
- package/cli/audit/pattern-detector.js +56 -28
- package/cli/audit/project-figures.js +28 -0
- package/cli/audit/prompt-rule-lines.js +46 -0
- package/cli/audit/prompts.js +74 -46
- package/cli/audit/prop-surface.js +74 -0
- package/cli/audit/ratchet.js +112 -23
- package/cli/audit/render-depth.js +79 -0
- package/cli/audit/reporter-banner.js +7 -4
- package/cli/audit/reporter-grades.js +52 -34
- package/cli/audit/reporter-grouping.js +10 -5
- package/cli/audit/reporter-markdown.js +16 -8
- package/cli/audit/reporter-sections.js +31 -16
- package/cli/audit/reporter-summary.js +28 -16
- package/cli/audit/reporter-utils.js +54 -30
- package/cli/audit/roadmap.js +20 -15
- package/cli/audit/rule-overrides.js +78 -0
- package/cli/audit/rule-pillars.js +43 -0
- package/cli/audit/rule-revisions.js +42 -0
- package/cli/audit/rules-helpers.js +13 -63
- package/cli/audit/rules-predicates.d.ts +1 -0
- package/cli/audit/rules-predicates.js +84 -64
- package/cli/audit/rules-registry.js +94 -10
- package/cli/audit/rules.js +92 -171
- package/cli/audit/shallow-catch-csharp.js +49 -0
- package/cli/audit/shallow-catch-escalation.js +157 -0
- package/cli/audit/shallow-catch-reads.js +116 -0
- package/cli/audit/social-gh.js +18 -9
- package/cli/audit/social-git.js +82 -40
- package/cli/audit/social-http.js +17 -9
- package/cli/audit/social-publisher.js +14 -7
- package/cli/audit/social.js +39 -30
- package/cli/audit/staged-delta.js +67 -0
- package/cli/audit/status-file.js +67 -0
- package/cli/audit/structural-weight-evaluator.js +17 -29
- package/cli/audit/structural-weight.js +30 -13
- package/cli/audit/suppressions.js +130 -0
- package/cli/audit/template-rules.js +82 -0
- package/cli/audit/types.d.ts +24 -1
- package/cli/audit-engine.js +128 -0
- package/cli/audit-preflight-git.js +15 -1
- package/cli/audit-preflight.js +6 -4
- package/cli/audit-scan.js +180 -0
- package/cli/audit-scope.js +31 -14
- package/cli/audit.js +6 -201
- package/cli/babel-lazy.js +41 -0
- package/cli/badge.js +9 -6
- package/cli/banner.js +37 -0
- package/cli/build/child-registry.js +57 -0
- package/cli/build/executor.js +122 -48
- package/cli/build.js +75 -25
- package/cli/cli-args.js +107 -0
- package/cli/columnar.js +6 -3
- package/cli/commands/cmd-audit-each.js +164 -0
- package/cli/commands/cmd-audit-feed.js +78 -0
- package/cli/commands/cmd-audit.js +136 -57
- package/cli/commands/cmd-batch.js +60 -0
- package/cli/commands/cmd-check.js +74 -0
- package/cli/commands/cmd-project.js +18 -9
- package/cli/commands/cmd-router.js +148 -32
- package/cli/commands/cmd-show.js +56 -0
- package/cli/commands/cmd-staged-delta.js +27 -0
- package/cli/commands/cmd-wrappers-files.js +77 -0
- package/cli/commands/cmd-wrappers-git.js +122 -0
- package/cli/commands/cmd-wrappers-json.js +101 -0
- package/cli/commands/cmd-wrappers.js +7 -322
- package/cli/commands/unknown-flags.js +228 -0
- package/cli/commands-schema-badge.js +73 -0
- package/cli/commands-schema-commit.js +21 -0
- package/cli/commands-schema-edit.js +106 -0
- package/cli/commands-schema-host.js +65 -0
- package/cli/commands-schema-ops.js +127 -0
- package/cli/commands-schema-patterns.js +69 -0
- package/cli/commands-schema-report.js +18 -0
- package/cli/commands-schema-search.js +121 -0
- package/cli/commands-schema-setup.js +30 -0
- package/cli/commands-schema-verify.js +89 -0
- package/cli/commands-schema-wrappers.js +131 -0
- package/cli/commands-schema.js +26 -408
- package/cli/comment-ranges.js +108 -0
- package/cli/commit/commit-args.js +73 -0
- package/cli/commit/commit-cli.js +25 -0
- package/cli/commit/commit-facts.js +49 -0
- package/cli/commit/commit-git.js +98 -0
- package/cli/commit/commit-index.js +35 -0
- package/cli/commit/commit-message.js +52 -0
- package/cli/commit/commit-record.js +68 -0
- package/cli/commit/commit-run.js +160 -0
- package/cli/commit/commit-validate.js +62 -0
- package/cli/config/index.js +54 -8
- package/cli/config/loader.js +77 -8
- package/cli/config/profiles.js +7 -0
- package/cli/conflicts-cli.js +118 -0
- package/cli/conflicts.js +104 -0
- package/cli/create.js +11 -6
- package/cli/db-project-stamp.js +124 -0
- package/cli/docs-check/command-tree.js +27 -0
- package/cli/docs-check/extract.js +151 -0
- package/cli/docs-check/resolve.js +85 -0
- package/cli/docs-check/run.js +88 -0
- package/cli/doctor/check-env.js +43 -0
- package/cli/doctor/check-host.js +115 -0
- package/cli/doctor/check-index.js +93 -0
- package/cli/doctor/check-mcp.js +78 -0
- package/cli/doctor/doctor-cli.js +60 -0
- package/cli/doctor/kit-locate.js +40 -0
- package/cli/doctor/proc-scan.js +66 -0
- package/cli/edit-atomic.js +75 -0
- package/cli/edit-diff.js +98 -0
- package/cli/edit-guardrails.js +77 -0
- package/cli/edit-locks.js +128 -0
- package/cli/embeddings/vectorizer.js +9 -5
- package/cli/errors/catcher.js +45 -52
- package/cli/errors/formatter.js +14 -10
- package/cli/errors/policy.js +26 -0
- package/cli/errors/publisher.js +5 -1
- package/cli/errors/report-output.js +67 -0
- package/cli/errors/sanitizer.js +52 -3
- package/cli/errors/storage.js +17 -5
- package/cli/explode-importers.js +102 -0
- package/cli/explode-path-args.js +115 -0
- package/cli/explode-plan.js +153 -0
- package/cli/explode-prologue.js +43 -0
- package/cli/explode-relocate.js +73 -0
- package/cli/exploder.js +205 -193
- package/cli/forge/anchors.js +50 -0
- package/cli/forge/audit-forge.js +58 -0
- package/cli/forge/binding-walk.js +84 -0
- package/cli/forge/bindings.js +238 -0
- package/cli/forge/blueprint-cli.js +153 -0
- package/cli/forge/blueprint-context.js +69 -0
- package/cli/forge/blueprint-members.js +82 -0
- package/cli/forge/blueprint-store.js +106 -0
- package/cli/forge/blueprint-target.js +44 -0
- package/cli/forge/blueprint.js +276 -0
- package/cli/forge/body-end-cache.js +34 -0
- package/cli/forge/body-ends.js +86 -0
- package/cli/forge/canon-inline.js +342 -0
- package/cli/forge/canon-logic.js +106 -0
- package/cli/forge/canon-nodes.js +270 -0
- package/cli/forge/canon-print.js +120 -0
- package/cli/forge/canonicalize.js +49 -0
- package/cli/forge/conventions.js +51 -0
- package/cli/forge/drift.js +120 -0
- package/cli/forge/exclusions.js +21 -0
- package/cli/forge/exits.js +76 -0
- package/cli/forge/facets.js +86 -0
- package/cli/forge/file-units.js +53 -0
- package/cli/forge/fingerprint-file.js +52 -0
- package/cli/forge/fingerprint-session.js +215 -0
- package/cli/forge/fingerprint-sync.js +74 -0
- package/cli/forge/fingerprint-visitors.js +66 -0
- package/cli/forge/fixtures/heal/a7-dry-run.diff.txt +179 -0
- package/cli/forge/fixtures/heal/cli/commit/commit-facts.js.txt +49 -0
- package/cli/forge/fixtures/heal/cli/doctor/check-host.js.txt +117 -0
- package/cli/forge/fixtures/heal/cli/doctor/kit-locate.js.txt +42 -0
- package/cli/forge/fixtures/heal/cli/hooks/guard-paths.js.txt +80 -0
- package/cli/forge/fixtures/heal/cli/hooks/project-status.js.txt +62 -0
- package/cli/forge/fixtures/heal/cli/main.js.txt +169 -0
- package/cli/forge/fixtures/heal/cli/mcp/context.js.txt +81 -0
- package/cli/forge/fixtures/heal/cli/mcp/installer-report.js.txt +47 -0
- package/cli/forge/fixtures/heal/cli/path-scope.js.txt +169 -0
- package/cli/forge/fixtures/heal/cli/project-detector.js.txt +364 -0
- package/cli/forge/fixtures/heal/cli/project-markers.js.txt +42 -0
- package/cli/forge/fixtures/heal/cli/team/coordination-root.js.txt +161 -0
- package/cli/forge/fixtures/heal/cli/team/usage-reader.js.txt +109 -0
- package/cli/forge/fixtures/heal/cli/test-slots.js.txt +129 -0
- package/cli/forge/fixtures/social-gh.js.txt +131 -0
- package/cli/forge/fixtures/team-flags.js.txt +214 -0
- package/cli/forge/fold.js +199 -0
- package/cli/forge/forge-groups.js +200 -0
- package/cli/forge/forge-report.js +73 -0
- package/cli/forge/fuzz/binding-hook.js +36 -0
- package/cli/forge/fuzz/choices.js +40 -0
- package/cli/forge/fuzz/classes.js +41 -0
- package/cli/forge/fuzz/coverage.js +26 -0
- package/cli/forge/fuzz/gen-alias.js +61 -0
- package/cli/forge/fuzz/gen-control.js +73 -0
- package/cli/forge/fuzz/gen-kit.js +75 -0
- package/cli/forge/fuzz/gen-logic.js +77 -0
- package/cli/forge/fuzz/gen-mixed.js +204 -0
- package/cli/forge/fuzz/gen-modules.js +80 -0
- package/cli/forge/fuzz/gen-objects.js +92 -0
- package/cli/forge/fuzz/gen-scope.js +131 -0
- package/cli/forge/fuzz/gen-templates.js +87 -0
- package/cli/forge/fuzz/harness.js +314 -0
- package/cli/forge/fuzz/pair-check.js +115 -0
- package/cli/forge/fuzz/resolve.js +32 -0
- package/cli/forge/fuzz/run.js +121 -0
- package/cli/forge/fuzz/sandbox.js +108 -0
- package/cli/forge/fuzz/seeds.js +119 -0
- package/cli/forge/fuzz/slow-shard.js +60 -0
- package/cli/forge/fuzz/template-oracle.js +148 -0
- package/cli/forge/fuzz/transpile.js +61 -0
- package/cli/forge/gates.js +115 -0
- package/cli/forge/group-shape.js +137 -0
- package/cli/forge/group-store.js +160 -0
- package/cli/forge/group.js +280 -0
- package/cli/forge/gt-sandbox.js +83 -0
- package/cli/forge/gt-scaffold.js +110 -0
- package/cli/forge/hash-labels.js +117 -0
- package/cli/forge/hash.js +119 -0
- package/cli/forge/heal-apply.js +170 -0
- package/cli/forge/heal-cli.js +132 -0
- package/cli/forge/heal-leases.js +52 -0
- package/cli/forge/heal-locate.js +70 -0
- package/cli/forge/heal-match.js +208 -0
- package/cli/forge/heal-ops.js +197 -0
- package/cli/forge/heal-plan.js +143 -0
- package/cli/forge/heal-sandbox.js +126 -0
- package/cli/forge/heal-specs.js +80 -0
- package/cli/forge/heal-store.js +80 -0
- package/cli/forge/heal-text.js +60 -0
- package/cli/forge/heal-typecheck.js +108 -0
- package/cli/forge/heal-undo.js +74 -0
- package/cli/forge/heal-verify.js +148 -0
- package/cli/forge/hole-kinds.js +126 -0
- package/cli/forge/inline-mode.js +6 -0
- package/cli/forge/inline-on.setup.js +4 -0
- package/cli/forge/lgg-stage.js +125 -0
- package/cli/forge/lgg.js +197 -0
- package/cli/forge/library-match.js +74 -0
- package/cli/forge/murmur.js +86 -0
- package/cli/forge/naming.js +101 -0
- package/cli/forge/pattern-schema-ddl.js +157 -0
- package/cli/forge/placement.js +165 -0
- package/cli/forge/rank.js +174 -0
- package/cli/forge/refine.js +93 -0
- package/cli/forge/rejected-members.js +92 -0
- package/cli/forge/rejects.js +77 -0
- package/cli/forge/root-shapes.js +84 -0
- package/cli/forge/run-cache.js +145 -0
- package/cli/forge/sibling-blocks.js +41 -0
- package/cli/forge/siblings.js +140 -0
- package/cli/forge/store.js +180 -0
- package/cli/forge/template-normalize.js +209 -0
- package/cli/forge/template-roles.js +86 -0
- package/cli/forge/template-units.js +148 -0
- package/cli/forge/templates.js +42 -0
- package/cli/forge/unify-step.js +65 -0
- package/cli/forge/unit-floor.js +74 -0
- package/cli/forge/unit-hash.js +229 -0
- package/cli/forge/unit-trees.js +153 -0
- package/cli/forge/units.js +261 -0
- package/cli/forge/windows.js +129 -0
- package/cli/friction/friction-cli.js +71 -0
- package/cli/friction/friction-export.js +54 -0
- package/cli/friction/friction-log.js +54 -0
- package/cli/friction/usage-classify.js +56 -0
- package/cli/friction/usage-report.js +86 -0
- package/cli/friction/wrong-call.js +12 -0
- package/cli/fs-json.js +17 -0
- package/cli/generator-compact.js +55 -0
- package/cli/generator-help.js +16 -15
- package/cli/generator-indexer.js +2 -1
- package/cli/generator-jig-cli.js +11 -7
- package/cli/generator-jig.js +38 -33
- package/cli/generator-templates/archetypes/index.js +30 -13
- package/cli/generator-templates/archetypes/vector-matcher.js +8 -4
- package/cli/generator-templates/compact.js +4 -2
- package/cli/generator-templates/controller-converters.js +23 -14
- package/cli/generator-templates/controller.js +10 -5
- package/cli/generator-templates/hooks.js +4 -2
- package/cli/generator-templates/naming.js +2 -1
- package/cli/generator-templates/react.js +2 -1
- package/cli/generator-templates/specs.js +4 -2
- package/cli/generator-templates/svelte.js +4 -2
- package/cli/generator-templates/types.js +6 -3
- package/cli/generator-templates/views.js +4 -2
- package/cli/generator-templates/vue.js +4 -2
- package/cli/generator-writes.js +24 -0
- package/cli/generator.d.ts +1 -1
- package/cli/generator.js +86 -127
- package/cli/git-file-listing.js +69 -0
- package/cli/help-args.js +18 -0
- package/cli/help.d.ts +7 -3
- package/cli/help.js +94 -149
- package/cli/hooks/bypass-log.js +44 -0
- package/cli/hooks/claude-post-edit.js +79 -0
- package/cli/hooks/claude-pre-tool.js +178 -0
- package/cli/hooks/claude-settings-merge.js +101 -0
- package/cli/hooks/dispatch-identity.js +125 -0
- package/cli/hooks/entry.js +181 -0
- package/cli/hooks/foreign-identity.js +60 -0
- package/cli/hooks/guard-args.js +55 -0
- package/cli/hooks/guard-cases.js +94 -0
- package/cli/hooks/guard-config.js +43 -0
- package/cli/hooks/guard-invocation.js +106 -0
- package/cli/hooks/guard-paths.js +80 -0
- package/cli/hooks/guard-route.js +211 -0
- package/cli/hooks/guard-rules-nudge.js +37 -0
- package/cli/hooks/guard-rules-reads.js +66 -0
- package/cli/hooks/guard-rules-shell.js +239 -0
- package/cli/hooks/guard-rules.js +114 -0
- package/cli/hooks/hook-commands.js +21 -0
- package/cli/hooks/install-hooks-apply.js +36 -0
- package/cli/hooks/install-hooks-cli.js +100 -0
- package/cli/hooks/install-hooks-config.js +48 -0
- package/cli/hooks/install-hooks-pins.js +66 -0
- package/cli/hooks/install-hooks-plan.js +56 -0
- package/cli/hooks/install-hooks-status.js +7 -0
- package/cli/hooks/interpreter-writes.js +195 -0
- package/cli/hooks/launcher.js +60 -0
- package/cli/hooks/mcp-json-merge.js +39 -0
- package/cli/hooks/native-edit-lock.js +40 -0
- package/cli/hooks/native-tool-policy.js +152 -0
- package/cli/hooks/out-of-band-edits.js +141 -0
- package/cli/hooks/post-edit-scope.js +43 -0
- package/cli/hooks/project-status.js +59 -0
- package/cli/hooks/repo-membership.js +32 -0
- package/cli/hooks/run-hook.js +79 -0
- package/cli/hooks/session-identity.js +153 -0
- package/cli/hooks/session-start.js +50 -0
- package/cli/hooks/shell-lexer-readers.js +76 -0
- package/cli/hooks/shell-lexer-state.js +59 -0
- package/cli/hooks/shell-lexer.js +110 -0
- package/cli/hooks/shell-parse.js +232 -0
- package/cli/hooks/statusline.js +27 -0
- package/cli/hooks/xatoms-hints.js +38 -0
- package/cli/host-protocol.js +109 -0
- package/cli/host-shims.js +9 -8
- package/cli/index-admission.js +41 -0
- package/cli/index-freshness.js +83 -0
- package/cli/index-row-check.js +58 -0
- package/cli/index.js +52 -150
- package/cli/installer-templates.js +67 -75
- package/cli/installer.d.ts +16 -1
- package/cli/installer.js +159 -58
- package/cli/languages.js +8 -4
- package/cli/lattice-directives.js +24 -0
- package/cli/lattice-payload.js +34 -0
- package/cli/{tesseract-state.js → lattice-state.js} +8 -4
- package/cli/lease-view.js +48 -0
- package/cli/library/entry-fp.js +42 -0
- package/cli/library/entry-schema.js +90 -0
- package/cli/library/library-tasks.js +25 -0
- package/cli/library/registry.js +56 -0
- package/cli/library/reverify.js +56 -0
- package/cli/library/verify-checks.js +89 -0
- package/cli/library/verify.js +81 -0
- package/cli/license-config.js +124 -0
- package/cli/license.js +168 -135
- package/cli/line-count.js +23 -0
- package/cli/literal-replace.js +107 -0
- package/cli/main.js +166 -0
- package/cli/mcp/antigravity.js +11 -9
- package/cli/mcp/batch.js +59 -0
- package/cli/mcp/call-args.js +75 -0
- package/cli/mcp/call-effects.js +57 -0
- package/cli/mcp/call-scope.js +70 -62
- package/cli/mcp/context.js +81 -0
- package/cli/mcp/envelope.js +62 -0
- package/cli/mcp/fingerprint.js +26 -0
- package/cli/mcp/fresh-entry.js +34 -0
- package/cli/mcp/fresh-protocol.js +37 -0
- package/cli/mcp/fresh-runner.js +40 -0
- package/cli/mcp/help.js +53 -0
- package/cli/mcp/index.js +9 -5
- package/cli/mcp/inflight.js +47 -0
- package/cli/mcp/installer-jsonc.js +64 -0
- package/cli/mcp/installer-package.js +54 -0
- package/cli/mcp/installer-report.js +47 -0
- package/cli/mcp/installer-write.js +117 -0
- package/cli/mcp/installer.js +88 -187
- package/cli/mcp/manifests-analysis.js +156 -0
- package/cli/mcp/manifests-runners.js +48 -0
- package/cli/mcp/manifests-team.js +100 -0
- package/cli/mcp/manifests.js +69 -309
- package/cli/mcp/offload-worker.js +11 -0
- package/cli/mcp/offload.js +18 -0
- package/cli/mcp/patterns-cli.js +76 -0
- package/cli/mcp/patterns-forge-cli.js +120 -0
- package/cli/mcp/prompts.js +13 -10
- package/cli/mcp/resources.js +8 -35
- package/cli/mcp/roots.js +46 -0
- package/cli/mcp/scorecard-worker.js +7 -0
- package/cli/mcp/scorecard.js +42 -0
- package/cli/mcp/server-info.js +28 -0
- package/cli/mcp/server.js +91 -291
- package/cli/mcp/spec-harness.js +62 -0
- package/cli/mcp/stale-exec.js +48 -0
- package/cli/mcp/staleness.js +26 -0
- package/cli/mcp/stdio.js +141 -0
- package/cli/mcp/tool-call.js +73 -0
- package/cli/mcp/tools-audit-feed.js +33 -0
- package/cli/mcp/tools-audit.js +13 -7
- package/cli/mcp/tools-generate.js +3 -3
- package/cli/mcp/tools-lazy.js +39 -0
- package/cli/mcp/tools-patch.js +93 -21
- package/cli/mcp/tools-patterns.js +6 -3
- package/cli/mcp/tools-project.js +8 -4
- package/cli/mcp/tools-q-modes.js +15 -14
- package/cli/mcp/tools-q.js +94 -33
- package/cli/mcp/tools-read.js +30 -80
- package/cli/mcp/tools-team-feed.js +10 -8
- package/cli/mcp/tools-team-locks.js +22 -10
- package/cli/mcp/tools-team-mailbox.js +8 -7
- package/cli/mcp/tools-team-tasks.js +125 -38
- package/cli/mcp/tools-team.js +14 -7
- package/cli/mcp/tools-verify.js +44 -15
- package/cli/mcp/tools-write.js +11 -16
- package/cli/mcp/tools.js +202 -68
- package/cli/mcp/worker-run.js +24 -0
- package/cli/missing-imports.js +52 -0
- package/cli/mutation-args.js +96 -0
- package/cli/mutators.js +164 -61
- package/cli/navigator-actions.js +19 -13
- package/cli/navigator-banner-helpers.js +1 -26
- package/cli/navigator-banner.js +5 -3
- package/cli/navigator-conversion.js +23 -12
- package/cli/navigator-grades.js +70 -35
- package/cli/navigator-guide.js +13 -11
- package/cli/navigator-menu.js +80 -166
- package/cli/navigator-paged.js +15 -8
- package/cli/navigator-sections.js +32 -0
- package/cli/navigator-share.js +53 -39
- package/cli/navigator.d.ts +25 -5
- package/cli/navigator.js +14 -41
- package/cli/network-policy.js +72 -0
- package/cli/network-recorder.fixture.mjs +35 -0
- package/cli/outline/ast-outline.js +120 -0
- package/cli/outline/style-outline.js +42 -0
- package/cli/outline/vue-outline.js +88 -0
- package/cli/patcher-cli.js +255 -0
- package/cli/patcher.d.ts +55 -24
- package/cli/patcher.js +167 -358
- package/cli/path-scope.js +78 -22
- package/cli/patterns/fixtures/gt/A1.txt +109 -0
- package/cli/patterns/fixtures/gt/A10.txt +13 -0
- package/cli/patterns/fixtures/gt/A11.txt +10 -0
- package/cli/patterns/fixtures/gt/A12.txt +29 -0
- package/cli/patterns/fixtures/gt/A13.txt +39 -0
- package/cli/patterns/fixtures/gt/A14.txt +45 -0
- package/cli/patterns/fixtures/gt/A15.txt +70 -0
- package/cli/patterns/fixtures/gt/A16.txt +59 -0
- package/cli/patterns/fixtures/gt/A17.txt +29 -0
- package/cli/patterns/fixtures/gt/A18.txt +9 -0
- package/cli/patterns/fixtures/gt/A19.txt +29 -0
- package/cli/patterns/fixtures/gt/A2.txt +28 -0
- package/cli/patterns/fixtures/gt/A20.txt +83 -0
- package/cli/patterns/fixtures/gt/A21.txt +138 -0
- package/cli/patterns/fixtures/gt/A22.txt +32 -0
- package/cli/patterns/fixtures/gt/A23.txt +37 -0
- package/cli/patterns/fixtures/gt/A24.txt +67 -0
- package/cli/patterns/fixtures/gt/A25.txt +41 -0
- package/cli/patterns/fixtures/gt/A26.txt +29 -0
- package/cli/patterns/fixtures/gt/A3.txt +17 -0
- package/cli/patterns/fixtures/gt/A4.txt +44 -0
- package/cli/patterns/fixtures/gt/A5.txt +32 -0
- package/cli/patterns/fixtures/gt/A6.txt +15 -0
- package/cli/patterns/fixtures/gt/A7.txt +79 -0
- package/cli/patterns/fixtures/gt/A8.txt +41 -0
- package/cli/patterns/fixtures/gt/A9.txt +42 -0
- package/cli/patterns/fixtures/gt/B1.txt +11 -0
- package/cli/patterns/fixtures/gt/B10.txt +41 -0
- package/cli/patterns/fixtures/gt/B11.txt +7 -0
- package/cli/patterns/fixtures/gt/B2.txt +19 -0
- package/cli/patterns/fixtures/gt/B3.txt +70 -0
- package/cli/patterns/fixtures/gt/B4.txt +55 -0
- package/cli/patterns/fixtures/gt/B5.txt +21 -0
- package/cli/patterns/fixtures/gt/B6.txt +15 -0
- package/cli/patterns/fixtures/gt/B7.txt +24 -0
- package/cli/patterns/fixtures/gt/B8.txt +40 -0
- package/cli/patterns/fixtures/gt/B9.txt +18 -0
- package/cli/patterns/fixtures/gt/C1.txt +26 -0
- package/cli/patterns/fixtures/gt/C2.txt +33 -0
- package/cli/patterns/fixtures/gt/C3.txt +26 -0
- package/cli/patterns/fixtures/gt/C4.txt +7 -0
- package/cli/patterns/fixtures/gt/C5.txt +29 -0
- package/cli/patterns/fixtures/gt/C6.txt +7 -0
- package/cli/patterns/fixtures/gt/C7.txt +18 -0
- package/cli/patterns/fixtures/gt/labels.json +1837 -0
- package/cli/patterns/gt-build.js +55 -0
- package/cli/patterns/gt-locations.js +76 -0
- package/cli/patterns/gt-resolve.js +66 -0
- package/cli/patterns/gt-score-cli.js +80 -0
- package/cli/patterns/gt-score.js +188 -0
- package/cli/patterns/gt-text.js +79 -0
- package/cli/pillars-wizard.js +53 -24
- package/cli/pillars-write-guard.js +4 -1
- package/cli/postinstall.js +22 -19
- package/cli/project-detector.js +60 -35
- package/cli/project-markers.js +42 -0
- package/cli/project-scope.js +20 -0
- package/cli/read-revision.js +70 -0
- package/cli/reader-cards-gate.js +29 -0
- package/cli/reader-cards.js +153 -0
- package/cli/reader-cli.js +45 -18
- package/cli/reader-format.js +48 -0
- package/cli/reader-logic.js +128 -250
- package/cli/reader.js +210 -221
- package/cli/request-context.js +9 -0
- package/cli/result-status.js +23 -0
- package/cli/rules.js +81 -0
- package/cli/scaffold.js +80 -51
- package/cli/scan-ignore.js +12 -0
- package/cli/search-args.js +102 -0
- package/cli/search-ast-module.js +103 -0
- package/cli/search-ast.js +75 -112
- package/cli/search-commands-blast.js +70 -0
- package/cli/search-commands-graph.js +57 -105
- package/cli/search-commands-hazards.js +105 -0
- package/cli/search-commands-literal.js +102 -0
- package/cli/search-commands-semantic.js +39 -27
- package/cli/search-commands.js +93 -186
- package/cli/search-db.js +52 -252
- package/cli/search-debug.js +13 -0
- package/cli/search-graph-edges.js +112 -0
- package/cli/search-index-meta.js +66 -0
- package/cli/search-index-write.js +153 -0
- package/cli/search-literal-files.js +64 -0
- package/cli/search-literal.js +150 -0
- package/cli/search-output.js +88 -0
- package/cli/search-queries-graph.js +120 -193
- package/cli/search-queries-semantic.js +41 -14
- package/cli/search-queries-similar.js +2 -1
- package/cli/search-queries.js +46 -21
- package/cli/search-query-view.js +67 -0
- package/cli/search-rank.js +54 -0
- package/cli/search-replace-blocks.js +120 -0
- package/cli/search-resolve.js +52 -0
- package/cli/search-root.js +78 -0
- package/cli/search-scan.js +102 -0
- package/cli/search-schema-ddl.js +172 -0
- package/cli/search-schema.js +135 -220
- package/cli/search-session.js +11 -0
- package/cli/search-sync-paths.js +78 -0
- package/cli/search-sync-plan.js +63 -0
- package/cli/search-sync-rows.js +96 -0
- package/cli/search-sync.js +128 -0
- package/cli/search-tokenizer.js +8 -4
- package/cli/search.d.ts +26 -5
- package/cli/search.js +156 -410
- package/cli/sfc/component-resolver.js +96 -0
- package/cli/sfc/import-coverage.js +24 -0
- package/cli/sfc/module-aliases.js +102 -0
- package/cli/sfc/script-asts.js +51 -0
- package/cli/sfc/sfc-metadata.js +104 -0
- package/cli/sfc/sfc-parse.js +101 -0
- package/cli/sfc/svelte-parse.js +46 -0
- package/cli/sfc/template-walk.js +78 -0
- package/cli/sfc-scripts.js +60 -0
- package/cli/share-consent.js +49 -0
- package/cli/share-outcome.js +57 -0
- package/cli/silence-warnings.js +2 -1
- package/cli/source-parse.js +130 -0
- package/cli/spec-isolated-home.js +17 -0
- package/cli/spec-support/import-trace.mjs +22 -0
- package/cli/spec-support/run-cli.js +58 -0
- package/cli/sqlite-memory.js +47 -0
- package/cli/status-command.js +107 -0
- package/cli/symbol-locator.js +121 -0
- package/cli/team/agent-identity.js +58 -0
- package/cli/team/audit-run-adoption.js +117 -0
- package/cli/team/audit-run-bypass.js +177 -0
- package/cli/team/audit-run-calls.js +108 -0
- package/cli/team/audit-run-db.js +181 -0
- package/cli/team/audit-run-identity.js +80 -0
- package/cli/team/audit-run-invocations.js +130 -0
- package/cli/team/audit-run-protocol.js +258 -0
- package/cli/team/audit-run-render.js +107 -0
- package/cli/team/audit-run-shas.js +179 -0
- package/cli/team/audit-run.js +203 -0
- package/cli/team/claim-ignore-deps.js +16 -0
- package/cli/team/coordination-busy.js +164 -0
- package/cli/team/coordination-db.js +85 -0
- package/cli/team/coordination-fixture.js +53 -0
- package/cli/team/coordination-repos.js +72 -0
- package/cli/team/coordination-root.js +161 -0
- package/cli/team/coordination-target.js +114 -0
- package/cli/team/dispatch-templates/dispatch-v1.js +228 -0
- package/cli/team/edit-shas.js +45 -0
- package/cli/team/lease-activity.js +130 -0
- package/cli/team/lease-cap.js +67 -0
- package/cli/team/lease-contention.js +30 -0
- package/cli/team/lease-key.js +46 -0
- package/cli/team/lease-lapse.js +83 -0
- package/cli/team/lease-reacquire.js +99 -0
- package/cli/team/lease-renew.js +97 -0
- package/cli/team/lease-roots.js +30 -0
- package/cli/team/lease-waiter-notice.js +48 -0
- package/cli/team/staged-leases.js +64 -0
- package/cli/team/task-completion-output.js +78 -0
- package/cli/team/task-detail-sections.js +86 -0
- package/cli/team/task-list-view.js +10 -1
- package/cli/team/task-ref.js +73 -0
- package/cli/team/task-target.js +53 -0
- package/cli/team/task-tier.js +17 -0
- package/cli/team/team-brief.js +78 -0
- package/cli/team/team-commands-board.js +118 -0
- package/cli/team/team-commands-dispatch.js +85 -0
- package/cli/team/team-commands-lock-staged.js +87 -0
- package/cli/team/team-commands-lock-views.js +144 -0
- package/cli/team/team-commands-lock.js +115 -26
- package/cli/team/team-commands-migrate.js +171 -0
- package/cli/team/team-commands-profile.js +44 -0
- package/cli/team/team-commands-repo.js +114 -0
- package/cli/team/team-commands-task.js +312 -0
- package/cli/team/team-commands-tokens.js +57 -0
- package/cli/team/team-commands-triage.js +43 -0
- package/cli/team/team-commands-vds.js +2 -1
- package/cli/team/team-commands.js +108 -463
- package/cli/team/team-db-agents.js +12 -6
- package/cli/team/team-db-feed.js +25 -13
- package/cli/team/team-db-lock-promotion.js +95 -51
- package/cli/team/team-db-locks.js +167 -35
- package/cli/team/team-db-mailbox.js +15 -8
- package/cli/team/team-db-readonly.js +76 -0
- package/cli/team/team-db-task-helpers.js +68 -19
- package/cli/team/team-db-tasks.js +21 -9
- package/cli/team/team-db-transaction.js +20 -5
- package/cli/team/team-db.js +11 -4
- package/cli/team/team-dispatch-batches.js +271 -0
- package/cli/team/team-dispatch-prompts.js +152 -0
- package/cli/team/team-dispatch-render.js +154 -0
- package/cli/team/team-dispatch-run-cli.js +154 -0
- package/cli/team/team-dispatch-runs.js +155 -0
- package/cli/team/team-dispatch-script.js +67 -0
- package/cli/team/team-dispatch-select.js +220 -0
- package/cli/team/team-dispatch-v2-fixture.js +62 -0
- package/cli/team/team-dispatch-v2.js +207 -0
- package/cli/team/team-dispatch.js +229 -0
- package/cli/team/team-dispatcher-authority.js +43 -0
- package/cli/team/team-flags.js +222 -48
- package/cli/team/team-format.js +80 -26
- package/cli/team/team-handoff-hint.js +9 -0
- package/cli/team/team-migrate-agents.js +52 -0
- package/cli/team/team-migrate-apply.js +178 -0
- package/cli/team/team-migrate-junk.js +55 -0
- package/cli/team/team-migrate-metadata.js +80 -0
- package/cli/team/team-migrate-paths.js +50 -0
- package/cli/team/team-migrate-plan.js +85 -0
- package/cli/team/team-migrate-report.js +89 -0
- package/cli/team/team-migrate-tables.js +85 -0
- package/cli/team/team-migrate.js +193 -0
- package/cli/team/team-needs.js +99 -0
- package/cli/team/team-profile-format.js +126 -0
- package/cli/team/team-profile.js +144 -0
- package/cli/team/team-projects-coordinator.js +54 -33
- package/cli/team/team-projects-format.js +8 -4
- package/cli/team/team-projects-memory.js +6 -3
- package/cli/team/team-projects.js +2 -1
- package/cli/team/team-release-train.js +2 -1
- package/cli/team/team-route.js +132 -0
- package/cli/team/team-schema-repo.js +48 -0
- package/cli/team/team-schema-usage.js +25 -0
- package/cli/team/team-schema-vds.js +7 -3
- package/cli/team/team-schema.js +24 -4
- package/cli/team/team-task-close.js +132 -0
- package/cli/team/team-task-guard.js +24 -0
- package/cli/team/team-task-handoff.js +122 -0
- package/cli/team/team-task-ownership.js +74 -0
- package/cli/team/team-task-rules.js +21 -0
- package/cli/team/team-task-uncommitted.js +49 -0
- package/cli/team/team-telemetry.js +44 -32
- package/cli/team/team-tokens.js +4 -1
- package/cli/team/team-triage-generate.js +212 -0
- package/cli/team/team-triage-log.js +11 -0
- package/cli/team/team-triage-verify.js +153 -0
- package/cli/team/team-triage.js +92 -339
- package/cli/team/team-vds.js +2 -1
- package/cli/team/usage-compute.js +70 -0
- package/cli/team/usage-pricing.js +62 -0
- package/cli/team/usage-reader.js +106 -0
- package/cli/team/usage-render.js +72 -0
- package/cli/team/usage-store.js +56 -0
- package/cli/team/usage-transcript.js +127 -0
- package/cli/team/write-lock-guard.js +48 -0
- package/cli/telemetry/call-ledger.js +264 -0
- package/cli/telemetry/call-schema.js +53 -0
- package/cli/telemetry/savings-dbs.js +111 -0
- package/cli/telemetry/savings-render.js +68 -0
- package/cli/telemetry/savings-report.js +101 -0
- package/cli/telemetry/savings-routing.js +66 -0
- package/cli/telemetry/savings-tooling.js +140 -0
- package/cli/terminal.js +38 -40
- package/cli/tesseract-manifesto.js +2 -17
- package/cli/tesseract.js +8 -21
- package/cli/test-audit.js +218 -0
- package/cli/test-changes.js +60 -0
- package/cli/test-command.js +201 -0
- package/cli/test-depth.js +43 -0
- package/cli/test-failures.js +170 -0
- package/cli/test-graph-open.js +150 -0
- package/cli/test-graph.js +188 -0
- package/cli/test-lanes.js +117 -0
- package/cli/test-output.js +155 -0
- package/cli/test-paths.js +51 -0
- package/cli/test-profile.js +64 -0
- package/cli/test-report.js +112 -0
- package/cli/test-run.js +53 -0
- package/cli/test-scope.js +55 -0
- package/cli/test-select.js +107 -0
- package/cli/test-slots.js +276 -0
- package/cli/test-workers.js +45 -0
- package/cli/test-workspace.js +83 -0
- package/cli/theme.js +6 -3
- package/cli/timers.js +6 -0
- package/cli/trend.js +10 -5
- package/cli/tsconfig-shape.js +20 -0
- package/cli/tty-banner.js +11 -0
- package/cli/typecheck-audit.js +146 -0
- package/cli/typecheck-command.js +94 -0
- package/cli/typecheck-sandbox.js +93 -0
- package/cli/ui-actions-codebase.js +20 -7
- package/cli/ui-actions-helpers.js +9 -0
- package/cli/ui-actions-studio.js +11 -7
- package/cli/ui-actions-tasks.js +3 -2
- package/cli/ui-actions-vds.js +2 -1
- package/cli/ui-actions.js +4 -2
- package/cli/ui-attention.js +28 -12
- package/cli/ui-auth-hosts.js +46 -0
- package/cli/ui-auth.js +89 -0
- package/cli/ui-client-cert.js +2 -1
- package/cli/ui-client-filetree.js +2 -2
- package/cli/ui-db-studio.js +23 -33
- package/cli/ui-dev-watcher.js +2 -1
- package/cli/ui-forum-data.js +45 -46
- package/cli/ui-forum-topics.js +6 -3
- package/cli/ui-fresh-index.js +11 -0
- package/cli/ui-handlers.js +6 -6
- package/cli/ui-html.js +6 -12
- package/cli/ui-index.html +3 -3
- package/cli/ui-route-helpers.js +10 -0
- package/cli/ui-server-routes.js +15 -17
- package/cli/ui-server.js +49 -50
- package/cli/ui-sql-guard.js +76 -0
- package/cli/ui-sql-mask.js +61 -0
- package/cli/ui-sse.js +5 -4
- package/cli/ui-template-filetree.js +4 -4
- package/cli/ui-template-kanban.js +4 -7
- package/cli/verify-changed.js +43 -0
- package/cli/verify-helpers.js +21 -207
- package/cli/verify-lint.js +54 -20
- package/cli/verify-report.js +117 -0
- package/cli/verify-steps.js +71 -0
- package/cli/verify.js +111 -372
- package/cli/wait-command.js +147 -0
- package/cli/workspace-run.js +153 -0
- package/cli/workspace.js +147 -0
- package/cli/write-append.js +28 -0
- package/library/node-js/is-path-inside/entry.json +57 -0
- package/library/node-js/is-path-inside/negative/path-scope.js.txt +13 -0
- package/library/node-js/is-path-inside/piece.js +15 -0
- package/library/node-js/is-path-inside/piece.spec.js +38 -0
- package/library/node-js/read-json-or/entry.json +70 -0
- package/library/node-js/read-json-or/negative/ratchet.js.txt +14 -0
- package/library/node-js/read-json-or/negative/workspace.js.txt +8 -0
- package/library/node-js/read-json-or/piece.js +17 -0
- package/library/node-js/read-json-or/piece.spec.js +36 -0
- package/library/vue-ts/nullable-timer-handle/ambient.d.ts +5 -0
- package/library/vue-ts/nullable-timer-handle/entry.json +84 -0
- package/library/vue-ts/nullable-timer-handle/negative/const-alias.ts.txt +17 -0
- package/library/vue-ts/nullable-timer-handle/negative/inline-guard.ts.txt +15 -0
- package/library/vue-ts/nullable-timer-handle/piece.spec.js +48 -0
- package/library/vue-ts/nullable-timer-handle/piece.ts +41 -0
- package/package.json +9 -3
- package/scripts/check-framework-generation.mjs +32 -12
- package/scripts/direct-run.mjs +9 -0
- package/scripts/pre-commit.sh +48 -74
- package/scripts/publish-both.mjs +24 -16
- package/scripts/publish-summary.mjs +14 -0
- package/scripts/postinstall.mjs +0 -27
package/cli/audit/autofix.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { resolveSafePath } from '../path-scope.js';
|
|
4
|
+
import { applyEdits } from '../apply-edits.js';
|
|
5
|
+
import { autofixContent } from './autofix-content.js';
|
|
6
|
+
import { STATUS, inconclusive } from '../result-status.js';
|
|
7
|
+
|
|
8
|
+
export { autofixContent } from './autofix-content.js';
|
|
3
9
|
|
|
4
10
|
const IGNORED_DIRS = new Set([
|
|
5
11
|
'node_modules',
|
|
@@ -9,183 +15,92 @@ const IGNORED_DIRS = new Set([
|
|
|
9
15
|
'.git',
|
|
10
16
|
'.next',
|
|
11
17
|
'.turbo',
|
|
12
|
-
'.cache'
|
|
18
|
+
'.cache',
|
|
19
|
+
'.chemx',
|
|
20
|
+
'.claude'
|
|
13
21
|
]);
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const RESIDUE_PATTERNS = [
|
|
18
|
-
['hope this', 'helps'].join(' '),
|
|
19
|
-
['feel free', 'to tweak'].join(' '),
|
|
20
|
-
['let me know', 'if you need'].join(' '),
|
|
21
|
-
['as an ai', 'language model'].join(' ')
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const RESIDUE_REGEX = new RegExp(`\\b(?:${RESIDUE_PATTERNS.join('|')})\\b`, 'i');
|
|
25
|
-
const PREAMBLE_REGEX = /\b(?:here(?:'s| is) the (?:complete|updated|refactored|full) (?:code|implementation|file|component|version))\b/i;
|
|
26
|
-
const TRUNCATION_REGEX = /^\s*\/\/\s*\.\.\.\s*(?:existing|rest of|remaining)\s+(?:code|implementation|logic|imports)/i;
|
|
27
|
-
const MARKDOWN_FENCE_REGEX = /^\s*```(?:typescript|javascript|tsx|jsx|vue|js|ts|html|css|scss)?\s*$/;
|
|
28
|
-
|
|
29
|
-
export const autofixContent = (content, options = {}) => {
|
|
30
|
-
const allowedRules = options.rules ? new Set(options.rules) : null;
|
|
31
|
-
const shouldFix = (rule) => !allowedRules || allowedRules.has(rule);
|
|
32
|
-
|
|
33
|
-
const lines = content.split('\n');
|
|
34
|
-
const fixes = [];
|
|
35
|
-
const resultLines = [];
|
|
36
|
-
|
|
37
|
-
for (let i = 0; i < lines.length; i++) {
|
|
38
|
-
let line = lines[i];
|
|
39
|
-
const lineNumber = i + 1;
|
|
40
|
-
let shouldDropLine = false;
|
|
41
|
-
|
|
42
|
-
// 1. Leaked markdown fence removal
|
|
43
|
-
if (shouldFix('AI_SLOP_CONVERSATIONAL_ARTIFACT') && MARKDOWN_FENCE_REGEX.test(line)) {
|
|
44
|
-
fixes.push({
|
|
45
|
-
line: lineNumber,
|
|
46
|
-
rule: 'AI_SLOP_CONVERSATIONAL_ARTIFACT',
|
|
47
|
-
action: 'Removed leaked markdown code fence'
|
|
48
|
-
});
|
|
49
|
-
shouldDropLine = true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 2. Pure conversational preamble or residue comment removal
|
|
53
|
-
if (!shouldDropLine && shouldFix('AI_SLOP_CONVERSATIONAL_ARTIFACT')) {
|
|
54
|
-
const isComment = /^\s*(?:\/\/|\/\*|<!--)/.test(line);
|
|
55
|
-
if (isComment && (PREAMBLE_REGEX.test(line) || RESIDUE_REGEX.test(line))) {
|
|
56
|
-
fixes.push({
|
|
57
|
-
line: lineNumber,
|
|
58
|
-
rule: 'AI_SLOP_CONVERSATIONAL_ARTIFACT',
|
|
59
|
-
action: 'Removed AI conversational residue comment'
|
|
60
|
-
});
|
|
61
|
-
shouldDropLine = true;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
23
|
+
// Markdown is deliberately absent: fences and prose are content there, not AI residue.
|
|
24
|
+
export const FIXABLE_EXTENSIONS = new Set(['.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs', '.vue', '.svelte', '.scss', '.css']);
|
|
64
25
|
|
|
65
|
-
|
|
66
|
-
const hasLazyTruncation = TRUNCATION_REGEX.test(line);
|
|
67
|
-
const isLazyTruncationEligible = !shouldDropLine && shouldFix('AI_SLOP_LAZY_PLACEHOLDER');
|
|
68
|
-
if (isLazyTruncationEligible && hasLazyTruncation) {
|
|
69
|
-
fixes.push({
|
|
70
|
-
line: lineNumber,
|
|
71
|
-
rule: 'AI_SLOP_LAZY_PLACEHOLDER',
|
|
72
|
-
action: 'Removed lazy AI truncation placeholder comment'
|
|
73
|
-
});
|
|
74
|
-
shouldDropLine = true;
|
|
75
|
-
}
|
|
26
|
+
const isFixable = (filePath) => FIXABLE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
76
27
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
line = line.replace(/\u2014/g, '-');
|
|
81
|
-
fixes.push({
|
|
82
|
-
line: lineNumber,
|
|
83
|
-
rule: 'TYPOGRAPHY_EM_DASH',
|
|
84
|
-
action: 'Replaced em dash with standard hyphen'
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const hasTimeoutMacro = /setTimeout\([^,]+,\s*0\)/.test(line);
|
|
89
|
-
const isTimeoutEligible = !shouldDropLine && shouldFix('MACRO_TASK_OVER_MICRO_TASK');
|
|
90
|
-
if (isTimeoutEligible && hasTimeoutMacro) {
|
|
91
|
-
line = line.replace(/setTimeout\(([^,]+),\s*0\)/g, 'queueMicrotask($1)');
|
|
92
|
-
fixes.push({
|
|
93
|
-
line: lineNumber,
|
|
94
|
-
rule: 'MACRO_TASK_OVER_MICRO_TASK',
|
|
95
|
-
action: 'Replaced setTimeout(fn, 0) with queueMicrotask(fn)'
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!shouldDropLine) {
|
|
100
|
-
resultLines.push(line);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
fixedContent: resultLines.join('\n'),
|
|
106
|
-
fixes
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const collectFiles = (targetPath, baseDir) => {
|
|
111
|
-
const stat = fs.statSync(targetPath);
|
|
112
|
-
if (stat.isFile()) {
|
|
113
|
-
return [targetPath];
|
|
114
|
-
}
|
|
28
|
+
const collectFiles = (targetPath) => {
|
|
29
|
+
const isFile = fs.statSync(targetPath).isFile();
|
|
30
|
+
if (isFile) return isFixable(targetPath) ? [targetPath] : [];
|
|
115
31
|
|
|
116
32
|
let files = [];
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
if (
|
|
33
|
+
for (const entry of fs.readdirSync(targetPath, { withFileTypes: true })) {
|
|
34
|
+
const isIgnored = IGNORED_DIRS.has(entry.name);
|
|
35
|
+
if (isIgnored) continue;
|
|
120
36
|
const fullPath = path.join(targetPath, entry.name);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
37
|
+
const isDirectory = entry.isDirectory();
|
|
38
|
+
const isFixableFile = !isDirectory && isFixable(entry.name);
|
|
39
|
+
if (isDirectory) files = files.concat(collectFiles(fullPath));
|
|
40
|
+
else if (isFixableFile) files.push(fullPath);
|
|
126
41
|
}
|
|
127
42
|
return files;
|
|
128
43
|
};
|
|
129
44
|
|
|
45
|
+
// No fixable file was looked at: that proves nothing, so it is inconclusive (exit 3), never a green check.
|
|
46
|
+
const NOTHING_CHECKED = inconclusive('NO_FILES_CHECKED');
|
|
47
|
+
|
|
48
|
+
const excludedReason = (filePath) => {
|
|
49
|
+
const ext = path.extname(filePath).toLowerCase() || 'extensionless';
|
|
50
|
+
return `${ext} files are not autofix targets (fixable: ${[...FIXABLE_EXTENSIONS].join(' ')}); nothing was checked`;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Applies token-aware mechanical fixes to a file or directory, through applyEdits
|
|
55
|
+
* (parse check, declaration-loss check, team locks, atomic writes, one rollback-able batch).
|
|
56
|
+
*
|
|
57
|
+
* @param {string} targetPath File or directory (default 'src').
|
|
58
|
+
* @param {object} [options] { cwd, dryRun, rules, agentId }
|
|
59
|
+
* @returns {object} status (pass, or inconclusive when no fixable file was checked), the uncapped
|
|
60
|
+
* fix list, suggestions, skipped files, and the diff on a dry run.
|
|
61
|
+
*/
|
|
130
62
|
export const runAutofix = (targetPath, options = {}) => {
|
|
131
63
|
const cwd = options.cwd || process.cwd();
|
|
132
|
-
const
|
|
64
|
+
const target = targetPath || 'src';
|
|
133
65
|
const dryRun = Boolean(options.dryRun);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
const allFixes = [];
|
|
148
|
-
let filesChanged = 0;
|
|
149
|
-
|
|
66
|
+
const resolvedTarget = resolveSafePath(target, cwd);
|
|
67
|
+
const root = fs.realpathSync(cwd);
|
|
68
|
+
const empty = { ...NOTHING_CHECKED, target, dryRun, filesScanned: 0, filesChanged: 0, totalFixes: 0, fixes: [], suggestions: [], skipped: [] };
|
|
69
|
+
const isMissing = !fs.existsSync(resolvedTarget);
|
|
70
|
+
if (isMissing) return { ...empty, skipped: [{ file: target, reason: 'target does not exist; nothing was checked' }] };
|
|
71
|
+
const isExcludedFile = fs.statSync(resolvedTarget).isFile() && !isFixable(resolvedTarget);
|
|
72
|
+
if (isExcludedFile) return { ...empty, skipped: [{ file: path.relative(root, resolvedTarget), reason: excludedReason(resolvedTarget) }] };
|
|
73
|
+
|
|
74
|
+
const files = collectFiles(resolvedTarget);
|
|
75
|
+
const fixes = [];
|
|
76
|
+
const suggestions = [];
|
|
77
|
+
const skipped = [];
|
|
78
|
+
const edits = [];
|
|
150
79
|
for (const filePath of files) {
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
rule: fix.rule,
|
|
162
|
-
action: fix.action
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (!dryRun) {
|
|
167
|
-
fs.writeFileSync(filePath, fixedContent, 'utf-8');
|
|
168
|
-
}
|
|
169
|
-
}
|
|
80
|
+
const file = path.relative(root, filePath);
|
|
81
|
+
const original = fs.readFileSync(filePath, 'utf-8');
|
|
82
|
+
const result = autofixContent(original, { ...options, filePath });
|
|
83
|
+
const isSkipped = Boolean(result.skipped);
|
|
84
|
+
if (isSkipped) skipped.push({ file, reason: result.skipped });
|
|
85
|
+
result.suggestions.forEach((s) => suggestions.push({ file, ...s }));
|
|
86
|
+
const isChanged = result.fixes.length > 0 && result.fixedContent !== original;
|
|
87
|
+
if (!isChanged) continue;
|
|
88
|
+
result.fixes.forEach((f) => fixes.push({ file, line: f.line, rule: f.rule, action: f.action }));
|
|
89
|
+
edits.push({ path: filePath, content: result.fixedContent });
|
|
170
90
|
}
|
|
171
91
|
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const result = {
|
|
178
|
-
target: targetPath || 'src',
|
|
92
|
+
const applied = edits.length > 0 ? applyEdits(edits, { cwd, dryRun, agentId: options.agentId }) : null;
|
|
93
|
+
const isNothingChecked = files.length === 0;
|
|
94
|
+
return {
|
|
95
|
+
...(isNothingChecked ? NOTHING_CHECKED : { status: STATUS.PASS }),
|
|
96
|
+
target,
|
|
179
97
|
dryRun,
|
|
180
98
|
filesScanned: files.length,
|
|
181
|
-
filesChanged,
|
|
182
|
-
totalFixes:
|
|
183
|
-
fixes
|
|
99
|
+
filesChanged: edits.length,
|
|
100
|
+
totalFixes: fixes.length,
|
|
101
|
+
fixes,
|
|
102
|
+
suggestions,
|
|
103
|
+
skipped,
|
|
104
|
+
...(dryRun && applied ? { diff: applied.diff } : {})
|
|
184
105
|
};
|
|
185
|
-
|
|
186
|
-
if (isCapped) {
|
|
187
|
-
result.omittedFixesCount = allFixes.length - MAX_REPORTED_FIXES;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return result;
|
|
191
106
|
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LINE_BUDGET_FILE, LINE_BUDGET_MOLECULE and VIEW_MONOLITH from the one budget
|
|
3
|
+
* policy in line-budgets.js (finding line-budget-chaos).
|
|
4
|
+
*/
|
|
5
|
+
import { PILLARS } from './rules-registry.js';
|
|
6
|
+
import {
|
|
7
|
+
countLines,
|
|
8
|
+
getLineBudgets,
|
|
9
|
+
resolveFileTier,
|
|
10
|
+
isViewMarkupFile,
|
|
11
|
+
classifyFileSize
|
|
12
|
+
} from './line-budgets.js';
|
|
13
|
+
|
|
14
|
+
const fileViolation = (relativePath, rule, severity, hazard, directive) => ({
|
|
15
|
+
filePath: relativePath,
|
|
16
|
+
line: 1,
|
|
17
|
+
column: 1,
|
|
18
|
+
hazard,
|
|
19
|
+
rule,
|
|
20
|
+
severity,
|
|
21
|
+
pillar: PILLARS.PILLAR_1,
|
|
22
|
+
directive
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const FILE_SEVERITY_BY_CLASS = Object.freeze({
|
|
26
|
+
extreme: { severity: 'CRITICAL', limitKey: 'critical', label: 'Extreme monolith hazard' },
|
|
27
|
+
severe: { severity: 'HIGH', limitKey: 'high', label: 'Severe monolith hazard' },
|
|
28
|
+
warning: { severity: 'MEDIUM', limitKey: 'warn', label: 'Monolith line budget warning' }
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const resolveFileSeverity = (lineCount, budget) => {
|
|
32
|
+
const { severity, limitKey, label } = FILE_SEVERITY_BY_CLASS[classifyFileSize(lineCount, budget)];
|
|
33
|
+
return { severity, limit: budget[limitKey], label };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const resolveMoleculeSeverity = (lineCount, limit) => {
|
|
37
|
+
const isCriticalMolecule = lineCount >= limit * 5;
|
|
38
|
+
if (isCriticalMolecule) return 'CRITICAL';
|
|
39
|
+
const isHighMolecule = lineCount >= limit * 2.5;
|
|
40
|
+
if (isHighMolecule) return 'HIGH';
|
|
41
|
+
return 'MEDIUM';
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const resolveTemplateLines = (content, sfc) => {
|
|
45
|
+
const template = sfc?.template;
|
|
46
|
+
if (template) return template.endLine - template.startLine + 1;
|
|
47
|
+
return countLines(content);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {{ content: string, relativePath: string, config?: object, sfc?: object|null, hasHighComplexity?: boolean }} input
|
|
52
|
+
*/
|
|
53
|
+
export const checkLineBudgets = ({ content, relativePath, config = {}, sfc = null, hasHighComplexity = false }) => {
|
|
54
|
+
const budgets = getLineBudgets(config);
|
|
55
|
+
const lineCount = countLines(content);
|
|
56
|
+
const tier = resolveFileTier(relativePath, config);
|
|
57
|
+
|
|
58
|
+
const isFileMonolith = classifyFileSize(lineCount, budgets.file) !== null;
|
|
59
|
+
if (isFileMonolith) {
|
|
60
|
+
const { severity, limit, label } = resolveFileSeverity(lineCount, budgets.file);
|
|
61
|
+
return [fileViolation(relativePath, 'LINE_BUDGET_FILE', severity, `${label} (${lineCount} > ${limit} lines)`,
|
|
62
|
+
'Decompose monolith into domain capsules and molecules (Directive 1.A)')];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const isOverMoleculeBudget = tier === 'molecule' && lineCount > budgets.molecule;
|
|
66
|
+
const isMoleculeEnforced = budgets.isMoleculeHardCap || hasHighComplexity;
|
|
67
|
+
const isMoleculeViolation = Boolean(isOverMoleculeBudget && isMoleculeEnforced);
|
|
68
|
+
if (isMoleculeViolation) {
|
|
69
|
+
const severity = resolveMoleculeSeverity(lineCount, budgets.molecule);
|
|
70
|
+
return [fileViolation(relativePath, 'LINE_BUDGET_MOLECULE', severity, `Molecule capsule over budget (${lineCount} > ${budgets.molecule} lines, ${budgets.profile})`,
|
|
71
|
+
'Split molecule into focused sub-molecules or extract state to a composable (Directive 1.C)')];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isViewEntry = tier === 'view' && isViewMarkupFile(relativePath);
|
|
75
|
+
const templateLines = isViewEntry ? resolveTemplateLines(content, sfc) : 0;
|
|
76
|
+
const isViewMonolith = templateLines > budgets.viewTemplate.warn;
|
|
77
|
+
if (isViewMonolith) {
|
|
78
|
+
const isSevere = templateLines >= budgets.viewTemplate.critical;
|
|
79
|
+
return [fileViolation(relativePath, 'VIEW_MONOLITH', isSevere ? 'CRITICAL' : 'MEDIUM',
|
|
80
|
+
`View template over budget (${templateLines} > ${budgets.viewTemplate.warn} lines)`,
|
|
81
|
+
'Refactor top-level view to a 10 to 20 line Table of Contents (Directive 1.B)')];
|
|
82
|
+
}
|
|
83
|
+
return [];
|
|
84
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catch-clause handling predicates for ERROR_SWALLOWED_EXCEPTION (Directive 2.H).
|
|
3
|
+
* A catch is handled when it throws, returns a value, calls anything (logger,
|
|
4
|
+
* notifier, handler), or assigns state that outlives the catch (error state,
|
|
5
|
+
* a fallback value, a member of an outer object).
|
|
6
|
+
*/
|
|
7
|
+
import * as t from '@babel/types';
|
|
8
|
+
|
|
9
|
+
const isMeaningfulStatement = (stmt) => !t.isEmptyStatement(stmt);
|
|
10
|
+
|
|
11
|
+
export const isEmptyCatchBody = (catchNode) => {
|
|
12
|
+
const body = catchNode.body?.body || [];
|
|
13
|
+
return !body.some(isMeaningfulStatement);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const isOuterBindingTarget = (left, catchPath) => {
|
|
17
|
+
const isMember = t.isMemberExpression(left) || t.isOptionalMemberExpression(left);
|
|
18
|
+
if (isMember) return true;
|
|
19
|
+
if (!t.isIdentifier(left)) return false;
|
|
20
|
+
const binding = catchPath.scope.getBinding(left.name);
|
|
21
|
+
if (!binding) return true;
|
|
22
|
+
const isDeclaredInsideCatch = Boolean(binding.path.findParent((p) => p === catchPath));
|
|
23
|
+
return !isDeclaredInsideCatch;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** True when the catch body neither propagates, reports, nor records the failure. */
|
|
27
|
+
export const isSwallowedCatch = (astPath) => {
|
|
28
|
+
if (isEmptyCatchBody(astPath.node)) return true;
|
|
29
|
+
|
|
30
|
+
let hasActiveHandling = false;
|
|
31
|
+
const markHandled = () => { hasActiveHandling = true; };
|
|
32
|
+
astPath.traverse({
|
|
33
|
+
ThrowStatement: markHandled,
|
|
34
|
+
CallExpression: markHandled,
|
|
35
|
+
OptionalCallExpression: markHandled,
|
|
36
|
+
NewExpression: markHandled,
|
|
37
|
+
ReturnStatement(retPath) {
|
|
38
|
+
const hasValue = retPath.node.argument !== null;
|
|
39
|
+
if (hasValue) markHandled();
|
|
40
|
+
},
|
|
41
|
+
AssignmentExpression(assignPath) {
|
|
42
|
+
const isOuterTarget = isOuterBindingTarget(assignPath.node.left, astPath);
|
|
43
|
+
if (isOuterTarget) markHandled();
|
|
44
|
+
},
|
|
45
|
+
Function(fnPath) {
|
|
46
|
+
fnPath.skip();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return !hasActiveHandling;
|
|
51
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { isSqliteMemoryTarget, isLinkedWorktreeRoot } from '../sqlite-memory.js';
|
|
4
|
+
import { hasProjectMarker, isForbiddenRoot, forbiddenRootRefusal } from '../project-markers.js';
|
|
5
|
+
|
|
6
|
+
// Locates (and creates) the .chemx directory that holds history and the index db.
|
|
7
|
+
// The walk prefers an existing ancestor .chemx, but stops at the first project marker (.git,
|
|
8
|
+
// package.json, .chemxrc; a linked worktree has a .git file): each package and each checkout keeps
|
|
9
|
+
// its own index instead of sharing a parent's. It never climbs into the OS temp dir, its ancestors
|
|
10
|
+
// or the filesystem root, and never answers one of them (#2570): a stray /tmp/.chemx is ignored.
|
|
11
|
+
const isIndexBoundary = (dir) => isLinkedWorktreeRoot(fs, path, dir) || hasProjectMarker(dir);
|
|
12
|
+
|
|
13
|
+
// Throws for a forbidden root: callers would otherwise create a db at /tmp or /.
|
|
14
|
+
const refuseForbidden = (dir) => {
|
|
15
|
+
const refusal = forbiddenRootRefusal(dir);
|
|
16
|
+
if (refusal) throw new Error(refusal);
|
|
17
|
+
return dir;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const findChemxDir = (startDir = process.cwd()) => {
|
|
21
|
+
const hasCustomRoot = Boolean(process.env.CHEMX_PROJECT_ROOT);
|
|
22
|
+
if (hasCustomRoot) {
|
|
23
|
+
return path.join(refuseForbidden(path.resolve(process.env.CHEMX_PROJECT_ROOT)), '.chemx');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let current = path.resolve(startDir);
|
|
27
|
+
while (!isForbiddenRoot(current)) {
|
|
28
|
+
const candidate = path.join(current, '.chemx');
|
|
29
|
+
const hasExistingChemx = fs.existsSync(candidate);
|
|
30
|
+
if (hasExistingChemx) {
|
|
31
|
+
return candidate;
|
|
32
|
+
}
|
|
33
|
+
if (isIndexBoundary(current)) return candidate;
|
|
34
|
+
current = path.dirname(current);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return path.join(refuseForbidden(path.resolve(startDir)), '.chemx');
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const ensureChemxDir = (cwd = process.cwd()) => {
|
|
41
|
+
const isMemoryTarget = isSqliteMemoryTarget(cwd);
|
|
42
|
+
if (isMemoryTarget) {
|
|
43
|
+
throw new Error(`ensureChemxDir: "${cwd}" is an in-memory SQLite target, not a directory`);
|
|
44
|
+
}
|
|
45
|
+
const dir = findChemxDir(cwd);
|
|
46
|
+
try {
|
|
47
|
+
const isDirMissing = !fs.existsSync(dir);
|
|
48
|
+
if (isDirMissing) {
|
|
49
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
return dir;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Ensure .chemx is gitignored if git repo exists
|
|
56
|
+
const targetParent = path.dirname(dir);
|
|
57
|
+
const gitDir = path.resolve(targetParent, '.git');
|
|
58
|
+
const hasGit = fs.existsSync(gitDir);
|
|
59
|
+
if (hasGit) {
|
|
60
|
+
const gitignorePath = path.resolve(targetParent, '.gitignore');
|
|
61
|
+
try {
|
|
62
|
+
const hasGitignore = fs.existsSync(gitignorePath);
|
|
63
|
+
let content = hasGitignore ? fs.readFileSync(gitignorePath, 'utf-8') : '';
|
|
64
|
+
const hasChemxEntry = content.includes('.chemx');
|
|
65
|
+
if (!hasChemxEntry) {
|
|
66
|
+
const hasTrailingNewline = content.endsWith('\n') || content.length === 0;
|
|
67
|
+
const trailingNewline = hasTrailingNewline ? '' : '\n';
|
|
68
|
+
fs.appendFileSync(gitignorePath, `${trailingNewline}# Chemical X local telemetry & audit history\n.chemx/\n`, 'utf-8');
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
return dir;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return dir;
|
|
76
|
+
};
|
|
@@ -2,7 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { deserializeVector, cosineSimilarity } from '../embeddings/vectorizer.js';
|
|
3
3
|
|
|
4
4
|
const isSpecOrTest = (filePath) => {
|
|
5
|
-
|
|
5
|
+
const isInvalidPath = !filePath || typeof filePath !== 'string';
|
|
6
|
+
if (isInvalidPath) return false;
|
|
6
7
|
return filePath.includes('.spec.') || filePath.includes('.test.') || filePath.includes('__tests__');
|
|
7
8
|
};
|
|
8
9
|
|
|
@@ -10,7 +11,8 @@ export const detectSemanticClones = (db, options = {}) => {
|
|
|
10
11
|
const isValidDb = Boolean(db);
|
|
11
12
|
if (!isValidDb) return { count: 0, threshold: 0.85, pairs: [] };
|
|
12
13
|
|
|
13
|
-
const
|
|
14
|
+
const hasNumericThreshold = typeof options.threshold === 'number';
|
|
15
|
+
const threshold = hasNumericThreshold ? options.threshold : 0.85;
|
|
14
16
|
const limit = options.limit || 50;
|
|
15
17
|
|
|
16
18
|
const rows = db.prepare(
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where comments sit on a source line, outside string literals, so a `chemx-allow:` marker
|
|
3
|
+
* quoted in a string never counts as an annotation. One pass per line; the state carries an
|
|
4
|
+
* open block comment and an open template literal into the next line.
|
|
5
|
+
*
|
|
6
|
+
* Known gaps (they err towards flagging): a lone apostrophe in markup text or a quote inside
|
|
7
|
+
* a regex literal opens a string for the rest of that line, and C# verbatim strings are read
|
|
8
|
+
* with backslash escapes.
|
|
9
|
+
*/
|
|
10
|
+
const BLOCK_OPENERS = [['/*', '*/'], ['<!--', '-->']];
|
|
11
|
+
const QUOTES = new Set(['"', "'", '`']);
|
|
12
|
+
const BACKSLASH = '\\';
|
|
13
|
+
const CARRIED_QUOTE = '`';
|
|
14
|
+
|
|
15
|
+
export const INITIAL_SCAN_STATE = Object.freeze({ inBlock: false, blockCloser: null, quote: null });
|
|
16
|
+
|
|
17
|
+
const findBlockOpener = (line, index) => BLOCK_OPENERS.find(([opener]) => line.startsWith(opener, index));
|
|
18
|
+
|
|
19
|
+
const isHashComment = (line, index) => line[index] === '#' && (index === 0 || /\s/.test(line[index - 1]));
|
|
20
|
+
|
|
21
|
+
const isLineCommentStart = (line, index) => line.startsWith('//', index) || isHashComment(line, index);
|
|
22
|
+
|
|
23
|
+
// Index just past the string that is open at index (quote already consumed), or -1 when it
|
|
24
|
+
// runs past the end of the line.
|
|
25
|
+
const skipString = (line, index, quote) => {
|
|
26
|
+
let cursor = index;
|
|
27
|
+
while (cursor < line.length) {
|
|
28
|
+
const char = line[cursor];
|
|
29
|
+
const isEscape = char === BACKSLASH;
|
|
30
|
+
const isClosingQuote = char === quote;
|
|
31
|
+
if (isClosingQuote) return cursor + 1;
|
|
32
|
+
cursor += isEscape ? 2 : 1;
|
|
33
|
+
}
|
|
34
|
+
return -1;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Comment regions on one line as [start, end) column pairs, and the state for the next line.
|
|
39
|
+
*/
|
|
40
|
+
export const scanCommentRegions = (line, state = INITIAL_SCAN_STATE) => {
|
|
41
|
+
const regions = [];
|
|
42
|
+
let { inBlock, blockCloser, quote } = state;
|
|
43
|
+
let regionStart = 0;
|
|
44
|
+
let index = 0;
|
|
45
|
+
while (index < line.length) {
|
|
46
|
+
if (inBlock) {
|
|
47
|
+
const closeAt = line.indexOf(blockCloser, index);
|
|
48
|
+
const isStillOpen = closeAt === -1;
|
|
49
|
+
if (isStillOpen) break;
|
|
50
|
+
regions.push([regionStart, closeAt + blockCloser.length]);
|
|
51
|
+
index = closeAt + blockCloser.length;
|
|
52
|
+
inBlock = false;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (quote) {
|
|
56
|
+
const afterString = skipString(line, index, quote);
|
|
57
|
+
const isUnterminated = afterString === -1;
|
|
58
|
+
if (isUnterminated) break;
|
|
59
|
+
quote = null;
|
|
60
|
+
index = afterString;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (isLineCommentStart(line, index)) {
|
|
64
|
+
regions.push([index, line.length]);
|
|
65
|
+
index = line.length;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
const block = findBlockOpener(line, index);
|
|
69
|
+
if (block) {
|
|
70
|
+
inBlock = true;
|
|
71
|
+
blockCloser = block[1];
|
|
72
|
+
regionStart = index;
|
|
73
|
+
index += block[0].length;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const isQuote = QUOTES.has(line[index]);
|
|
77
|
+
if (isQuote) quote = line[index];
|
|
78
|
+
index += 1;
|
|
79
|
+
}
|
|
80
|
+
if (inBlock) regions.push([regionStart, line.length]);
|
|
81
|
+
const carriedQuote = quote === CARRIED_QUOTE ? quote : null;
|
|
82
|
+
return { regions, state: { inBlock, blockCloser: inBlock ? blockCloser : null, quote: carriedQuote } };
|
|
83
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit coverage: how much of each scanned file the AST rules actually saw. A file
|
|
3
|
+
* that only got line-level text checks (unsupported language, --fast, parse error,
|
|
4
|
+
* an SFC template that failed to parse) is reported as partial so a low hazard
|
|
5
|
+
* count is never presented as a confident pass.
|
|
6
|
+
*/
|
|
7
|
+
export const COVERAGE_KINDS = Object.freeze({
|
|
8
|
+
AST: 'ast',
|
|
9
|
+
TEXT_ONLY: 'text-only',
|
|
10
|
+
PARSE_ERROR: 'parse-error',
|
|
11
|
+
EMPTY: 'empty'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const createCoverageCollector = () => ({ files: [] });
|
|
15
|
+
|
|
16
|
+
/** Records one file. `sfc` is { scriptBlocks, hasTemplate, isTemplateParsed } for .vue files. */
|
|
17
|
+
export const recordFileCoverage = (collector, { relativePath, kind, sfc = null }) => {
|
|
18
|
+
if (!collector) return;
|
|
19
|
+
collector.files.push({ relativePath, kind, sfc });
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const isPartialEntry = (entry) => {
|
|
23
|
+
const isAstless = entry.kind !== COVERAGE_KINDS.AST && entry.kind !== COVERAGE_KINDS.EMPTY;
|
|
24
|
+
const hasUnparsedTemplate = Boolean(entry.sfc?.hasTemplate) && !entry.sfc?.isTemplateParsed;
|
|
25
|
+
return isAstless || hasUnparsedTemplate;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const summarizeCoverage = (collector) => {
|
|
29
|
+
const entries = collector?.files ?? [];
|
|
30
|
+
const countKind = (kind) => entries.filter((e) => e.kind === kind).length;
|
|
31
|
+
const sfcEntries = entries.filter((e) => e.sfc);
|
|
32
|
+
const partialFiles = entries.filter(isPartialEntry).map((e) => e.relativePath);
|
|
33
|
+
const astFiles = countKind(COVERAGE_KINDS.AST);
|
|
34
|
+
return {
|
|
35
|
+
files: entries.length,
|
|
36
|
+
astParsed: astFiles,
|
|
37
|
+
textOnly: countKind(COVERAGE_KINDS.TEXT_ONLY),
|
|
38
|
+
parseErrors: countKind(COVERAGE_KINDS.PARSE_ERROR),
|
|
39
|
+
astPct: entries.length > 0 ? Math.round((astFiles / entries.length) * 100) : 100,
|
|
40
|
+
sfc: {
|
|
41
|
+
files: sfcEntries.length,
|
|
42
|
+
scriptBlocks: sfcEntries.reduce((sum, e) => sum + (e.sfc.scriptBlocks ?? 0), 0),
|
|
43
|
+
templatesParsed: sfcEntries.filter((e) => e.sfc.isTemplateParsed).length
|
|
44
|
+
},
|
|
45
|
+
isPartial: partialFiles.length > 0,
|
|
46
|
+
partialFiles: partialFiles.slice(0, 20)
|
|
47
|
+
};
|
|
48
|
+
};
|