@shrkcrft/inspector 0.1.0-alpha.30 → 0.1.0-alpha.31
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/dist/acceptance-replay.js +1 -1
- package/dist/agent-contract-templates.js +6 -6
- package/dist/agent-contract.d.ts.map +1 -1
- package/dist/agent-contract.js +13 -8
- package/dist/agent-orchestration.js +2 -2
- package/dist/agent-task-prep.d.ts +16 -0
- package/dist/agent-task-prep.d.ts.map +1 -1
- package/dist/agent-task-prep.js +51 -4
- package/dist/ai-readiness.d.ts.map +1 -1
- package/dist/ai-readiness.js +21 -3
- package/dist/architecture-map.d.ts +16 -0
- package/dist/architecture-map.d.ts.map +1 -1
- package/dist/architecture-map.js +42 -26
- package/dist/area-explore.d.ts +2 -2
- package/dist/area-explore.d.ts.map +1 -1
- package/dist/area-explore.js +36 -16
- package/dist/area-map.d.ts +56 -11
- package/dist/area-map.d.ts.map +1 -1
- package/dist/area-map.js +106 -25
- package/dist/asset-doctor-proposed-exit.d.ts +21 -0
- package/dist/asset-doctor-proposed-exit.d.ts.map +1 -0
- package/dist/asset-doctor-proposed-exit.js +22 -0
- package/dist/asset-provenance.js +1 -1
- package/dist/boundaries-changed-only.d.ts +24 -1
- package/dist/boundaries-changed-only.d.ts.map +1 -1
- package/dist/boundaries-changed-only.js +12 -2
- package/dist/boundary-check-options.model.d.ts +40 -0
- package/dist/boundary-check-options.model.d.ts.map +1 -0
- package/dist/boundary-check-options.model.js +1 -0
- package/dist/boundary-check-result.model.d.ts +89 -0
- package/dist/boundary-check-result.model.d.ts.map +1 -0
- package/dist/boundary-check-result.model.js +1 -0
- package/dist/boundary-configuration-status.d.ts +38 -0
- package/dist/boundary-configuration-status.d.ts.map +1 -0
- package/dist/boundary-configuration-status.js +118 -0
- package/dist/boundary-configuration-status.model.d.ts +37 -0
- package/dist/boundary-configuration-status.model.d.ts.map +1 -0
- package/dist/boundary-configuration-status.model.js +1 -0
- package/dist/boundary-load-issue.model.d.ts +30 -0
- package/dist/boundary-load-issue.model.d.ts.map +1 -0
- package/dist/boundary-load-issue.model.js +1 -0
- package/dist/boundary-rule-check.model.d.ts +44 -0
- package/dist/boundary-rule-check.model.d.ts.map +1 -0
- package/dist/boundary-rule-check.model.js +1 -0
- package/dist/boundary-rule-invalidation.model.d.ts +31 -0
- package/dist/boundary-rule-invalidation.model.d.ts.map +1 -0
- package/dist/boundary-rule-invalidation.model.js +1 -0
- package/dist/boundary-rule-set-diff.model.d.ts +75 -0
- package/dist/boundary-rule-set-diff.model.d.ts.map +1 -0
- package/dist/boundary-rule-set-diff.model.js +1 -0
- package/dist/boundary-rule-sources.d.ts +28 -0
- package/dist/boundary-rule-sources.d.ts.map +1 -0
- package/dist/boundary-rule-sources.js +110 -0
- package/dist/boundary-stale-exception-finding.model.d.ts +12 -0
- package/dist/boundary-stale-exception-finding.model.d.ts.map +1 -0
- package/dist/boundary-stale-exception-finding.model.js +1 -0
- package/dist/boundary-unit-liveness.d.ts +35 -0
- package/dist/boundary-unit-liveness.d.ts.map +1 -0
- package/dist/boundary-unit-liveness.js +71 -0
- package/dist/change-intent.d.ts +3 -0
- package/dist/change-intent.d.ts.map +1 -1
- package/dist/change-intent.js +61 -27
- package/dist/changes-summary.d.ts.map +1 -1
- package/dist/changes-summary.js +19 -9
- package/dist/ci-integrity-report.js +1 -1
- package/dist/ci-predict.d.ts.map +1 -1
- package/dist/ci-predict.js +38 -5
- package/dist/code-intelligence-doctor.d.ts +6 -0
- package/dist/code-intelligence-doctor.d.ts.map +1 -1
- package/dist/code-intelligence-doctor.js +22 -7
- package/dist/command-recommender.d.ts +45 -2
- package/dist/command-recommender.d.ts.map +1 -1
- package/dist/command-recommender.js +41 -263
- package/dist/command-resolution-status.d.ts +44 -0
- package/dist/command-resolution-status.d.ts.map +1 -0
- package/dist/command-resolution-status.js +44 -0
- package/dist/command-safety-level.d.ts +15 -0
- package/dist/command-safety-level.d.ts.map +1 -0
- package/dist/command-safety-level.js +43 -0
- package/dist/command-taxonomy.js +1 -1
- package/dist/compliance-evidence.js +1 -1
- package/dist/compliance-profiles.js +1 -1
- package/dist/construct-registry.d.ts +40 -0
- package/dist/construct-registry.d.ts.map +1 -1
- package/dist/construct-registry.js +186 -82
- package/dist/context-tuning.d.ts +4 -0
- package/dist/context-tuning.d.ts.map +1 -1
- package/dist/context-tuning.js +10 -7
- package/dist/contract-template-registry.d.ts +10 -0
- package/dist/contract-template-registry.d.ts.map +1 -1
- package/dist/contract-template-registry.js +59 -33
- package/dist/contribution-kind.d.ts +52 -0
- package/dist/contribution-kind.d.ts.map +1 -0
- package/dist/contribution-kind.js +52 -0
- package/dist/contribution-load-failures.d.ts +106 -0
- package/dist/contribution-load-failures.d.ts.map +1 -0
- package/dist/contribution-load-failures.js +575 -0
- package/dist/contributions-report.d.ts +28 -0
- package/dist/contributions-report.d.ts.map +1 -0
- package/dist/contributions-report.js +242 -0
- package/dist/convention-registry.d.ts +22 -0
- package/dist/convention-registry.d.ts.map +1 -1
- package/dist/convention-registry.js +79 -39
- package/dist/coverage-report.d.ts.map +1 -1
- package/dist/coverage-report.js +6 -6
- package/dist/custom-checks.d.ts +60 -1
- package/dist/custom-checks.d.ts.map +1 -1
- package/dist/custom-checks.js +159 -6
- package/dist/dashboard/dashboard-data.d.ts +6 -0
- package/dist/dashboard/dashboard-data.d.ts.map +1 -1
- package/dist/dashboard/dashboard-data.js +99 -8
- package/dist/dashboard/dashboard-knowledge.d.ts.map +1 -1
- package/dist/dashboard/dashboard-knowledge.js +14 -2
- package/dist/decision-records.d.ts +20 -0
- package/dist/decision-records.d.ts.map +1 -1
- package/dist/decision-records.js +68 -20
- package/dist/declared-cross-references.d.ts +61 -0
- package/dist/declared-cross-references.d.ts.map +1 -0
- package/dist/declared-cross-references.js +550 -0
- package/dist/declared-gate-plane-rules.d.ts +24 -0
- package/dist/declared-gate-plane-rules.d.ts.map +1 -0
- package/dist/declared-gate-plane-rules.js +39 -0
- package/dist/declared-reference-coverage.d.ts +27 -0
- package/dist/declared-reference-coverage.d.ts.map +1 -0
- package/dist/declared-reference-coverage.js +50 -0
- package/dist/declared-xref-status.d.ts +19 -0
- package/dist/declared-xref-status.d.ts.map +1 -0
- package/dist/declared-xref-status.js +19 -0
- package/dist/delegate-pack-recipes.d.ts +13 -2
- package/dist/delegate-pack-recipes.d.ts.map +1 -1
- package/dist/delegate-pack-recipes.js +45 -14
- package/dist/demo-package.js +2 -2
- package/dist/demo-script.js +2 -2
- package/dist/demo-workflow.js +3 -3
- package/dist/dev-cycle.js +1 -1
- package/dist/dev-session.js +1 -1
- package/dist/doc-references.d.ts +23 -2
- package/dist/doc-references.d.ts.map +1 -1
- package/dist/doc-references.js +96 -17
- package/dist/doctor-result.d.ts +8 -0
- package/dist/doctor-result.d.ts.map +1 -1
- package/dist/doctor-verdict-kind.d.ts +19 -0
- package/dist/doctor-verdict-kind.d.ts.map +1 -0
- package/dist/doctor-verdict-kind.js +19 -0
- package/dist/doctor-verdict.d.ts +18 -0
- package/dist/doctor-verdict.d.ts.map +1 -0
- package/dist/doctor-verdict.js +28 -0
- package/dist/drift.d.ts +17 -0
- package/dist/drift.d.ts.map +1 -1
- package/dist/drift.js +40 -10
- package/dist/entrypoint-matrix.d.ts.map +1 -1
- package/dist/entrypoint-matrix.js +4 -1
- package/dist/feedback-ingestion.d.ts +28 -2
- package/dist/feedback-ingestion.d.ts.map +1 -1
- package/dist/feedback-ingestion.js +68 -19
- package/dist/fix-preview.d.ts.map +1 -1
- package/dist/fix-preview.js +9 -5
- package/dist/framework-extractor-outcomes.d.ts +27 -0
- package/dist/framework-extractor-outcomes.d.ts.map +1 -0
- package/dist/framework-extractor-outcomes.js +83 -0
- package/dist/fuzzy-impact.js +1 -1
- package/dist/healing-plan.d.ts.map +1 -1
- package/dist/healing-plan.js +3 -4
- package/dist/helper-catalog.d.ts +25 -0
- package/dist/helper-catalog.d.ts.map +1 -0
- package/dist/helper-catalog.js +91 -0
- package/dist/helper-registry.d.ts.map +1 -1
- package/dist/helper-registry.js +17 -1
- package/dist/helper-view.d.ts +33 -0
- package/dist/helper-view.d.ts.map +1 -0
- package/dist/helper-view.js +1 -0
- package/dist/i-asset-doctor-flags.d.ts +16 -0
- package/dist/i-asset-doctor-flags.d.ts.map +1 -0
- package/dist/i-asset-doctor-flags.js +1 -0
- package/dist/i-command-resolution.d.ts +22 -0
- package/dist/i-command-resolution.d.ts.map +1 -0
- package/dist/i-command-resolution.js +1 -0
- package/dist/i-command-resolve-options.d.ts +24 -0
- package/dist/i-command-resolve-options.d.ts.map +1 -0
- package/dist/i-command-resolve-options.js +1 -0
- package/dist/i-command-safety.d.ts +13 -0
- package/dist/i-command-safety.d.ts.map +1 -0
- package/dist/i-command-safety.js +1 -0
- package/dist/i-contribution-accepted-entry.d.ts +18 -0
- package/dist/i-contribution-accepted-entry.d.ts.map +1 -0
- package/dist/i-contribution-accepted-entry.js +1 -0
- package/dist/i-contribution-entry-rejection.d.ts +21 -0
- package/dist/i-contribution-entry-rejection.d.ts.map +1 -0
- package/dist/i-contribution-entry-rejection.js +1 -0
- package/dist/i-contribution-file-issue.d.ts +18 -0
- package/dist/i-contribution-file-issue.d.ts.map +1 -0
- package/dist/i-contribution-file-issue.js +1 -0
- package/dist/i-contribution-file-report.d.ts +40 -0
- package/dist/i-contribution-file-report.d.ts.map +1 -0
- package/dist/i-contribution-file-report.js +1 -0
- package/dist/i-contribution-file-validation.d.ts +24 -0
- package/dist/i-contribution-file-validation.d.ts.map +1 -0
- package/dist/i-contribution-file-validation.js +1 -0
- package/dist/i-contributions-report.d.ts +31 -0
- package/dist/i-contributions-report.d.ts.map +1 -0
- package/dist/i-contributions-report.js +1 -0
- package/dist/i-declared-xref-field.d.ts +25 -0
- package/dist/i-declared-xref-field.d.ts.map +1 -0
- package/dist/i-declared-xref-field.js +1 -0
- package/dist/i-declared-xref-issue.d.ts +25 -0
- package/dist/i-declared-xref-issue.d.ts.map +1 -0
- package/dist/i-declared-xref-issue.js +1 -0
- package/dist/i-declared-xref-report.d.ts +48 -0
- package/dist/i-declared-xref-report.d.ts.map +1 -0
- package/dist/i-declared-xref-report.js +1 -0
- package/dist/i-declared-xref-row.d.ts +29 -0
- package/dist/i-declared-xref-row.d.ts.map +1 -0
- package/dist/i-declared-xref-row.js +1 -0
- package/dist/i-doctor-verdict.d.ts +10 -0
- package/dist/i-doctor-verdict.d.ts.map +1 -0
- package/dist/i-doctor-verdict.js +1 -0
- package/dist/i-kind-outcomes.d.ts +13 -0
- package/dist/i-kind-outcomes.d.ts.map +1 -0
- package/dist/i-kind-outcomes.js +1 -0
- package/dist/i-pack-doctor-verdict.d.ts +15 -0
- package/dist/i-pack-doctor-verdict.d.ts.map +1 -0
- package/dist/i-pack-doctor-verdict.js +1 -0
- package/dist/i-probed-id-field.d.ts +17 -0
- package/dist/i-probed-id-field.d.ts.map +1 -0
- package/dist/i-probed-id-field.js +1 -0
- package/dist/i-reference-kind-declaration.d.ts +38 -0
- package/dist/i-reference-kind-declaration.d.ts.map +1 -0
- package/dist/i-reference-kind-declaration.js +1 -0
- package/dist/i-reference-warm-options.d.ts +21 -0
- package/dist/i-reference-warm-options.d.ts.map +1 -0
- package/dist/i-reference-warm-options.js +1 -0
- package/dist/i-registry-outcomes.d.ts +16 -0
- package/dist/i-registry-outcomes.d.ts.map +1 -0
- package/dist/i-registry-outcomes.js +1 -0
- package/dist/i-scaffold-pattern-doctor-report.d.ts +35 -0
- package/dist/i-scaffold-pattern-doctor-report.d.ts.map +1 -0
- package/dist/i-scaffold-pattern-doctor-report.js +1 -0
- package/dist/i-search-tuning-key-probe.d.ts +30 -0
- package/dist/i-search-tuning-key-probe.d.ts.map +1 -0
- package/dist/i-search-tuning-key-probe.js +1 -0
- package/dist/i-search-tuning-lint-issue.d.ts +61 -0
- package/dist/i-search-tuning-lint-issue.d.ts.map +1 -0
- package/dist/i-search-tuning-lint-issue.js +1 -0
- package/dist/i-search-tuning-lint-report.d.ts +38 -0
- package/dist/i-search-tuning-lint-report.d.ts.map +1 -0
- package/dist/i-search-tuning-lint-report.js +1 -0
- package/dist/i-unresolvable-reference-scan.d.ts +14 -0
- package/dist/i-unresolvable-reference-scan.d.ts.map +1 -0
- package/dist/i-unresolvable-reference-scan.js +1 -0
- package/dist/i-unresolvable-reference.d.ts +29 -0
- package/dist/i-unresolvable-reference.d.ts.map +1 -0
- package/dist/i-unresolvable-reference.js +1 -0
- package/dist/i-workspace-profile-payload.d.ts +12 -0
- package/dist/i-workspace-profile-payload.d.ts.map +1 -0
- package/dist/i-workspace-profile-payload.js +1 -0
- package/dist/impact-analysis.d.ts +15 -0
- package/dist/impact-analysis.d.ts.map +1 -1
- package/dist/impact-analysis.js +58 -13
- package/dist/impact-render.d.ts.map +1 -1
- package/dist/impact-render.js +22 -0
- package/dist/import-hygiene.d.ts +35 -1
- package/dist/import-hygiene.d.ts.map +1 -1
- package/dist/import-hygiene.js +107 -13
- package/dist/index.d.ts +141 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +172 -0
- package/dist/inspection-discovery.d.ts +45 -0
- package/dist/inspection-discovery.d.ts.map +1 -0
- package/dist/inspection-discovery.js +70 -0
- package/dist/knowledge-advisory-code.d.ts +17 -0
- package/dist/knowledge-advisory-code.d.ts.map +1 -0
- package/dist/knowledge-advisory-code.js +17 -0
- package/dist/knowledge-aged-entry.d.ts +10 -0
- package/dist/knowledge-aged-entry.d.ts.map +1 -0
- package/dist/knowledge-aged-entry.js +1 -0
- package/dist/knowledge-authoring.d.ts +24 -1
- package/dist/knowledge-authoring.d.ts.map +1 -1
- package/dist/knowledge-authoring.js +46 -7
- package/dist/knowledge-entry-verdict-record.d.ts +22 -0
- package/dist/knowledge-entry-verdict-record.d.ts.map +1 -0
- package/dist/knowledge-entry-verdict-record.js +1 -0
- package/dist/knowledge-entry-verdict.d.ts +17 -0
- package/dist/knowledge-entry-verdict.d.ts.map +1 -0
- package/dist/knowledge-entry-verdict.js +17 -0
- package/dist/knowledge-graph.d.ts +6 -0
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +18 -7
- package/dist/knowledge-kind-bucket.d.ts +19 -0
- package/dist/knowledge-kind-bucket.d.ts.map +1 -0
- package/dist/knowledge-kind-bucket.js +1 -0
- package/dist/knowledge-load-failure.d.ts +23 -0
- package/dist/knowledge-load-failure.d.ts.map +1 -0
- package/dist/knowledge-load-failure.js +1 -0
- package/dist/knowledge-reference-kind-bucket.d.ts +11 -0
- package/dist/knowledge-reference-kind-bucket.d.ts.map +1 -0
- package/dist/knowledge-reference-kind-bucket.js +1 -0
- package/dist/knowledge-stale-advisory.d.ts +14 -0
- package/dist/knowledge-stale-advisory.d.ts.map +1 -0
- package/dist/knowledge-stale-advisory.js +1 -0
- package/dist/knowledge-stale-coverage.d.ts +19 -0
- package/dist/knowledge-stale-coverage.d.ts.map +1 -0
- package/dist/knowledge-stale-coverage.js +1 -0
- package/dist/knowledge-stale-gate-flags.d.ts +33 -0
- package/dist/knowledge-stale-gate-flags.d.ts.map +1 -0
- package/dist/knowledge-stale-gate-flags.js +1 -0
- package/dist/knowledge-stale-gate-input.d.ts +46 -0
- package/dist/knowledge-stale-gate-input.d.ts.map +1 -0
- package/dist/knowledge-stale-gate-input.js +1 -0
- package/dist/knowledge-stale-gate-result.d.ts +33 -0
- package/dist/knowledge-stale-gate-result.d.ts.map +1 -0
- package/dist/knowledge-stale-gate-result.js +1 -0
- package/dist/knowledge-stale-gate-rule.d.ts +33 -0
- package/dist/knowledge-stale-gate-rule.d.ts.map +1 -0
- package/dist/knowledge-stale-gate-rule.js +1 -0
- package/dist/knowledge-stale-gate-violation.d.ts +13 -0
- package/dist/knowledge-stale-gate-violation.d.ts.map +1 -0
- package/dist/knowledge-stale-gate-violation.js +1 -0
- package/dist/knowledge-stale-gate.d.ts +83 -0
- package/dist/knowledge-stale-gate.d.ts.map +1 -0
- package/dist/knowledge-stale-gate.js +429 -0
- package/dist/knowledge-stale-quality-gate.d.ts +26 -0
- package/dist/knowledge-stale-quality-gate.d.ts.map +1 -0
- package/dist/knowledge-stale-quality-gate.js +110 -0
- package/dist/knowledge-stale.d.ts +122 -9
- package/dist/knowledge-stale.d.ts.map +1 -1
- package/dist/knowledge-stale.js +996 -291
- package/dist/knowledge-unverifiable-reason.d.ts +12 -0
- package/dist/knowledge-unverifiable-reason.d.ts.map +1 -0
- package/dist/knowledge-unverifiable-reason.js +12 -0
- package/dist/loader-diagnostics.d.ts +14 -2
- package/dist/loader-diagnostics.d.ts.map +1 -1
- package/dist/match-terms.d.ts +48 -0
- package/dist/match-terms.d.ts.map +1 -0
- package/dist/match-terms.js +155 -0
- package/dist/migration-profile-registry.d.ts +10 -0
- package/dist/migration-profile-registry.d.ts.map +1 -1
- package/dist/migration-profile-registry.js +57 -34
- package/dist/migration-readiness.d.ts.map +1 -1
- package/dist/migration-readiness.js +1 -3
- package/dist/nearest-id.d.ts +10 -26
- package/dist/nearest-id.d.ts.map +1 -1
- package/dist/nearest-id.js +9 -59
- package/dist/pack-asset-freshness.d.ts +65 -0
- package/dist/pack-asset-freshness.d.ts.map +1 -0
- package/dist/pack-asset-freshness.js +340 -0
- package/dist/pack-author-ux.d.ts +24 -3
- package/dist/pack-author-ux.d.ts.map +1 -1
- package/dist/pack-author-ux.js +87 -93
- package/dist/pack-contributions-inventory.d.ts +79 -39
- package/dist/pack-contributions-inventory.d.ts.map +1 -1
- package/dist/pack-contributions-inventory.js +443 -286
- package/dist/pack-doctor-verdict.d.ts +29 -0
- package/dist/pack-doctor-verdict.d.ts.map +1 -0
- package/dist/pack-doctor-verdict.js +45 -0
- package/dist/pack-doctor.d.ts +74 -1
- package/dist/pack-doctor.d.ts.map +1 -1
- package/dist/pack-doctor.js +281 -1
- package/dist/pack-helper-plan.d.ts +24 -0
- package/dist/pack-helper-plan.d.ts.map +1 -0
- package/dist/pack-helper-plan.js +77 -0
- package/dist/pack-helper-registry.d.ts +14 -0
- package/dist/pack-helper-registry.d.ts.map +1 -1
- package/dist/pack-helper-registry.js +76 -37
- package/dist/pack-manifest-reader.d.ts +8 -0
- package/dist/pack-manifest-reader.d.ts.map +1 -0
- package/dist/pack-manifest-reader.js +79 -0
- package/dist/pack-release-check.d.ts +14 -1
- package/dist/pack-release-check.d.ts.map +1 -1
- package/dist/pack-release-check.js +23 -1
- package/dist/pack-signature-status.d.ts +18 -6
- package/dist/pack-signature-status.d.ts.map +1 -1
- package/dist/pack-signature-status.js +59 -105
- package/dist/pack-test-runner.d.ts +27 -5
- package/dist/pack-test-runner.d.ts.map +1 -1
- package/dist/pack-test-runner.js +91 -35
- package/dist/pack-typecheck.d.ts +8 -0
- package/dist/pack-typecheck.d.ts.map +1 -0
- package/dist/pack-typecheck.js +76 -0
- package/dist/plan-review.d.ts +2 -0
- package/dist/plan-review.d.ts.map +1 -1
- package/dist/plan-review.js +17 -5
- package/dist/plan-simulation.d.ts.map +1 -1
- package/dist/plan-simulation.js +16 -5
- package/dist/playbook-load-issue.d.ts +16 -0
- package/dist/playbook-load-issue.d.ts.map +1 -0
- package/dist/playbook-load-issue.js +1 -0
- package/dist/playbook-registry.d.ts +32 -1
- package/dist/playbook-registry.d.ts.map +1 -1
- package/dist/playbook-registry.js +144 -55
- package/dist/policy-declaration.d.ts +18 -0
- package/dist/policy-declaration.d.ts.map +1 -0
- package/dist/policy-declaration.js +1 -0
- package/dist/policy-engine.d.ts +8 -0
- package/dist/policy-engine.d.ts.map +1 -1
- package/dist/policy-engine.js +26 -9
- package/dist/policy-overrides.d.ts.map +1 -1
- package/dist/policy-overrides.js +4 -4
- package/dist/policy-registry.d.ts +27 -0
- package/dist/policy-registry.d.ts.map +1 -1
- package/dist/policy-registry.js +87 -20
- package/dist/probed-id-fields.d.ts +21 -0
- package/dist/probed-id-fields.d.ts.map +1 -0
- package/dist/probed-id-fields.js +25 -0
- package/dist/probed-id-source.d.ts +11 -0
- package/dist/probed-id-source.d.ts.map +1 -0
- package/dist/probed-id-source.js +11 -0
- package/dist/profile-registry.d.ts +25 -2
- package/dist/profile-registry.d.ts.map +1 -1
- package/dist/profile-registry.js +59 -6
- package/dist/quality-gate-examination.d.ts +15 -0
- package/dist/quality-gate-examination.d.ts.map +1 -0
- package/dist/quality-gate-examination.js +15 -0
- package/dist/quality-gate-row-status.d.ts +19 -0
- package/dist/quality-gate-row-status.d.ts.map +1 -0
- package/dist/quality-gate-row-status.js +28 -0
- package/dist/quality-gate-status.d.ts +16 -0
- package/dist/quality-gate-status.d.ts.map +1 -0
- package/dist/quality-gate-status.js +16 -0
- package/dist/quality-html.d.ts.map +1 -1
- package/dist/quality-html.js +14 -3
- package/dist/quality-report-coverage.d.ts +26 -0
- package/dist/quality-report-coverage.d.ts.map +1 -0
- package/dist/quality-report-coverage.js +48 -0
- package/dist/quality-report.d.ts +28 -1
- package/dist/quality-report.d.ts.map +1 -1
- package/dist/quality-report.js +263 -35
- package/dist/query-intent-kind.d.ts +18 -0
- package/dist/query-intent-kind.d.ts.map +1 -0
- package/dist/query-intent-kind.js +18 -0
- package/dist/query-intent-result.d.ts +23 -0
- package/dist/query-intent-result.d.ts.map +1 -0
- package/dist/query-intent-result.js +1 -0
- package/dist/query-intent.d.ts +18 -0
- package/dist/query-intent.d.ts.map +1 -0
- package/dist/query-intent.js +336 -0
- package/dist/query-resolver.d.ts +18 -0
- package/dist/query-resolver.d.ts.map +1 -1
- package/dist/query-resolver.js +7 -4
- package/dist/ranked-recommendations.d.ts +36 -0
- package/dist/ranked-recommendations.d.ts.map +1 -0
- package/dist/ranked-recommendations.js +1 -0
- package/dist/ranker-explainability.d.ts.map +1 -1
- package/dist/ranker-explainability.js +38 -10
- package/dist/recommend-recipe.d.ts +17 -0
- package/dist/recommend-recipe.d.ts.map +1 -0
- package/dist/recommend-recipe.js +1 -0
- package/dist/recommend-recipes.d.ts +9 -0
- package/dist/recommend-recipes.d.ts.map +1 -0
- package/dist/recommend-recipes.js +106 -0
- package/dist/recommendation-candidate.d.ts +30 -0
- package/dist/recommendation-candidate.d.ts.map +1 -0
- package/dist/recommendation-candidate.js +1 -0
- package/dist/recommendation-confidence.d.ts +27 -0
- package/dist/recommendation-confidence.d.ts.map +1 -0
- package/dist/recommendation-confidence.js +1 -0
- package/dist/recommendation-ranking-options.d.ts +24 -0
- package/dist/recommendation-ranking-options.d.ts.map +1 -0
- package/dist/recommendation-ranking-options.js +1 -0
- package/dist/recommendation-ranking.d.ts +50 -0
- package/dist/recommendation-ranking.d.ts.map +1 -0
- package/dist/recommendation-ranking.js +527 -0
- package/dist/recommendation-source.d.ts +23 -0
- package/dist/recommendation-source.d.ts.map +1 -0
- package/dist/recommendation-source.js +23 -0
- package/dist/recommendation-suppression.d.ts +14 -0
- package/dist/recommendation-suppression.d.ts.map +1 -0
- package/dist/recommendation-suppression.js +14 -0
- package/dist/reference-asset-kind.d.ts +14 -0
- package/dist/reference-asset-kind.d.ts.map +1 -0
- package/dist/reference-asset-kind.js +14 -0
- package/dist/reference-content-check.d.ts +32 -0
- package/dist/reference-content-check.d.ts.map +1 -0
- package/dist/reference-content-check.js +143 -0
- package/dist/reference-failure.d.ts +31 -0
- package/dist/reference-failure.d.ts.map +1 -0
- package/dist/reference-failure.js +31 -0
- package/dist/reference-id-status.d.ts +15 -0
- package/dist/reference-id-status.d.ts.map +1 -0
- package/dist/reference-id-status.js +15 -0
- package/dist/reference-kind-declarations.d.ts +42 -0
- package/dist/reference-kind-declarations.d.ts.map +1 -0
- package/dist/reference-kind-declarations.js +142 -0
- package/dist/reference-lookup.d.ts +6 -0
- package/dist/reference-lookup.d.ts.map +1 -1
- package/dist/reference-lookup.js +13 -5
- package/dist/reference-registry.d.ts +109 -11
- package/dist/reference-registry.d.ts.map +1 -1
- package/dist/reference-registry.js +186 -30
- package/dist/reference-subject.d.ts +20 -0
- package/dist/reference-subject.d.ts.map +1 -0
- package/dist/reference-subject.js +1 -0
- package/dist/registration-hint-discovery-status.d.ts +25 -0
- package/dist/registration-hint-discovery-status.d.ts.map +1 -0
- package/dist/registration-hint-discovery-status.js +25 -0
- package/dist/registration-hint-registry.d.ts +80 -0
- package/dist/registration-hint-registry.d.ts.map +1 -1
- package/dist/registration-hint-registry.js +356 -138
- package/dist/registry-lifecycle.d.ts +200 -19
- package/dist/registry-lifecycle.d.ts.map +1 -1
- package/dist/registry-lifecycle.js +526 -136
- package/dist/release-readiness.d.ts.map +1 -1
- package/dist/release-readiness.js +10 -7
- package/dist/release-smoke.d.ts.map +1 -1
- package/dist/release-smoke.js +11 -7
- package/dist/report-site.d.ts.map +1 -1
- package/dist/report-site.js +25 -7
- package/dist/repository-intelligence.d.ts.map +1 -1
- package/dist/repository-intelligence.js +3 -2
- package/dist/repository-knowledge-model.d.ts.map +1 -1
- package/dist/repository-knowledge-model.js +18 -5
- package/dist/resolve-project-config.d.ts +64 -0
- package/dist/resolve-project-config.d.ts.map +1 -1
- package/dist/resolve-project-config.js +240 -32
- package/dist/reuse/compute-reuse-coverage.d.ts +29 -0
- package/dist/reuse/compute-reuse-coverage.d.ts.map +1 -0
- package/dist/reuse/compute-reuse-coverage.js +198 -0
- package/dist/reuse/rank-reuse-candidates.d.ts +38 -0
- package/dist/reuse/rank-reuse-candidates.d.ts.map +1 -0
- package/dist/reuse/rank-reuse-candidates.js +212 -0
- package/dist/reuse/rank-reuse-options.d.ts +20 -0
- package/dist/reuse/rank-reuse-options.d.ts.map +1 -0
- package/dist/reuse/rank-reuse-options.js +1 -0
- package/dist/reuse/rank-reuse-suggestions.d.ts +15 -0
- package/dist/reuse/rank-reuse-suggestions.d.ts.map +1 -0
- package/dist/reuse/rank-reuse-suggestions.js +31 -0
- package/dist/reuse/resolve-curated-reuse.d.ts +43 -0
- package/dist/reuse/resolve-curated-reuse.d.ts.map +1 -0
- package/dist/reuse/resolve-curated-reuse.js +115 -0
- package/dist/reuse/reuse-candidate.d.ts +29 -0
- package/dist/reuse/reuse-candidate.d.ts.map +1 -0
- package/dist/reuse/reuse-candidate.js +1 -0
- package/dist/reuse/reuse-coverage-report.d.ts +74 -0
- package/dist/reuse/reuse-coverage-report.d.ts.map +1 -0
- package/dist/reuse/reuse-coverage-report.js +1 -0
- package/dist/reuse/reuse-curated-coverage.d.ts +36 -0
- package/dist/reuse/reuse-curated-coverage.d.ts.map +1 -0
- package/dist/reuse/reuse-curated-coverage.js +1 -0
- package/dist/reuse/reuse-curated-resolution.d.ts +36 -0
- package/dist/reuse/reuse-curated-resolution.d.ts.map +1 -0
- package/dist/reuse/reuse-curated-resolution.js +1 -0
- package/dist/reuse/reuse-curated-status.d.ts +21 -0
- package/dist/reuse/reuse-curated-status.d.ts.map +1 -0
- package/dist/reuse/reuse-curated-status.js +21 -0
- package/dist/reuse/reuse-match-detail.d.ts +15 -0
- package/dist/reuse/reuse-match-detail.d.ts.map +1 -0
- package/dist/reuse/reuse-match-detail.js +1 -0
- package/dist/reuse/reuse-ranking.d.ts +37 -0
- package/dist/reuse/reuse-ranking.d.ts.map +1 -0
- package/dist/reuse/reuse-ranking.js +1 -0
- package/dist/reuse/reuse-suggestion.d.ts +19 -0
- package/dist/reuse/reuse-suggestion.d.ts.map +1 -0
- package/dist/reuse/reuse-suggestion.js +1 -0
- package/dist/reuse/reuse-symbol-lookup.d.ts +28 -0
- package/dist/reuse/reuse-symbol-lookup.d.ts.map +1 -0
- package/dist/reuse/reuse-symbol-lookup.js +1 -0
- package/dist/reuse/reuse-tokenize.d.ts +11 -0
- package/dist/reuse/reuse-tokenize.d.ts.map +1 -0
- package/dist/reuse/reuse-tokenize.js +26 -0
- package/dist/reuse/score-reuse-name.d.ts +16 -0
- package/dist/reuse/score-reuse-name.d.ts.map +1 -0
- package/dist/reuse/score-reuse-name.js +35 -0
- package/dist/reuse/score-reuse-primitive.d.ts +33 -0
- package/dist/reuse/score-reuse-primitive.d.ts.map +1 -0
- package/dist/reuse/score-reuse-primitive.js +92 -0
- package/dist/review-packet.d.ts +2 -0
- package/dist/review-packet.d.ts.map +1 -1
- package/dist/review-packet.js +13 -6
- package/dist/role-views.d.ts.map +1 -1
- package/dist/role-views.js +16 -16
- package/dist/routing-recommends-channels.d.ts +24 -0
- package/dist/routing-recommends-channels.d.ts.map +1 -0
- package/dist/routing-recommends-channels.js +19 -0
- package/dist/run-boundary-check.d.ts +118 -0
- package/dist/run-boundary-check.d.ts.map +1 -0
- package/dist/run-boundary-check.js +592 -0
- package/dist/safety-audit.js +1 -1
- package/dist/scaffold-coverage.js +1 -1
- package/dist/scaffold-pattern-doctor-report.d.ts +19 -0
- package/dist/scaffold-pattern-doctor-report.d.ts.map +1 -0
- package/dist/scaffold-pattern-doctor-report.js +54 -0
- package/dist/scaffold-patterns.d.ts +75 -1
- package/dist/scaffold-patterns.d.ts.map +1 -1
- package/dist/scaffold-patterns.js +375 -84
- package/dist/schema-inventory.d.ts.map +1 -1
- package/dist/schema-inventory.js +4 -3
- package/dist/search-document-id.d.ts +52 -0
- package/dist/search-document-id.d.ts.map +1 -0
- package/dist/search-document-id.js +72 -0
- package/dist/search-document-prefix.d.ts +7 -0
- package/dist/search-document-prefix.d.ts.map +1 -0
- package/dist/search-document-prefix.js +1 -0
- package/dist/search-index.d.ts.map +1 -1
- package/dist/search-index.js +20 -23
- package/dist/search-tuning-explain.d.ts +6 -0
- package/dist/search-tuning-explain.d.ts.map +1 -1
- package/dist/search-tuning-explain.js +19 -17
- package/dist/search-tuning-key-probes.d.ts +16 -0
- package/dist/search-tuning-key-probes.d.ts.map +1 -0
- package/dist/search-tuning-key-probes.js +65 -0
- package/dist/search-tuning-key-resolution.d.ts +25 -0
- package/dist/search-tuning-key-resolution.d.ts.map +1 -0
- package/dist/search-tuning-key-resolution.js +1 -0
- package/dist/search-tuning-key-resolver.d.ts +4 -0
- package/dist/search-tuning-key-resolver.d.ts.map +1 -0
- package/dist/search-tuning-key-resolver.js +107 -0
- package/dist/search-tuning-key-status.d.ts +24 -0
- package/dist/search-tuning-key-status.d.ts.map +1 -0
- package/dist/search-tuning-key-status.js +24 -0
- package/dist/search-tuning-lint.d.ts +9 -0
- package/dist/search-tuning-lint.d.ts.map +1 -0
- package/dist/search-tuning-lint.js +468 -0
- package/dist/search-tuning-registry.d.ts +43 -0
- package/dist/search-tuning-registry.d.ts.map +1 -1
- package/dist/search-tuning-registry.js +214 -49
- package/dist/self-audit.d.ts +12 -0
- package/dist/self-audit.d.ts.map +1 -1
- package/dist/self-audit.js +36 -10
- package/dist/self-config-doctor-v2.d.ts +145 -3
- package/dist/self-config-doctor-v2.d.ts.map +1 -1
- package/dist/self-config-doctor-v2.js +1304 -181
- package/dist/self-config-doctor.d.ts +20 -1
- package/dist/self-config-doctor.d.ts.map +1 -1
- package/dist/self-config-doctor.js +53 -280
- package/dist/settled-unit-states.d.ts +9 -0
- package/dist/settled-unit-states.d.ts.map +1 -0
- package/dist/settled-unit-states.js +14 -0
- package/dist/sharkcraft-inspector.d.ts +34 -0
- package/dist/sharkcraft-inspector.d.ts.map +1 -1
- package/dist/sharkcraft-inspector.js +273 -26
- package/dist/spec/spec-evidence.d.ts.map +1 -1
- package/dist/spec/spec-evidence.js +14 -20
- package/dist/split-identifier.d.ts +21 -0
- package/dist/split-identifier.d.ts.map +1 -0
- package/dist/split-identifier.js +27 -0
- package/dist/start-here.d.ts.map +1 -1
- package/dist/start-here.js +1 -2
- package/dist/substitute-placeholders.d.ts +8 -0
- package/dist/substitute-placeholders.d.ts.map +1 -0
- package/dist/substitute-placeholders.js +9 -0
- package/dist/symbol-index.d.ts +33 -0
- package/dist/symbol-index.d.ts.map +1 -1
- package/dist/symbol-index.js +241 -3
- package/dist/symbol-member-entry.d.ts +26 -0
- package/dist/symbol-member-entry.d.ts.map +1 -0
- package/dist/symbol-member-entry.js +1 -0
- package/dist/symbol-member-kind.d.ts +14 -0
- package/dist/symbol-member-kind.d.ts.map +1 -0
- package/dist/symbol-member-kind.js +14 -0
- package/dist/task-packet.d.ts.map +1 -1
- package/dist/task-packet.js +52 -9
- package/dist/task-ranker.d.ts +8 -0
- package/dist/task-ranker.d.ts.map +1 -1
- package/dist/task-ranker.js +25 -13
- package/dist/task-risk.js +1 -1
- package/dist/task-routing-hint-registry.d.ts +20 -1
- package/dist/task-routing-hint-registry.d.ts.map +1 -1
- package/dist/task-routing-hint-registry.js +186 -42
- package/dist/template-drift.d.ts.map +1 -1
- package/dist/template-drift.js +30 -9
- package/dist/template-lint.d.ts.map +1 -1
- package/dist/template-lint.js +160 -2
- package/dist/term-query.d.ts +10 -0
- package/dist/term-query.d.ts.map +1 -0
- package/dist/term-query.js +1 -0
- package/dist/test-definitions.d.ts +6 -3
- package/dist/test-definitions.d.ts.map +1 -1
- package/dist/test-runner.d.ts +95 -10
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +309 -308
- package/dist/tuning-query-tokens.d.ts +29 -0
- package/dist/tuning-query-tokens.d.ts.map +1 -0
- package/dist/tuning-query-tokens.js +51 -0
- package/dist/typecheck-files.d.ts +36 -0
- package/dist/typecheck-files.d.ts.map +1 -0
- package/dist/typecheck-files.js +158 -0
- package/dist/uncertainty.js +1 -1
- package/dist/universal-search.d.ts.map +1 -1
- package/dist/universal-search.js +5 -3
- package/dist/unregistered-exports.d.ts +19 -0
- package/dist/unregistered-exports.d.ts.map +1 -0
- package/dist/unregistered-exports.js +141 -0
- package/dist/unresolvable-reason.d.ts +11 -0
- package/dist/unresolvable-reason.d.ts.map +1 -0
- package/dist/unresolvable-reason.js +11 -0
- package/dist/upgrade-advisor.d.ts.map +1 -1
- package/dist/upgrade-advisor.js +16 -9
- package/dist/validate-contribution-file.d.ts +4 -0
- package/dist/validate-contribution-file.d.ts.map +1 -0
- package/dist/validate-contribution-file.js +228 -0
- package/dist/why-file.d.ts +3 -0
- package/dist/why-file.d.ts.map +1 -1
- package/dist/why-file.js +7 -3
- package/package.json +17 -17
|
@@ -8,15 +8,28 @@
|
|
|
8
8
|
* Ignored: generated files (.generated.*, .d.ts), files containing
|
|
9
9
|
* `@shrkcrft lifecycle-ignore <reason>`. Sites with `@shrkcrft lifecycle-managed-by <name>`
|
|
10
10
|
* are reported under `ignored` with the managed-by reference.
|
|
11
|
+
*
|
|
12
|
+
* Bounded, and honest about the bound (round 11):
|
|
13
|
+
* - candidates are SORTED by project-relative path, so `offset` / `limit`
|
|
14
|
+
* page through them deterministically and `nextOffset` always reaches the
|
|
15
|
+
* remainder a cap, the budget or a signal left unexamined;
|
|
16
|
+
* - the wall-clock budget is checked between files AND inside each file
|
|
17
|
+
* (after the strip, after the declaration scan, before every register), so
|
|
18
|
+
* one pathological file cannot run past it unbounded. A file over its own
|
|
19
|
+
* sub-budget is abandoned whole and NAMED in `overBudgetFiles`;
|
|
20
|
+
* - every per-file step is linear — no two newline-spanning quantifiers
|
|
21
|
+
* touch in any pattern that runs on the blanked buffer, and the remover
|
|
22
|
+
* lookup is one pass per file instead of one regex per candidate name;
|
|
23
|
+
* - the report carries engine-owned coverage (`files`, `registrations`), and
|
|
24
|
+
* {@link registryLifecycleVerdict} reads nothing else.
|
|
11
25
|
*/
|
|
12
|
-
import { readdirSync, readFileSync } from 'node:fs';
|
|
13
|
-
import { extname, join, relative } from 'node:path';
|
|
26
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
27
|
+
import { extname, join, relative, sep } from 'node:path';
|
|
28
|
+
import { coverageShortfall } from '@shrkcrft/core';
|
|
14
29
|
/**
|
|
15
30
|
* Default directories the walk skips — build artefacts + non-source trees that
|
|
16
|
-
* inflate the scan without owning runtime lifecycle.
|
|
17
|
-
*
|
|
18
|
-
* can override the set via config (`registryLifecycle.skipDirs`) / the engine's
|
|
19
|
-
* `skipDirs` input, so a hardcoded exclusion never silently blinds the check.
|
|
31
|
+
* inflate the scan without owning runtime lifecycle. Extend it with
|
|
32
|
+
* `registryLifecycle.skipDirsAdd`; replace it with `registryLifecycle.skipDirs`.
|
|
20
33
|
*/
|
|
21
34
|
export const DEFAULT_REGISTRY_LIFECYCLE_SKIP_DIRS = Object.freeze([
|
|
22
35
|
'node_modules',
|
|
@@ -36,52 +49,102 @@ export const DEFAULT_REGISTRY_LIFECYCLE_SKIP_DIRS = Object.freeze([
|
|
|
36
49
|
'.agents',
|
|
37
50
|
'.github',
|
|
38
51
|
]);
|
|
52
|
+
/**
|
|
53
|
+
* The dependency / VCS-adjacent / build-output defaults. A replacing
|
|
54
|
+
* `skipDirs` list that omits one of these makes the scan read vendored or
|
|
55
|
+
* generated code — four false positives from one added exclusion, measured —
|
|
56
|
+
* so dropping one is always reported. (`.git` & co. stay skipped by the
|
|
57
|
+
* dot-entry rule regardless.)
|
|
58
|
+
*/
|
|
59
|
+
export const CORE_REGISTRY_LIFECYCLE_SKIP_DIRS = Object.freeze([
|
|
60
|
+
'node_modules',
|
|
61
|
+
'dist',
|
|
62
|
+
'build',
|
|
63
|
+
'out',
|
|
64
|
+
'coverage',
|
|
65
|
+
'.sharkcraft',
|
|
66
|
+
]);
|
|
39
67
|
const SCAN_EXTENSIONS = new Set(['.ts', '.tsx']);
|
|
40
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Skip pathological single files — named in `excludedFiles.oversized` AND
|
|
70
|
+
* counted UNEXAMINED in the files coverage: a cap is never a deliberate
|
|
71
|
+
* narrowing (round 11 review: subtracting them from `expected` let a missing
|
|
72
|
+
* remover inside a 361 KB file settle to a clean ✓). The boundaries reader's
|
|
73
|
+
* rule (`readScopeCoverage`: over-cap = unread = a shortfall) — one rule.
|
|
74
|
+
*/
|
|
41
75
|
const MAX_SCAN_FILE_BYTES = 256 * 1024;
|
|
42
|
-
/**
|
|
76
|
+
/** How the files coverage names the size cap. */
|
|
77
|
+
const LIFECYCLE_READ_CAP = `${MAX_SCAN_FILE_BYTES / 1024} KB`;
|
|
78
|
+
/** Wall-clock budget for a whole run. */
|
|
43
79
|
const DEFAULT_BUDGET_MS = 15_000;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
80
|
+
/** Default file cap. */
|
|
81
|
+
const DEFAULT_LIMIT = 2000;
|
|
82
|
+
/** Labels named in a coverage record's `unexamined`. */
|
|
83
|
+
const UNEXAMINED_SHOWN = 20;
|
|
84
|
+
/**
|
|
85
|
+
* THE skip-dir authority: the engine, the CLI and `shrk doctor` all call this.
|
|
86
|
+
* `skipDirsAdd` extends; `skipDirs` replaces; a replacement that drops a core
|
|
87
|
+
* default is reported in `droppedDefaults`.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveRegistryLifecycleSkipDirs(input) {
|
|
90
|
+
const base = input.skipDirs ?? DEFAULT_REGISTRY_LIFECYCLE_SKIP_DIRS;
|
|
91
|
+
const effective = [...new Set([...base, ...(input.skipDirsAdd ?? [])])].sort();
|
|
92
|
+
const kept = new Set(effective);
|
|
93
|
+
const droppedDefaults = CORE_REGISTRY_LIFECYCLE_SKIP_DIRS.filter((d) => !kept.has(d));
|
|
94
|
+
return { effective, droppedDefaults };
|
|
95
|
+
}
|
|
96
|
+
/** The warning a replacing skip list that drops core defaults earns. One wording, scan and doctor. */
|
|
97
|
+
export function registryLifecycleSkipDirsWarning(droppedDefaults) {
|
|
98
|
+
return (`registryLifecycle.skipDirs replaces the defaults and drops: ${droppedDefaults.join(', ')} — ` +
|
|
99
|
+
'use skipDirsAdd to extend the default skip set instead');
|
|
52
100
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
101
|
+
function isGeneratedPath(file) {
|
|
102
|
+
return file.endsWith('.d.ts') || /\.generated\.(ts|tsx)$/.test(file);
|
|
103
|
+
}
|
|
104
|
+
function isGeneratedContent(content) {
|
|
105
|
+
return /^\/\/ @generated\b/m.test(content);
|
|
106
|
+
}
|
|
107
|
+
function toPosix(p) {
|
|
108
|
+
return sep === '/' ? p : p.split(sep).join('/');
|
|
109
|
+
}
|
|
110
|
+
function comparePaths(a, b) {
|
|
111
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
112
|
+
}
|
|
113
|
+
function isMissing(e) {
|
|
114
|
+
return e?.code === 'ENOENT';
|
|
115
|
+
}
|
|
116
|
+
/** Walk for candidates. Returns `false` when the budget expired before the walk finished. */
|
|
117
|
+
function walkCandidates(dir, out, skipDirs, expired) {
|
|
118
|
+
// The budget bounds DISCOVERY too, not only the per-file loop — a
|
|
119
|
+
// pathological tree could otherwise eat the whole budget first (a25 §2.5).
|
|
120
|
+
if (expired())
|
|
121
|
+
return false;
|
|
60
122
|
let entries;
|
|
61
123
|
try {
|
|
62
124
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
63
125
|
}
|
|
64
126
|
catch {
|
|
65
|
-
return;
|
|
127
|
+
return true;
|
|
66
128
|
}
|
|
67
129
|
for (const e of entries) {
|
|
68
|
-
if (
|
|
69
|
-
return;
|
|
130
|
+
if (expired())
|
|
131
|
+
return false;
|
|
70
132
|
if (skipDirs.has(e.name))
|
|
71
133
|
continue;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
134
|
+
// Hidden entries stay out, except `.sharkcraft` (skipped by default, but a
|
|
135
|
+
// replacing skip list makes it scannable — and is warned about).
|
|
136
|
+
if (e.name.startsWith('.') && e.name !== '.sharkcraft')
|
|
137
|
+
continue;
|
|
77
138
|
const abs = join(dir, e.name);
|
|
78
139
|
if (e.isDirectory()) {
|
|
79
|
-
|
|
140
|
+
if (!walkCandidates(abs, out, skipDirs, expired))
|
|
141
|
+
return false;
|
|
80
142
|
}
|
|
81
143
|
else if (e.isFile() && SCAN_EXTENSIONS.has(extname(e.name))) {
|
|
82
144
|
out.push(abs);
|
|
83
145
|
}
|
|
84
146
|
}
|
|
147
|
+
return true;
|
|
85
148
|
}
|
|
86
149
|
const REGISTER_PATTERNS = Object.freeze([
|
|
87
150
|
// export function registerX(
|
|
@@ -108,6 +171,29 @@ const ACCUMULATION_RE = /\.(?:set|add|push)\s*\(|\[[^\]]+\]\s*=[^=]/;
|
|
|
108
171
|
// A teardown-shaped API somewhere in the file — evidence the file is in the
|
|
109
172
|
// business of removing things, so a missing per-register remover is suspicious.
|
|
110
173
|
const TEARDOWN_RE = /\b(?:remove|unregister|clear|dispose|unsubscribe)\w*\s*\(|\boff\s*\(/i;
|
|
174
|
+
/**
|
|
175
|
+
* Every callable site `name(` / `name = (` in the blanked code, in ONE pass.
|
|
176
|
+
*
|
|
177
|
+
* Replaces a whole-file regex compiled once PER CANDIDATE NAME whose third
|
|
178
|
+
* alternative, `(?:public|private|protected)?\s*(?:async\s+)?NAME\s*\(`, could
|
|
179
|
+
* start at every offset of a blank run and cost O(run) there: O(run²) per
|
|
180
|
+
* blanked comment, times six candidate names, times every register — 16 s for
|
|
181
|
+
* one 51 KB file. Anchored on `\b` + an identifier, no whitespace quantifier
|
|
182
|
+
* can start a match, so this is linear. It also reports the NAME's offset, so
|
|
183
|
+
* `removerLine` is the method's own line (the old match began at the blank run).
|
|
184
|
+
*/
|
|
185
|
+
const CALLABLE_SITE_RE = /\b([A-Za-z_$][\w$]*)\s*(?:=\s*)?\(/g;
|
|
186
|
+
/**
|
|
187
|
+
* Every pattern this module runs on a blanked buffer, for the linearity lock
|
|
188
|
+
* (`r75-registry-lifecycle-scan.test.ts`): each must stay fast on a 64 KiB
|
|
189
|
+
* blank run and clean under `findBlankRunHazards`.
|
|
190
|
+
*/
|
|
191
|
+
export const REGISTRY_LIFECYCLE_PATTERNS = Object.freeze({
|
|
192
|
+
register: REGISTER_PATTERNS,
|
|
193
|
+
accumulation: ACCUMULATION_RE,
|
|
194
|
+
teardown: TEARDOWN_RE,
|
|
195
|
+
callableSite: CALLABLE_SITE_RE,
|
|
196
|
+
});
|
|
111
197
|
/**
|
|
112
198
|
* Blank out comments and string / template-literal bodies (preserving newlines
|
|
113
199
|
* so line numbers stay accurate) before scanning for `register*` declarations.
|
|
@@ -240,14 +326,29 @@ function findRegistersInFile(content, lineStarts) {
|
|
|
240
326
|
re.lastIndex = 0;
|
|
241
327
|
while ((m = re.exec(content)) !== null) {
|
|
242
328
|
const name = m[1];
|
|
243
|
-
|
|
329
|
+
// The NAME's offset, not the match start: the method pattern begins at
|
|
330
|
+
// the preceding `\n`, which used to report the line ABOVE the declaration.
|
|
331
|
+
const at = m.index + m[0].indexOf(name);
|
|
332
|
+
if (seen.has(`${name}@${at}`))
|
|
244
333
|
continue;
|
|
245
|
-
seen.add(`${name}@${
|
|
246
|
-
out.push({ name, line: lineAtOffset(lineStarts,
|
|
334
|
+
seen.add(`${name}@${at}`);
|
|
335
|
+
out.push({ name, line: lineAtOffset(lineStarts, at) });
|
|
247
336
|
}
|
|
248
337
|
}
|
|
249
338
|
return out;
|
|
250
339
|
}
|
|
340
|
+
/** First offset of every callable name in the file — built once, looked up per register. */
|
|
341
|
+
function indexCallableSites(code) {
|
|
342
|
+
const first = new Map();
|
|
343
|
+
CALLABLE_SITE_RE.lastIndex = 0;
|
|
344
|
+
let m;
|
|
345
|
+
while ((m = CALLABLE_SITE_RE.exec(code)) !== null) {
|
|
346
|
+
const name = m[1];
|
|
347
|
+
if (!first.has(name))
|
|
348
|
+
first.set(name, m.index);
|
|
349
|
+
}
|
|
350
|
+
return first;
|
|
351
|
+
}
|
|
251
352
|
function findIgnoreAnnotations(content, registerName) {
|
|
252
353
|
const ignoreRe = new RegExp(`@shrkcrft\\s+lifecycle-ignore(?:\\s+([^\\n]+))?[\\s\\S]{0,200}?\\b${registerName}\\b`, 'm');
|
|
253
354
|
const managedRe = new RegExp(`@shrkcrft\\s+lifecycle-managed-by\\s+([\\w.-]+)[\\s\\S]{0,200}?\\b${registerName}\\b`, 'm');
|
|
@@ -274,88 +375,142 @@ function expectedRemoverNames(registerName) {
|
|
|
274
375
|
`${stem}Off`,
|
|
275
376
|
];
|
|
276
377
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
export function buildRegistryLifecycleReport(input) {
|
|
378
|
+
/**
|
|
379
|
+
* Create a scan: discover and sort the candidates, then judge them one
|
|
380
|
+
* {@link IRegistryLifecycleScan.step} at a time. The sync report builder and
|
|
381
|
+
* the signal-aware async runner both drive this — one loop, not two.
|
|
382
|
+
*/
|
|
383
|
+
export function createRegistryLifecycleScan(input) {
|
|
288
384
|
const { projectRoot } = input;
|
|
385
|
+
const clock = input.now ?? (() => Date.now());
|
|
289
386
|
const scope = input.scope && input.scope.length > 0 ? input.scope : undefined;
|
|
290
387
|
const changedOnly = input.files !== undefined;
|
|
291
|
-
const
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
388
|
+
const budgetMs = input.budgetMs ?? DEFAULT_BUDGET_MS;
|
|
389
|
+
const perFileBudgetMs = input.perFileBudgetMs ?? Math.max(1000, Math.floor(budgetMs / 4));
|
|
390
|
+
const rawLimit = input.limit ?? DEFAULT_LIMIT;
|
|
391
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.floor(rawLimit) : 0;
|
|
392
|
+
const requestedOffset = Math.max(0, Math.floor(input.offset ?? 0));
|
|
393
|
+
const skip = resolveRegistryLifecycleSkipDirs({
|
|
394
|
+
...(input.skipDirs ? { skipDirs: input.skipDirs } : {}),
|
|
395
|
+
...(input.skipDirsAdd ? { skipDirsAdd: input.skipDirsAdd } : {}),
|
|
396
|
+
});
|
|
397
|
+
const warnings = [];
|
|
398
|
+
if (input.skipDirs !== undefined && skip.droppedDefaults.length > 0) {
|
|
399
|
+
warnings.push(registryLifecycleSkipDirsWarning(skip.droppedDefaults));
|
|
400
|
+
}
|
|
401
|
+
// An existing config that failed to load: the configured skip set was never
|
|
402
|
+
// applied, so this walk is NOT the scope the project asked for. Loud (a
|
|
403
|
+
// warning line) AND settled (a coverage record the verdict reads).
|
|
404
|
+
const loadError = input.configLoadError;
|
|
405
|
+
const configCoverage = loadError
|
|
406
|
+
? {
|
|
407
|
+
unit: 'config files',
|
|
408
|
+
expected: 1,
|
|
409
|
+
examined: 0,
|
|
410
|
+
...(loadError.file ? { unexamined: [loadError.file], unexaminedTotal: 1 } : {}),
|
|
411
|
+
reason: 'failed to load, so registryLifecycle.skipDirs / skipDirsAdd were not applied (the scan used the default skip set)',
|
|
412
|
+
}
|
|
413
|
+
: undefined;
|
|
414
|
+
if (loadError) {
|
|
415
|
+
warnings.push('sharkcraft.config.ts failed to load — registryLifecycle.skipDirs / skipDirsAdd not applied, so this scan ' +
|
|
416
|
+
`used the default skip set (${loadError.message}). Run \`shrk doctor\`.`);
|
|
417
|
+
}
|
|
418
|
+
const deadline = clock('start') + budgetMs;
|
|
419
|
+
const walkRoot = changedOnly ? projectRoot : scope ? join(projectRoot, scope) : projectRoot;
|
|
420
|
+
const rel = (abs) => toPosix(relative(projectRoot, abs));
|
|
421
|
+
// Candidates, SORTED by project-relative path: without a stable order a
|
|
422
|
+
// continuation cannot be derived (readdir order is not one).
|
|
297
423
|
let files;
|
|
424
|
+
let walkComplete = true;
|
|
298
425
|
if (input.files !== undefined) {
|
|
299
|
-
|
|
426
|
+
const abs = input.files
|
|
300
427
|
.map((f) => (f.startsWith('/') ? f : join(projectRoot, f)))
|
|
301
428
|
.filter((f) => SCAN_EXTENSIONS.has(extname(f)));
|
|
429
|
+
files = [...new Set(abs)];
|
|
302
430
|
}
|
|
303
431
|
else {
|
|
304
|
-
const walkRoot = scope ? join(projectRoot, scope) : projectRoot;
|
|
305
432
|
files = [];
|
|
306
|
-
|
|
433
|
+
walkComplete = walkCandidates(walkRoot, files, new Set(skip.effective), () => clock('walk') >= deadline);
|
|
307
434
|
}
|
|
308
|
-
const
|
|
435
|
+
const relOf = new Map(files.map((f) => [f, rel(f)]));
|
|
436
|
+
files.sort((a, b) => comparePaths(relOf.get(a), relOf.get(b)));
|
|
437
|
+
const start = Math.min(requestedOffset, files.length);
|
|
438
|
+
const end = limit > 0 ? Math.min(files.length, start + limit) : files.length;
|
|
439
|
+
let cursor = start;
|
|
440
|
+
let finished = false;
|
|
441
|
+
let timedOut = !walkComplete;
|
|
442
|
+
let filesScanned = 0;
|
|
443
|
+
let registersFound = 0;
|
|
444
|
+
let generated = 0;
|
|
445
|
+
let missingCount = 0;
|
|
446
|
+
const oversized = [];
|
|
447
|
+
const unreadable = [];
|
|
448
|
+
const overBudget = [];
|
|
309
449
|
const matchedPairs = [];
|
|
310
450
|
const missingRemovers = [];
|
|
311
451
|
const oneShotBootstrap = [];
|
|
312
452
|
const ignored = [];
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
// a Date.now() deadline is the only interruption point. Flush partial results.
|
|
323
|
-
if (Date.now() > deadline) {
|
|
324
|
-
timedOut = true;
|
|
325
|
-
break;
|
|
453
|
+
function judgeFile(abs, file, fileStart) {
|
|
454
|
+
if (isGeneratedPath(abs))
|
|
455
|
+
return { kind: 'generated' };
|
|
456
|
+
let size;
|
|
457
|
+
try {
|
|
458
|
+
size = statSync(abs).size;
|
|
459
|
+
}
|
|
460
|
+
catch (e) {
|
|
461
|
+
return { kind: isMissing(e) ? 'missing' : 'unreadable' };
|
|
326
462
|
}
|
|
463
|
+
if (size > MAX_SCAN_FILE_BYTES)
|
|
464
|
+
return { kind: 'oversized' };
|
|
327
465
|
let content;
|
|
328
466
|
try {
|
|
329
|
-
content = readFileSync(
|
|
467
|
+
content = readFileSync(abs, 'utf8');
|
|
330
468
|
}
|
|
331
|
-
catch {
|
|
332
|
-
|
|
469
|
+
catch (e) {
|
|
470
|
+
return { kind: isMissing(e) ? 'missing' : 'unreadable' };
|
|
333
471
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
472
|
+
if (isGeneratedContent(content))
|
|
473
|
+
return { kind: 'generated' };
|
|
474
|
+
const fileDeadline = Math.min(deadline, fileStart + perFileBudgetMs);
|
|
475
|
+
const abandon = (phase, t, registersSeen) => ({
|
|
476
|
+
kind: 'over-budget',
|
|
477
|
+
entry: {
|
|
478
|
+
file,
|
|
479
|
+
phase,
|
|
480
|
+
deadline: t >= deadline ? 'run' : 'file',
|
|
481
|
+
elapsedMs: Math.max(0, t - fileStart),
|
|
482
|
+
registersSeen,
|
|
483
|
+
},
|
|
484
|
+
});
|
|
342
485
|
// Scan declarations on code with comments/strings blanked out; keep the raw
|
|
343
486
|
// content only for the comment-based @shrkcrft annotations.
|
|
344
487
|
const code = stripCommentsAndLiterals(content);
|
|
488
|
+
let t = clock('strip');
|
|
489
|
+
if (t >= fileDeadline)
|
|
490
|
+
return abandon('strip', t, 0);
|
|
345
491
|
const lineStarts = buildLineStarts(code);
|
|
346
492
|
const registers = findRegistersInFile(code, lineStarts);
|
|
493
|
+
t = clock('registers');
|
|
494
|
+
if (t >= fileDeadline)
|
|
495
|
+
return abandon('registers', t, registers.length);
|
|
347
496
|
// Per-file lifecycle evidence: only a file that BOTH accumulates removable
|
|
348
497
|
// state AND has a teardown-shaped API plausibly owes a per-register remover.
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
const
|
|
498
|
+
const ownsLifecycle = ACCUMULATION_RE.test(code) && TEARDOWN_RE.test(code);
|
|
499
|
+
const sites = registers.length > 0 ? indexCallableSites(code) : new Map();
|
|
500
|
+
const annotated = content.includes('@shrkcrft');
|
|
501
|
+
const pairs = [];
|
|
502
|
+
const missing = [];
|
|
503
|
+
const oneShot = [];
|
|
504
|
+
const ign = [];
|
|
352
505
|
for (const reg of registers) {
|
|
353
|
-
|
|
354
|
-
|
|
506
|
+
t = clock('register');
|
|
507
|
+
if (t >= fileDeadline)
|
|
508
|
+
return abandon('removers', t, registers.length);
|
|
509
|
+
const ann = annotated ? findIgnoreAnnotations(content, reg.name) : { ignore: false };
|
|
355
510
|
if (ann.ignore) {
|
|
356
|
-
|
|
511
|
+
ign.push({
|
|
357
512
|
registerName: reg.name,
|
|
358
|
-
file
|
|
513
|
+
file,
|
|
359
514
|
line: reg.line,
|
|
360
515
|
reason: ann.reason ?? 'ignored',
|
|
361
516
|
...(ann.managedBy ? { managedBy: ann.managedBy } : {}),
|
|
@@ -363,88 +518,323 @@ export function buildRegistryLifecycleReport(input) {
|
|
|
363
518
|
continue;
|
|
364
519
|
}
|
|
365
520
|
const candidates = expectedRemoverNames(reg.name);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
521
|
+
// Candidate PRIORITY order is preserved: the first expected name with a
|
|
522
|
+
// callable site wins, exactly as the per-name loop it replaces.
|
|
523
|
+
const removerName = candidates.find((n) => sites.has(n));
|
|
524
|
+
if (removerName !== undefined) {
|
|
525
|
+
pairs.push({
|
|
369
526
|
registerName: reg.name,
|
|
370
|
-
removerName
|
|
371
|
-
file
|
|
527
|
+
removerName,
|
|
528
|
+
file,
|
|
372
529
|
registerLine: reg.line,
|
|
373
|
-
removerLine:
|
|
530
|
+
removerLine: lineAtOffset(lineStarts, sites.get(removerName)),
|
|
374
531
|
});
|
|
375
532
|
}
|
|
376
533
|
else if (ownsLifecycle) {
|
|
377
|
-
|
|
534
|
+
missing.push({
|
|
378
535
|
registerName: reg.name,
|
|
379
536
|
expectedRemoverNames: candidates,
|
|
380
|
-
file
|
|
537
|
+
file,
|
|
381
538
|
line: reg.line,
|
|
382
539
|
suggestion: `Add ${candidates[0]}() / ${candidates[1]}() / ${candidates[2]}() — or annotate with \`@shrkcrft lifecycle-ignore <reason>\` / \`@shrkcrft lifecycle-managed-by <name>\` if cleanup is owned elsewhere.`,
|
|
383
540
|
});
|
|
384
541
|
}
|
|
385
542
|
else {
|
|
386
543
|
// No teardown-shaped API in the file → one-shot / bootstrap registration.
|
|
387
|
-
|
|
544
|
+
oneShot.push({
|
|
388
545
|
registerName: reg.name,
|
|
389
|
-
file
|
|
546
|
+
file,
|
|
390
547
|
line: reg.line,
|
|
391
548
|
reason: 'no teardown-shaped API in file — treated as one-shot bootstrap',
|
|
392
549
|
});
|
|
393
550
|
}
|
|
394
551
|
}
|
|
552
|
+
return { kind: 'judged', registers: registers.length, pairs, missing, oneShot, ignored: ign };
|
|
553
|
+
}
|
|
554
|
+
function step() {
|
|
555
|
+
if (finished)
|
|
556
|
+
return false;
|
|
557
|
+
if (cursor >= end) {
|
|
558
|
+
finished = true;
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
const fileStart = clock('file');
|
|
562
|
+
if (fileStart >= deadline) {
|
|
563
|
+
timedOut = true;
|
|
564
|
+
finished = true;
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
const abs = files[cursor];
|
|
568
|
+
const outcome = judgeFile(abs, relOf.get(abs), fileStart);
|
|
569
|
+
switch (outcome.kind) {
|
|
570
|
+
case 'generated':
|
|
571
|
+
generated += 1;
|
|
572
|
+
break;
|
|
573
|
+
case 'missing':
|
|
574
|
+
missingCount += 1;
|
|
575
|
+
break;
|
|
576
|
+
case 'oversized':
|
|
577
|
+
oversized.push(relOf.get(abs));
|
|
578
|
+
break;
|
|
579
|
+
case 'unreadable':
|
|
580
|
+
unreadable.push(relOf.get(abs));
|
|
581
|
+
break;
|
|
582
|
+
case 'over-budget':
|
|
583
|
+
overBudget.push(outcome.entry);
|
|
584
|
+
if (outcome.entry.deadline === 'run') {
|
|
585
|
+
// The RUN's deadline expired inside this file: stop, and leave the
|
|
586
|
+
// cursor ON it so `--offset <nextOffset>` re-scans it.
|
|
587
|
+
timedOut = true;
|
|
588
|
+
finished = true;
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
break;
|
|
592
|
+
case 'judged':
|
|
593
|
+
filesScanned += 1;
|
|
594
|
+
registersFound += outcome.registers;
|
|
595
|
+
matchedPairs.push(...outcome.pairs);
|
|
596
|
+
missingRemovers.push(...outcome.missing);
|
|
597
|
+
oneShotBootstrap.push(...outcome.oneShot);
|
|
598
|
+
ignored.push(...outcome.ignored);
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
cursor += 1;
|
|
602
|
+
return true;
|
|
603
|
+
}
|
|
604
|
+
function snapshot(options = {}) {
|
|
605
|
+
const interrupted = options.interrupted === true && cursor < end;
|
|
606
|
+
const nextOffset = walkComplete && cursor < files.length ? cursor : undefined;
|
|
607
|
+
const truncated = !walkComplete || cursor < files.length;
|
|
608
|
+
// Deliberate narrowing only: a generated file, and one deleted mid-walk.
|
|
609
|
+
// An over-cap file stays EXPECTED and is named unexamined below.
|
|
610
|
+
const excludedCount = generated + missingCount;
|
|
611
|
+
const expected = Math.max(0, files.length - start - excludedCount);
|
|
612
|
+
const fileOverBudget = overBudget.filter((o) => o.deadline === 'file').map((o) => o.file);
|
|
613
|
+
const remaining = files.slice(cursor).map((f) => relOf.get(f));
|
|
614
|
+
const unexaminedAll = [...new Set([...fileOverBudget, ...unreadable, ...oversized, ...remaining])];
|
|
615
|
+
const reason = coverageReason({
|
|
616
|
+
walkComplete,
|
|
617
|
+
interrupted,
|
|
618
|
+
timedOut,
|
|
619
|
+
capped: truncated,
|
|
620
|
+
budgetMs,
|
|
621
|
+
limit,
|
|
622
|
+
perFileBudgetMs,
|
|
623
|
+
cursor,
|
|
624
|
+
processed: cursor - start,
|
|
625
|
+
overBudgetCount: fileOverBudget.length,
|
|
626
|
+
unreadableCount: unreadable.length,
|
|
627
|
+
oversizedCount: oversized.length,
|
|
628
|
+
});
|
|
629
|
+
const coverage = {
|
|
630
|
+
unit: 'files',
|
|
631
|
+
expected,
|
|
632
|
+
examined: filesScanned,
|
|
633
|
+
root: walkRoot,
|
|
634
|
+
...(truncated ? { capped: true } : {}),
|
|
635
|
+
...(unexaminedAll.length > 0
|
|
636
|
+
? { unexamined: unexaminedAll.slice(0, UNEXAMINED_SHOWN), unexaminedTotal: unexaminedAll.length }
|
|
637
|
+
: {}),
|
|
638
|
+
...(reason ? { reason } : {}),
|
|
639
|
+
};
|
|
640
|
+
const registrationCoverage = {
|
|
641
|
+
unit: 'registrations',
|
|
642
|
+
expected: registersFound,
|
|
643
|
+
examined: registersFound,
|
|
644
|
+
root: walkRoot,
|
|
645
|
+
...(registersFound === 0 ? { reason: 'no register* declaration in the examined files' } : {}),
|
|
646
|
+
};
|
|
647
|
+
const recommendations = [];
|
|
648
|
+
if (missingRemovers.length > 0) {
|
|
649
|
+
recommendations.push(`Run \`shrk check registry-lifecycle --json\` and add the matching remover(s), or document why not via a \`@shrkcrft lifecycle-ignore\` / \`@shrkcrft lifecycle-managed-by\` annotation.`);
|
|
650
|
+
}
|
|
651
|
+
const settled = registryLifecycleVerdict({
|
|
652
|
+
missingRemovers,
|
|
653
|
+
coverage,
|
|
654
|
+
registrationCoverage,
|
|
655
|
+
...(configCoverage ? { configCoverage } : {}),
|
|
656
|
+
});
|
|
657
|
+
return {
|
|
658
|
+
schema: 'sharkcraft.registry-lifecycle/v1',
|
|
659
|
+
filesScanned,
|
|
660
|
+
totalFiles: files.length,
|
|
661
|
+
truncated,
|
|
662
|
+
timedOut,
|
|
663
|
+
interrupted,
|
|
664
|
+
walkComplete,
|
|
665
|
+
changedOnly,
|
|
666
|
+
...(scope ? { scope } : {}),
|
|
667
|
+
offset: start,
|
|
668
|
+
limit,
|
|
669
|
+
budgetMs,
|
|
670
|
+
perFileBudgetMs,
|
|
671
|
+
candidatesExamined: cursor - start,
|
|
672
|
+
...(nextOffset !== undefined ? { nextOffset } : {}),
|
|
673
|
+
excludedFiles: { generated, missing: missingCount, oversized: [...oversized] },
|
|
674
|
+
unreadableFiles: [...unreadable],
|
|
675
|
+
overBudgetFiles: [...overBudget],
|
|
676
|
+
skipDirs: skip.effective,
|
|
677
|
+
droppedDefaultSkipDirs: skip.droppedDefaults,
|
|
678
|
+
warnings: [...warnings],
|
|
679
|
+
registersFound,
|
|
680
|
+
matchedPairs: [...matchedPairs],
|
|
681
|
+
missingRemovers: [...missingRemovers],
|
|
682
|
+
oneShotBootstrap: [...oneShotBootstrap],
|
|
683
|
+
ignored: [...ignored],
|
|
684
|
+
recommendations,
|
|
685
|
+
coverage,
|
|
686
|
+
registrationCoverage,
|
|
687
|
+
...(configCoverage ? { configCoverage } : {}),
|
|
688
|
+
verdict: settled.verdict,
|
|
689
|
+
...(settled.reason !== undefined ? { verdictReason: settled.reason } : {}),
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
return { step, snapshot };
|
|
693
|
+
}
|
|
694
|
+
/** Why the files coverage fell short — the continuation lives here, so the verdict line carries it. */
|
|
695
|
+
function coverageReason(s) {
|
|
696
|
+
if (!s.walkComplete) {
|
|
697
|
+
return `the ${s.budgetMs} ms wall-clock budget expired during the tree walk, before every candidate was found; narrow with --scope <dir> or raise --budget-ms`;
|
|
698
|
+
}
|
|
699
|
+
if (s.interrupted)
|
|
700
|
+
return `interrupted by a signal after ${s.processed} candidate(s); continue with --offset ${s.cursor}`;
|
|
701
|
+
if (s.timedOut) {
|
|
702
|
+
return `the ${s.budgetMs} ms wall-clock budget expired after ${s.processed} candidate(s); continue with --offset ${s.cursor}, or raise --budget-ms`;
|
|
703
|
+
}
|
|
704
|
+
if (s.capped)
|
|
705
|
+
return `--limit ${s.limit} reached; continue with --offset ${s.cursor} (or --limit 0 for an uncapped run)`;
|
|
706
|
+
const parts = [];
|
|
707
|
+
if (s.overBudgetCount > 0)
|
|
708
|
+
parts.push(`over the per-file budget (${s.perFileBudgetMs} ms) and never judged`);
|
|
709
|
+
if (s.unreadableCount > 0)
|
|
710
|
+
parts.push('unreadable');
|
|
711
|
+
if (s.oversizedCount > 0)
|
|
712
|
+
parts.push(`over the ${LIFECYCLE_READ_CAP} lifecycle read cap, so never judged`);
|
|
713
|
+
if (parts.length === 0)
|
|
714
|
+
return undefined;
|
|
715
|
+
// The budget remedy only reaches what a budget stopped; an over-cap file is
|
|
716
|
+
// never judged whatever the budget.
|
|
717
|
+
const remedy = s.overBudgetCount > 0 || s.unreadableCount > 0 ? ' — raise --budget-ms or narrow with --scope <dir>' : '';
|
|
718
|
+
return `${parts.join(' or ')}${remedy}`;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* THE lifecycle verdict. Both CLI verbs settle the same coverage records
|
|
722
|
+
* through `buildGateEnvelope`, and the MCP tool reads this — every surface
|
|
723
|
+
* answers from `coverageShortfall`, never a re-derived ternary.
|
|
724
|
+
*
|
|
725
|
+
* - a missing remover in the examined scope → `fail` (a real violation is
|
|
726
|
+
* real however much of the tree was examined);
|
|
727
|
+
* - otherwise any coverage shortfall (a config that failed to load, a cap,
|
|
728
|
+
* an expired budget, a signal, an over-budget or unreadable file, nothing
|
|
729
|
+
* in scope, no registrations) → `not-verified`, with the shortfall as the
|
|
730
|
+
* reason;
|
|
731
|
+
* - otherwise `pass`.
|
|
732
|
+
*/
|
|
733
|
+
export function registryLifecycleVerdict(report) {
|
|
734
|
+
if (report.missingRemovers.length > 0) {
|
|
735
|
+
return {
|
|
736
|
+
verdict: 'fail',
|
|
737
|
+
reason: `${report.missingRemovers.length} register* declaration(s) with no matching remover`,
|
|
738
|
+
};
|
|
395
739
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
truncated: files.length > scanFiles.length || timedOut,
|
|
405
|
-
timedOut,
|
|
406
|
-
changedOnly,
|
|
407
|
-
...(scope ? { scope } : {}),
|
|
408
|
-
registersFound,
|
|
409
|
-
matchedPairs,
|
|
410
|
-
missingRemovers,
|
|
411
|
-
oneShotBootstrap,
|
|
412
|
-
ignored,
|
|
413
|
-
recommendations,
|
|
414
|
-
};
|
|
740
|
+
// The config shortfall FIRST: when the configured scope was never applied,
|
|
741
|
+
// every other count describes the wrong scope.
|
|
742
|
+
const gap = (report.configCoverage ? coverageShortfall(report.configCoverage) : undefined) ??
|
|
743
|
+
coverageShortfall(report.coverage) ??
|
|
744
|
+
coverageShortfall(report.registrationCoverage);
|
|
745
|
+
if (gap !== undefined)
|
|
746
|
+
return { verdict: 'not-verified', reason: gap };
|
|
747
|
+
return { verdict: 'pass' };
|
|
415
748
|
}
|
|
416
|
-
|
|
749
|
+
/** Synchronous scan: drives {@link createRegistryLifecycleScan} to the end. */
|
|
750
|
+
export function buildRegistryLifecycleReport(input) {
|
|
751
|
+
const scan = createRegistryLifecycleScan(input);
|
|
752
|
+
while (scan.step()) {
|
|
753
|
+
// one candidate per step — the budget is checked inside each
|
|
754
|
+
}
|
|
755
|
+
return scan.snapshot();
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Signal-aware scan: the same {@link IRegistryLifecycleScan.step}, yielding to
|
|
759
|
+
* the event loop between files so a SIGTERM / SIGINT handler can run. An
|
|
760
|
+
* aborted run returns the partial report with `interrupted: true` and a
|
|
761
|
+
* `nextOffset` that continues it. Latency is bounded by one (linear) file.
|
|
762
|
+
*/
|
|
763
|
+
export async function runRegistryLifecycleScan(input, options = {}) {
|
|
764
|
+
const scan = createRegistryLifecycleScan(input);
|
|
765
|
+
for (;;) {
|
|
766
|
+
if (options.signal?.aborted)
|
|
767
|
+
return scan.snapshot({ interrupted: true });
|
|
768
|
+
if (!scan.step())
|
|
769
|
+
return scan.snapshot();
|
|
770
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
export function renderRegistryLifecycleReportText(report, options = {}) {
|
|
774
|
+
const command = options.command ?? 'shrk check registry-lifecycle';
|
|
417
775
|
const lines = [];
|
|
418
776
|
lines.push('=== Registry lifecycle ===');
|
|
419
777
|
if (report.scope)
|
|
420
778
|
lines.push(` scope ${report.scope}`);
|
|
421
779
|
if (report.changedOnly)
|
|
422
780
|
lines.push(' scope changed-only');
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (report.changedOnly && report.filesScanned === 0) {
|
|
426
|
-
lines.push('');
|
|
427
|
-
lines.push(' ! 0 files in the changed scope — lifecycle NOT verified (this is not a pass).');
|
|
428
|
-
return lines.join('\n') + '\n';
|
|
429
|
-
}
|
|
430
|
-
if (report.timedOut) {
|
|
431
|
-
lines.push(` ! wall-clock budget hit — scanned ${report.filesScanned}/${report.totalFiles} before flushing partial results (re-run with --scope <dir> to finish).`);
|
|
432
|
-
}
|
|
433
|
-
lines.push(` files scanned ${report.filesScanned}` +
|
|
434
|
-
(report.truncated && !report.timedOut
|
|
435
|
-
? ` ! capped (${report.totalFiles} candidates — re-run with --scope <dir> for the rest)`
|
|
436
|
-
: ''));
|
|
781
|
+
lines.push(` candidates ${report.totalFiles}` + (report.offset > 0 ? ` (this run starts at offset ${report.offset})` : ''));
|
|
782
|
+
lines.push(` files scanned ${report.filesScanned} of ${report.coverage.expected}`);
|
|
437
783
|
lines.push(` registers found ${report.registersFound}`);
|
|
438
784
|
lines.push(` matched pairs ${report.matchedPairs.length}`);
|
|
439
785
|
lines.push(` missing removers ${report.missingRemovers.length}`);
|
|
440
786
|
lines.push(` one-shot bootstrap ${report.oneShotBootstrap.length}`);
|
|
441
787
|
lines.push(` ignored ${report.ignored.length}`);
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
788
|
+
const ex = report.excludedFiles;
|
|
789
|
+
if (ex.generated + ex.missing > 0) {
|
|
790
|
+
const parts = [];
|
|
791
|
+
if (ex.generated > 0)
|
|
792
|
+
parts.push(`${ex.generated} generated`);
|
|
793
|
+
if (ex.missing > 0)
|
|
794
|
+
parts.push(`${ex.missing} deleted`);
|
|
795
|
+
lines.push(` excluded ${parts.join(', ')}`);
|
|
796
|
+
}
|
|
797
|
+
// An over-cap file is UNEXAMINED (it is in the coverage's expected scope),
|
|
798
|
+
// never "excluded": listed with the other files that were never judged.
|
|
799
|
+
for (const o of ex.oversized.slice(0, 20)) {
|
|
800
|
+
lines.push(` ! over read cap ${o} — over the ${LIFECYCLE_READ_CAP} lifecycle read cap, never judged`);
|
|
801
|
+
}
|
|
802
|
+
for (const o of report.overBudgetFiles) {
|
|
803
|
+
lines.push(` ! over budget ${o.file} — ${o.phase} phase, ${o.elapsedMs} ms (${o.deadline === 'run' ? "the run's budget" : `the ${report.perFileBudgetMs} ms per-file budget`}); ${o.registersSeen} register(s) seen, none judged`);
|
|
804
|
+
}
|
|
805
|
+
for (const u of report.unreadableFiles.slice(0, 20))
|
|
806
|
+
lines.push(` ! unreadable ${u}`);
|
|
807
|
+
for (const w of report.warnings)
|
|
808
|
+
lines.push(` ! ${w}`);
|
|
809
|
+
// Scope facts — what was NOT examined and how to reach it. The verdict line
|
|
810
|
+
// itself is the caller's (the CLI settles it through the gate envelope).
|
|
811
|
+
const remainingCount = report.totalFiles - (report.offset + report.candidatesExamined);
|
|
812
|
+
const resume = report.nextOffset !== undefined ? `${command} --offset ${report.nextOffset}` : undefined;
|
|
813
|
+
if (report.coverage.expected === 0 && report.walkComplete) {
|
|
814
|
+
lines.push('');
|
|
815
|
+
lines.push(report.changedOnly
|
|
816
|
+
? ' ! 0 files in the changed scope — nothing to judge.'
|
|
817
|
+
: ' ! 0 candidate files in scope — nothing to judge.');
|
|
818
|
+
}
|
|
819
|
+
else if (report.registersFound === 0 && report.filesScanned > 0 && !report.truncated) {
|
|
820
|
+
lines.push('');
|
|
821
|
+
lines.push(' ! 0 register* declarations in the examined files — nothing to judge.');
|
|
822
|
+
}
|
|
823
|
+
if (!report.walkComplete) {
|
|
824
|
+
lines.push('');
|
|
825
|
+
lines.push(` ! wall-clock budget (${report.budgetMs} ms) expired during the tree walk — ${report.totalFiles} candidate(s) found so far; narrow with --scope <dir> or raise --budget-ms.`);
|
|
826
|
+
}
|
|
827
|
+
else if (report.interrupted && resume) {
|
|
828
|
+
lines.push('');
|
|
829
|
+
lines.push(` ! INTERRUPTED — partial results (scanned ${report.filesScanned}/${report.coverage.expected}); continue with ${resume}`);
|
|
830
|
+
}
|
|
831
|
+
else if (report.timedOut && resume) {
|
|
832
|
+
lines.push('');
|
|
833
|
+
lines.push(` ! wall-clock budget (${report.budgetMs} ms) hit — scanned ${report.filesScanned}/${report.coverage.expected}; continue with ${resume} (or raise --budget-ms)`);
|
|
834
|
+
}
|
|
835
|
+
else if (resume) {
|
|
446
836
|
lines.push('');
|
|
447
|
-
lines.push(
|
|
837
|
+
lines.push(` ! capped — scanned ${report.candidatesExamined} of ${report.totalFiles - report.offset} candidate files (cap --limit ${report.limit}); ${remainingCount} unexamined. Continue: ${resume} (or --limit 0 for an uncapped run)`);
|
|
448
838
|
}
|
|
449
839
|
lines.push('');
|
|
450
840
|
if (report.missingRemovers.length > 0) {
|