@event4u/agent-config 9.14.0 → 9.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +110 -112
  3. package/README.md +8 -0
  4. package/dist/agent-src/commands/agents/audit.md +7 -7
  5. package/dist/agent-src/commands/agents/optimize.md +1 -1
  6. package/dist/agent-src/commands/analyze/reference-repo.md +1 -1
  7. package/dist/agent-src/commands/chat-history.md +1 -0
  8. package/dist/agent-src/commands/context.md +1 -0
  9. package/dist/agent-src/commands/council.md +1 -1
  10. package/dist/agent-src/commands/ghostwriter.md +1 -1
  11. package/dist/agent-src/commands/memory.md +2 -1
  12. package/dist/agent-src/commands/module.md +1 -0
  13. package/dist/agent-src/commands/optimize/agents-dir.md +1 -1
  14. package/dist/agent-src/commands/optimize/deep.md +5 -2
  15. package/dist/agent-src/commands/optimize/skills.md +5 -5
  16. package/dist/agent-src/commands/override.md +1 -0
  17. package/dist/agent-src/commands/prediction-pool.md +4 -4
  18. package/dist/agent-src/commands/research/deep.md +1 -1
  19. package/dist/agent-src/commands/roadmap.md +2 -1
  20. package/dist/agent-src/commands/rule-compliance-audit.md +1 -1
  21. package/dist/agent-src/commands/tdd.md +1 -0
  22. package/dist/agent-src/commands/tests.md +1 -0
  23. package/dist/agent-src/commands/upstream-contribute.md +5 -5
  24. package/dist/agent-src/commands/video/from-script.md +1 -1
  25. package/dist/agent-src/commands/video/from-song.md +1 -1
  26. package/dist/agent-src/commands/video/scene.md +1 -1
  27. package/dist/agent-src/commands/video/stitch.md +1 -1
  28. package/dist/agent-src/commands/video/storyboard.md +1 -1
  29. package/dist/agent-src/commands/worktree/create.md +2 -1
  30. package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
  31. package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +5 -5
  32. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -3
  33. package/dist/agent-src/contexts/contracts/emergency-triage-block.md +2 -2
  34. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +4 -3
  35. package/dist/agent-src/contexts/execution/subagent-routing.md +19 -0
  36. package/dist/agent-src/contexts/override-system.md +1 -1
  37. package/dist/agent-src/ghostwriter/fictional-fixture-v1.md +1 -1
  38. package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
  39. package/dist/agent-src/rules/autonomous-execution.md +2 -1
  40. package/dist/agent-src/rules/brand-consistency.md +1 -0
  41. package/dist/agent-src/rules/brand-source-of-truth.md +1 -0
  42. package/dist/agent-src/rules/code-comment-discipline.md +2 -0
  43. package/dist/agent-src/rules/communication-through-line.md +1 -0
  44. package/dist/agent-src/rules/content-quoting-floor.md +1 -0
  45. package/dist/agent-src/rules/cross-source-consistency.md +0 -1
  46. package/dist/agent-src/rules/downstream-changes.md +1 -0
  47. package/dist/agent-src/rules/external-code-graph-interop.md +1 -0
  48. package/dist/agent-src/rules/external-reference-deep-dive.md +1 -0
  49. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
  50. package/dist/agent-src/rules/finance-safety-floor.md +0 -1
  51. package/dist/agent-src/rules/icon-consistency.md +1 -0
  52. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
  53. package/dist/agent-src/rules/improve-before-implement.md +1 -1
  54. package/dist/agent-src/rules/invite-challenge.md +1 -0
  55. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
  56. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
  57. package/dist/agent-src/rules/markdown-safe-codeblocks.md +1 -0
  58. package/dist/agent-src/rules/media-governance-routing.md +4 -3
  59. package/dist/agent-src/rules/media-sync-ground-truth.md +1 -0
  60. package/dist/agent-src/rules/no-attribution-footers.md +1 -0
  61. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +1 -0
  62. package/dist/agent-src/rules/no-pr-progress-comments.md +1 -0
  63. package/dist/agent-src/rules/onboarding-gate.md +1 -0
  64. package/dist/agent-src/rules/output-discipline.md +1 -0
  65. package/dist/agent-src/rules/prefer-enums-over-literals.md +1 -0
  66. package/dist/agent-src/rules/preservation-guard.md +1 -0
  67. package/dist/agent-src/rules/question-not-instruction.md +1 -0
  68. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +1 -0
  69. package/dist/agent-src/rules/role-mode-adherence.md +1 -0
  70. package/dist/agent-src/rules/runtime-safety.md +1 -0
  71. package/dist/agent-src/rules/security-sensitive-stop.md +1 -0
  72. package/dist/agent-src/rules/session-canary.md +9 -2
  73. package/dist/agent-src/rules/source-confidentiality.md +1 -0
  74. package/dist/agent-src/rules/source-of-truth.md +1 -0
  75. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -0
  76. package/dist/agent-src/rules/think-before-action.md +1 -0
  77. package/dist/agent-src/rules/token-budget-discipline.md +1 -0
  78. package/dist/agent-src/rules/token-efficiency.md +1 -0
  79. package/dist/agent-src/rules/token-optimizer-maintenance.md +5 -5
  80. package/dist/agent-src/rules/tool-safety.md +1 -0
  81. package/dist/agent-src/rules/untrusted-input-defense.md +2 -0
  82. package/dist/agent-src/rules/user-interaction.md +1 -0
  83. package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
  84. package/dist/agent-src/skills/adr-create/SKILL.md +1 -1
  85. package/dist/agent-src/skills/check-refs/SKILL.md +1 -1
  86. package/dist/agent-src/skills/competitive-positioning/SKILL.md +1 -1
  87. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  88. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  89. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +1 -1
  90. package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
  91. package/dist/agent-src/skills/github-ci/SKILL.md +1 -0
  92. package/dist/agent-src/skills/guideline-writing/SKILL.md +1 -1
  93. package/dist/agent-src/skills/lint-skills/SKILL.md +1 -1
  94. package/dist/agent-src/skills/readme-reviewer/SKILL.md +1 -1
  95. package/dist/agent-src/skills/roadmap-management/SKILL.md +8 -1
  96. package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
  97. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
  98. package/dist/agent-src/skills/skill-writing/SKILL.md +4 -4
  99. package/dist/agent-src/skills/token-optimizer/SKILL.md +4 -4
  100. package/dist/agent-src/skills/upstream-contribute/SKILL.md +6 -6
  101. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +25 -0
  102. package/dist/agent-src/templates/AGENTS.md +1 -1
  103. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  104. package/dist/agent-src/templates/command.md +1 -1
  105. package/dist/agent-src/templates/copilot-instructions.md +3 -3
  106. package/dist/agent-src/templates/rule.md +2 -2
  107. package/dist/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
  108. package/dist/agent-src/templates/skill-archive-note.md +5 -5
  109. package/dist/agent-src/templates/skill.md +1 -1
  110. package/dist/cli/agent-config.js +66 -19
  111. package/dist/cli/agent-config.js.map +1 -1
  112. package/dist/cli/main.js +9 -4
  113. package/dist/cli/main.js.map +1 -1
  114. package/dist/cli/python/workspace_drive.js +2 -0
  115. package/dist/cli/python/workspace_drive.js.map +1 -1
  116. package/dist/cli/python/workspace_drive_health.js +2 -0
  117. package/dist/cli/python/workspace_drive_health.js.map +1 -1
  118. package/dist/cli/python/workspace_hosts.js +2 -0
  119. package/dist/cli/python/workspace_hosts.js.map +1 -1
  120. package/dist/cli/python/workspace_sessions.js +2 -0
  121. package/dist/cli/python/workspace_sessions.js.map +1 -1
  122. package/dist/cli/registry.js +1 -0
  123. package/dist/cli/registry.js.map +1 -1
  124. package/dist/cli-delegate/{chunk-A3HJ6NTI.js → chunk-63WSP6YZ.js} +2 -1
  125. package/dist/cli-delegate/{chunk-EJYIGZ3T.js → chunk-BKO2AZ7Z.js} +1 -1
  126. package/dist/cli-delegate/{chunk-GCVFLBP2.js → chunk-H574KOUH.js} +338 -494
  127. package/dist/cli-delegate/chunk-NXFWFAYV.js +339 -0
  128. package/dist/cli-delegate/{chunk-TEGJU2JX.js → chunk-ZXXJLL5K.js} +2 -2
  129. package/dist/cli-delegate/cmd_conformance.js +29 -23
  130. package/dist/cli-delegate/cmd_doctor.js +3 -3
  131. package/dist/cli-delegate/cmd_export.js +4 -4
  132. package/dist/cli-delegate/cmd_preflight.js +2 -2
  133. package/dist/cli-delegate/cmd_prune.js +4 -4
  134. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  135. package/dist/cli-delegate/cmd_sync.js +4 -4
  136. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  137. package/dist/cli-delegate/cmd_validate.js +4 -4
  138. package/dist/discovery/deprecation-report.md +1 -1
  139. package/dist/discovery/discovery-manifest.json +127 -95
  140. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  141. package/dist/discovery/discovery-manifest.summary.md +1 -1
  142. package/dist/discovery/orphan-report.md +1 -1
  143. package/dist/discovery/packs.json +2 -2
  144. package/dist/discovery/trust-report.md +1 -1
  145. package/dist/discovery/workspaces.json +2 -2
  146. package/dist/hooks/dispatch.js +729 -430
  147. package/dist/install/install.mjs +52 -11
  148. package/dist/install/rule_scope.js +18 -2
  149. package/dist/install/rule_scope.js.map +1 -1
  150. package/dist/mcp/registry-manifest.json +2 -2
  151. package/dist/mcp/server.json +2 -2
  152. package/dist/mcp/server.mjs +518 -411
  153. package/dist/router.json +1 -1
  154. package/dist/scripts/_lib/claude_settings_hooks.js +30 -5
  155. package/dist/scripts/_lib/claude_settings_hooks.js.map +1 -1
  156. package/dist/scripts/_lib/scoped_projection.js +223 -0
  157. package/dist/scripts/_lib/scoped_projection.js.map +1 -0
  158. package/dist/scripts/_lib/surface_tiers.js +125 -0
  159. package/dist/scripts/_lib/surface_tiers.js.map +1 -0
  160. package/dist/scripts/_lib/token_count.js +166 -0
  161. package/dist/scripts/_lib/token_count.js.map +1 -0
  162. package/dist/scripts/_lib/trigger_eval_floors.js +8 -0
  163. package/dist/scripts/_lib/trigger_eval_floors.js.map +1 -1
  164. package/dist/scripts/condense.js +139 -9
  165. package/dist/scripts/condense.js.map +1 -1
  166. package/dist/scripts/project_thin_rules.js +450 -0
  167. package/dist/scripts/project_thin_rules.js.map +1 -0
  168. package/dist/server/routes/workspace.js +2 -0
  169. package/dist/server/routes/workspace.js.map +1 -1
  170. package/dist/server/schemas/settings.js +9 -3
  171. package/dist/server/schemas/settings.js.map +1 -1
  172. package/dist/ui/assets/index-DJY_vQVn.js +40 -0
  173. package/dist/ui/assets/index-DJY_vQVn.js.map +1 -0
  174. package/dist/ui/index.html +1 -1
  175. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  176. package/package.json +11 -11
  177. package/src/agent-src/templates/AGENTS.md +1 -1
  178. package/src/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
  179. package/src/config/agent-settings.template.yml +59 -11
  180. package/src/config/ci-local-parity.yml +8 -0
  181. package/src/config/discovery/unassigned-artefacts.yml +23 -25
  182. package/src/config/evaluator-budgets.json +35 -5
  183. package/src/config/gate-coverage.yml +147 -0
  184. package/src/config/gate-violation-baselines.json +25 -0
  185. package/src/install/rule_scope.ts +27 -2
  186. package/src/scripts/_cli/cmd_conformance.ts +13 -24
  187. package/src/scripts/_dispatch.bash +10 -0
  188. package/src/scripts/_lib/claude_settings_hooks.ts +30 -4
  189. package/src/scripts/_lib/gate_baseline.ts +213 -0
  190. package/src/scripts/_lib/scoped_projection.ts +50 -0
  191. package/src/scripts/_lib/tier_budget_routing.ts +234 -0
  192. package/src/scripts/_lib/tool_adapter_registry.ts +8 -1
  193. package/src/scripts/_lib/trigger_eval_floors.ts +9 -0
  194. package/src/scripts/_lib/trigger_routers.ts +17 -5
  195. package/src/scripts/adr/regenerate_index.ts +4 -3
  196. package/src/scripts/ai-video/lib/parse-blueprint.sh +1 -1
  197. package/src/scripts/ai_council/compile_corpus.ts +1 -1
  198. package/src/scripts/audit_cloud_compatibility.ts +37 -2
  199. package/src/scripts/audit_initial_context.ts +53 -19
  200. package/src/scripts/audit_likelihood.ts +31 -2
  201. package/src/scripts/audit_user_type_axis.ts +58 -11
  202. package/src/scripts/bench_hook_latency.ts +172 -41
  203. package/src/scripts/build_mcp_catalog.ts +12 -1
  204. package/src/scripts/check_always_budget.ts +122 -11
  205. package/src/scripts/check_augment_description_cap.ts +24 -3
  206. package/src/scripts/check_ci_strict_superset.ts +150 -0
  207. package/src/scripts/check_cluster_patterns.ts +100 -0
  208. package/src/scripts/check_consumer_scope_flip.ts +26 -4
  209. package/src/scripts/check_evaluator_budgets.ts +198 -19
  210. package/src/scripts/check_gate_coverage.ts +337 -1
  211. package/src/scripts/check_generator_output_coverage.ts +2 -1
  212. package/src/scripts/check_iron_law_prominence.ts +1 -1
  213. package/src/scripts/check_kernel_rule_bundle.ts +1 -1
  214. package/src/scripts/check_no_new_legacy_path.ts +167 -3
  215. package/src/scripts/check_pack_size.ts +18 -4
  216. package/src/scripts/check_portability.ts +37 -7
  217. package/src/scripts/check_references.ts +19 -3
  218. package/src/scripts/check_release_pr_shape.ts +13 -0
  219. package/src/scripts/check_token_regression.ts +9 -2
  220. package/src/scripts/condense.ts +155 -12
  221. package/src/scripts/cost/budget.mjs +63 -2
  222. package/src/scripts/evaluator_umbrella.sh +34 -1
  223. package/src/scripts/generate_capability_matrix.ts +8 -0
  224. package/src/scripts/generate_router_coverage_from_matrix.ts +155 -0
  225. package/src/scripts/hook_manifest.yaml +17 -3
  226. package/src/scripts/hooks/block_config_weakening.ts +337 -0
  227. package/src/scripts/hooks/concern_registry.ts +2 -0
  228. package/src/scripts/hooks/probe_throttle.ts +75 -0
  229. package/src/scripts/install-hooks.sh +24 -2
  230. package/src/scripts/install.ts +2 -2
  231. package/src/scripts/lint_agents_md.ts +9 -3
  232. package/src/scripts/lint_archived_skills.ts +1 -1
  233. package/src/scripts/lint_artefact_frontmatter.ts +185 -37
  234. package/src/scripts/lint_command_routing.ts +21 -52
  235. package/src/scripts/lint_command_verbs.ts +47 -28
  236. package/src/scripts/lint_context_spine_usage.ts +38 -12
  237. package/src/scripts/lint_framework_leakage.ts +25 -6
  238. package/src/scripts/lint_handoffs.ts +49 -2
  239. package/src/scripts/lint_media_policy_linkage.ts +62 -30
  240. package/src/scripts/lint_namespace.ts +92 -7
  241. package/src/scripts/lint_new_skill_gate.ts +39 -31
  242. package/src/scripts/lint_originality_shingles.ts +7 -1
  243. package/src/scripts/lint_override_kernel_guard.ts +21 -3
  244. package/src/scripts/lint_pack_boundaries.ts +461 -91
  245. package/src/scripts/lint_pack_dependencies.ts +24 -57
  246. package/src/scripts/lint_persona_governance.ts +1 -1
  247. package/src/scripts/lint_role_experiences.ts +34 -5
  248. package/src/scripts/lint_trigger_precision.ts +142 -0
  249. package/src/scripts/mcp_server/consumer_tool_catalog.json +12 -201
  250. package/src/scripts/mcp_server/tools.ts +1 -1
  251. package/src/scripts/prepack-check.mjs +40 -1
  252. package/src/scripts/prepack_router_targets.d.mts +7 -0
  253. package/src/scripts/prepack_router_targets.mjs +93 -0
  254. package/src/scripts/print_required_checks.ts +72 -18
  255. package/src/scripts/profile_staleness_hook.ts +12 -0
  256. package/src/scripts/record_evaluator_measurements.mjs +105 -0
  257. package/src/scripts/recruit_preflight.sh +1 -1
  258. package/src/scripts/release.ts +105 -1
  259. package/src/scripts/router_target_paths.d.mts +4 -0
  260. package/src/scripts/router_target_paths.mjs +69 -0
  261. package/src/scripts/router_telemetry.ts +52 -1
  262. package/src/scripts/routing_doctor.ts +485 -0
  263. package/src/scripts/rule_trigger_eval.ts +403 -0
  264. package/src/scripts/schemas/rule.schema.json +5 -1
  265. package/src/scripts/session_canary_hook.ts +96 -5
  266. package/src/scripts/skill_linter.ts +9 -28
  267. package/src/scripts/smoke/skills.sh +1 -1
  268. package/src/scripts/sweep_dead_scan_roots.ts +356 -10
  269. package/src/scripts/trigger_coverage.ts +13 -2
  270. package/src/scripts/update_counts.ts +1 -1
  271. package/src/scripts/validate_telegraph_carveouts.ts +1 -1
  272. package/src/scripts/wrapper_freshness_hook.ts +14 -0
  273. package/src/server/schemas/settings.ts +19 -5
  274. package/dist/cli-delegate/chunk-TJIAM5FW.js +0 -133
  275. package/dist/ui/assets/index-BpSQt5vm.js +0 -40
  276. package/dist/ui/assets/index-BpSQt5vm.js.map +0 -1
@@ -2,16 +2,54 @@
2
2
  /**
3
3
  * Enforce cross-pack reference boundaries.
4
4
  *
5
- * Ported from the retired Python `src/scripts/lint_pack_boundaries.py` (ADR-200, Phase 4 /
6
- * Wave 4b). Mirrors the Python CLI contract exactly: `--format text|json`,
7
- * `--quiet`, same scan scope (packages/*\/.agent-src.uncondensed/), file
8
- * ordering, link regex, resolution semantics, finding messages, stdout/stderr
9
- * split, and exit codes (0 clean / skipped, 1 violations). No behaviour
10
- * changes — historical quirks preserved (consumers pin the exact behaviour).
5
+ * Walks every markdown link in every source artefact and verifies the link
6
+ * target's pack is the same pack, `core` (always allowed), or reachable from
7
+ * the source pack's `requires` graph. A link that crosses an undeclared pack
8
+ * boundary is dead the moment a consumer installs the source pack without the
9
+ * target's pack.
11
10
  *
12
- * Walks every markdown link in every artefact under
13
- * `packages/*\/.agent-src.uncondensed/` and verifies the link target's pack is
14
- * the same pack, `core` (always allowed), or in the source pack's `requires`.
11
+ * ## Scan-root repair (2026-08-02) — what changed and what parity survives
12
+ *
13
+ * This script was ported from a retired Python original and its header claimed
14
+ * byte-exact parity with it ("No behaviour changes — historical quirks
15
+ * preserved"). That claim is now PARTLY FALSE and is corrected here rather
16
+ * than left standing:
17
+ *
18
+ * - **BROKEN deliberately:** the scan root. The original walked the retired
19
+ * per-package source container under `packages/` — a tree ADR-051 split and
20
+ * a later commit deleted. The gate therefore printed `no packages/ tree to
21
+ * lint — skipping` and exited 0 on every run since — it enforced nothing.
22
+ * The corpus is now the live artefact tree via the shared resolver
23
+ * (`_lib/agent_src.iter_artefacts`), and an empty corpus is a LOUD failure
24
+ * (`_lib/scan_scope.assertScanned`), not a silent skip.
25
+ * - **BROKEN deliberately:** pack attribution. The original read the pack from
26
+ * the `packages/<pack>/` directory the artefact lived in. That layout is
27
+ * gone, so the pack now comes from the artefact's own `packs:` frontmatter
28
+ * (see `_packs_of` for the full rule, including the fail-safe).
29
+ * - **BROKEN deliberately:** `requires` is expanded TRANSITIVELY. The original
30
+ * compared against the direct list only, which reports a violation for a
31
+ * target the resolver provably does install (`nextjs` → `javascript`, via
32
+ * `typescript`). `src/config/discovery/packs.yml` documents `requires` as
33
+ * "the hard dependency graph (transitive, acyclic) the resolver expands";
34
+ * this gate now matches that definition.
35
+ * - **BROKEN deliberately:** exit code 2 is new (dead scan scope). 0 and 1
36
+ * keep their meanings.
37
+ * - **STILL HOLDS:** the CLI surface (`--format text|json`, `--quiet`, `-h`),
38
+ * the link regex and its fragment/query stripping, link-resolution semantics
39
+ * (external / absolute / out-of-tree targets ignored), the allow rule
40
+ * (same pack · `core` · declared `requires`), the per-violation text and
41
+ * JSON shapes, the stdout/stderr split, and exit 0 clean / 1 violations.
42
+ *
43
+ * ## Where the `requires` graph is read from
44
+ *
45
+ * `src/config/discovery/packs.yml` is the source of truth for the pack
46
+ * vocabulary and its `requires` edges — `generate_pack_manifests.ts` DERIVES
47
+ * every `src/{packs,domains}/<pack>/pack.yaml` from it. Reading the vocabulary
48
+ * therefore covers all 33 pack ids, including the three (`frontend-design`,
49
+ * `scale-discipline`, `history-discipline`) that artefacts declare but that own
50
+ * no pack-home directory and so have no generated manifest. The manifests are
51
+ * still read, as an overlay, for any pack home the vocabulary does not list
52
+ * (today: `core`).
15
53
  */
16
54
 
17
55
  import * as fs from 'node:fs';
@@ -19,15 +57,72 @@ import * as path from 'node:path';
19
57
  import { fileURLToPath, pathToFileURL } from 'node:url';
20
58
  import { parse as parseYaml } from 'yaml';
21
59
 
22
- // ROOT = Path(__file__).resolve().parents[2] — canonical (symlinks resolved).
60
+ import {
61
+ SRC_AGENT,
62
+ SRC_DOMAINS,
63
+ SRC_RULES,
64
+ SRC_SKILLS,
65
+ iter_artefacts,
66
+ } from './_lib/agent_src.js';
67
+ import { checkRatchet } from './_lib/gate_baseline.js';
68
+ import { DeadScopeError, assertScanned } from './_lib/scan_scope.js';
69
+ import { parse_frontmatter } from './validate_frontmatter.js';
70
+
23
71
  const _HERE = path.resolve(fileURLToPath(import.meta.url));
24
- const ROOT = _realpath(path.resolve(path.dirname(_HERE), '..', '..'));
25
- const PACKAGES = path.join(ROOT, 'packages');
72
+
73
+ // Module-level paths are test seams (mirrors the `_set_paths` shape used by
74
+ // the sibling `lint_artefact_frontmatter`). Mutable lets + a setter.
75
+ let ROOT = _realpath(path.resolve(path.dirname(_HERE), '..', '..'));
76
+ let VOCAB = path.join(ROOT, 'src', 'config', 'discovery', 'packs.yml');
77
+
78
+ const _DEFAULT_ROOT = ROOT;
79
+
80
+ /**
81
+ * True while a caller has repointed the root at a fixture tree.
82
+ *
83
+ * Stateless on purpose (compared against the value captured at import) so a
84
+ * test restoring the real path also restores real-repo behaviour. Two things
85
+ * key off it: the scan roots — an injected tree is scanned EXCLUSIVELY, because
86
+ * the shared resolver still points at the real repo and would otherwise drag
87
+ * the whole corpus into a fixture run — and the violation ratchet, which
88
+ * records repo debt and must never judge a fixture.
89
+ */
90
+ function _paths_overridden(): boolean {
91
+ return ROOT !== _DEFAULT_ROOT;
92
+ }
93
+
94
+ /**
95
+ * Test seam: repoint the root (and optionally the vocabulary file).
96
+ *
97
+ * Passing the default root restores real-repo behaviour, vocabulary included.
98
+ */
99
+ function _set_paths_for_test(opts: { root?: string; vocab?: string }): void {
100
+ if (opts.root !== undefined) {
101
+ ROOT = opts.root;
102
+ VOCAB =
103
+ ROOT === _DEFAULT_ROOT
104
+ ? path.join(ROOT, 'src', 'config', 'discovery', 'packs.yml')
105
+ : path.join(ROOT, 'packs.yml');
106
+ }
107
+ if (opts.vocab !== undefined) {
108
+ VOCAB = opts.vocab;
109
+ }
110
+ }
26
111
 
27
112
  // [..](target) with an optional #fragment / ?query stripped from the target.
28
113
  const LINK_RE = /\[[^\]]*\]\(([^)#?]+)(?:[#?][^)]*)?\)/g;
29
114
 
115
+ /** A pack every install carries — a link into it can never dangle. */
116
+ const ALWAYS_INSTALLED = 'core';
117
+
118
+ type ViolationKind =
119
+ /** Link crosses into a pack the source pack does not require. */
120
+ | 'cross-pack'
121
+ /** A unit-defining artefact whose own pack could not be determined. */
122
+ | 'unresolved-pack';
123
+
30
124
  interface ViolationRecord {
125
+ kind: ViolationKind;
31
126
  source_pack: string;
32
127
  target_pack: string;
33
128
  source: string;
@@ -65,6 +160,14 @@ function _isDir(p: string): boolean {
65
160
  }
66
161
  }
67
162
 
163
+ function _isFile(p: string): boolean {
164
+ try {
165
+ return fs.statSync(p).isFile();
166
+ } catch {
167
+ return false;
168
+ }
169
+ }
170
+
68
171
  function _exists(p: string): boolean {
69
172
  try {
70
173
  fs.statSync(p);
@@ -89,29 +192,6 @@ function _load_pack_meta(pkg_dir: string): Record<string, unknown> {
89
192
  : {};
90
193
  }
91
194
 
92
- /** Sorted list of immediate child dir entries of `packages/`, dirs only. */
93
- function _sortedPackageDirs(): string[] {
94
- let entries: fs.Dirent[];
95
- try {
96
- entries = fs.readdirSync(PACKAGES, { withFileTypes: true });
97
- } catch {
98
- return [];
99
- }
100
- return entries
101
- .map((e) => path.join(PACKAGES, e.name))
102
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
103
- .filter((p) => _isDir(p));
104
- }
105
-
106
- function _packId(meta: Record<string, unknown>, pkgName: string): string {
107
- const id = meta['id'];
108
- if (typeof id === 'string' && id.length > 0) {
109
- return id;
110
- }
111
- // pkg.name.removeprefix("pack-")
112
- return pkgName.startsWith('pack-') ? pkgName.slice('pack-'.length) : pkgName;
113
- }
114
-
115
195
  /** Recursively list `*.md` files under `dir`, sorted (sorted(rglob)). */
116
196
  function _rglobMdSorted(dir: string): string[] {
117
197
  const out: string[] = [];
@@ -135,23 +215,223 @@ function _rglobMdSorted(dir: string): string[] {
135
215
  return out.sort();
136
216
  }
137
217
 
138
- /** Map repo-relative POSIX artefact path -> pack id. Insertion order matters. */
139
- function _build_artefact_index(): Map<string, string> {
140
- const index = new Map<string, string>();
141
- if (!_exists(PACKAGES)) {
142
- return index;
218
+ /**
219
+ * The scan roots, named individually rather than via one container.
220
+ *
221
+ * Deliberately NOT `artefact_roots()`: that category-append view also yields
222
+ * `src/templates`, an unrelated consumer-scaffold tree this gate never
223
+ * scanned. Repairing a root must restore the old scope, not silently widen it.
224
+ * `iter_artefacts()` (used below) walks exactly these four.
225
+ */
226
+ function _scan_roots(): string[] {
227
+ if (_paths_overridden()) {
228
+ // Fixture mode — the injected tree is the whole world.
229
+ return [
230
+ path.join(ROOT, 'skills'),
231
+ path.join(ROOT, 'rules'),
232
+ path.join(ROOT, 'commands'),
233
+ ].filter(_isDir);
143
234
  }
144
- for (const pkg of _sortedPackageDirs()) {
145
- const src_root = path.join(pkg, '.agent-src.uncondensed');
146
- if (!_isDir(src_root)) {
235
+ return [SRC_AGENT(), SRC_SKILLS(), SRC_RULES(), SRC_DOMAINS()].filter(_isDir);
236
+ }
237
+
238
+ /** Every source artefact, as absolute paths, in deterministic order. */
239
+ function _iter_source_files(): string[] {
240
+ if (_paths_overridden()) {
241
+ const out: string[] = [];
242
+ for (const root of _scan_roots()) {
243
+ out.push(..._rglobMdSorted(root));
244
+ }
245
+ return out;
246
+ }
247
+ return [...iter_artefacts()];
248
+ }
249
+
250
+ /** Pack-home directories carrying a generated `pack.yaml`. */
251
+ function _pack_home_dirs(): string[] {
252
+ const parents = _paths_overridden()
253
+ ? [path.join(ROOT, 'packs')]
254
+ : [path.join(ROOT, 'src', 'packs'), path.join(ROOT, 'src', 'domains')];
255
+ const out: string[] = [];
256
+ for (const parent of parents) {
257
+ if (!_isDir(parent)) {
147
258
  continue;
148
259
  }
149
- const pid = _packId(_load_pack_meta(pkg), path.basename(pkg));
150
- for (const p of _rglobMdSorted(src_root)) {
151
- index.set(_relPosix(p, ROOT), pid);
260
+ for (const name of fs.readdirSync(parent).sort()) {
261
+ const dir = path.join(parent, name);
262
+ if (_isDir(dir) && _exists(path.join(dir, 'pack.yaml'))) {
263
+ out.push(dir);
264
+ }
152
265
  }
153
266
  }
154
- return index;
267
+ return out;
268
+ }
269
+
270
+ /**
271
+ * `pack id -> direct requires`.
272
+ *
273
+ * `packs.yml` first (the source of truth every `pack.yaml` is generated from,
274
+ * and the only place the three home-less packs are declared), then the
275
+ * manifests as an overlay for pack homes the vocabulary does not list.
276
+ */
277
+ function _pack_requires(): Map<string, string[]> {
278
+ const out = new Map<string, string[]>();
279
+ const asList = (v: unknown): string[] => (Array.isArray(v) ? v.map(String) : []);
280
+
281
+ if (_exists(VOCAB)) {
282
+ const vocab = parseYaml(fs.readFileSync(VOCAB, 'utf-8'), { version: '1.1' });
283
+ if (Array.isArray(vocab)) {
284
+ for (const entry of vocab) {
285
+ if (entry !== null && typeof entry === 'object' && !Array.isArray(entry)) {
286
+ const e = entry as Record<string, unknown>;
287
+ if (typeof e['id'] === 'string') {
288
+ out.set(e['id'], asList(e['requires']));
289
+ }
290
+ }
291
+ }
292
+ }
293
+ }
294
+ for (const dir of _pack_home_dirs()) {
295
+ const meta = _load_pack_meta(dir);
296
+ const id = typeof meta['id'] === 'string' ? meta['id'] : path.basename(dir);
297
+ if (!out.has(id)) {
298
+ out.set(id, asList(meta['requires']));
299
+ }
300
+ }
301
+ return out;
302
+ }
303
+
304
+ /** Transitive expansion of `requires`, cycle-safe. */
305
+ function _requires_closure(pack: string, direct: Map<string, string[]>): Set<string> {
306
+ const seen = new Set<string>();
307
+ const stack = [...(direct.get(pack) ?? [])];
308
+ while (stack.length > 0) {
309
+ const next = stack.pop() as string;
310
+ if (seen.has(next)) {
311
+ continue;
312
+ }
313
+ seen.add(next);
314
+ for (const dep of direct.get(next) ?? []) {
315
+ stack.push(dep);
316
+ }
317
+ }
318
+ return seen;
319
+ }
320
+
321
+ /** Packs declared in an artefact's own frontmatter (`packs:`). */
322
+ function _declared_packs(p: string): string[] {
323
+ let text: string;
324
+ try {
325
+ text = fs.readFileSync(p, 'utf-8');
326
+ } catch {
327
+ return [];
328
+ }
329
+ const [fm] = parse_frontmatter(text);
330
+ if (fm === null) {
331
+ return [];
332
+ }
333
+ const packs = fm['packs'];
334
+ if (Array.isArray(packs)) {
335
+ return packs.map(String).filter((s) => s !== '');
336
+ }
337
+ return typeof packs === 'string' && packs !== '' ? [packs] : [];
338
+ }
339
+
340
+ /**
341
+ * A unit-defining artefact — one ADR-013 requires to declare `packs:`.
342
+ *
343
+ * These are the files whose pack MUST be resolvable; the fail-safe below turns
344
+ * an unresolvable one into a violation rather than a silent exclusion.
345
+ */
346
+ function _is_unit_file(abs: string): boolean {
347
+ const base = path.basename(abs);
348
+ if (base === 'SKILL.md') {
349
+ return true;
350
+ }
351
+ // `command.md` only counts inside a command home. The same basename is
352
+ // also used by the authoring SCAFFOLDS under `src/agent-src/templates/`,
353
+ // which carry no frontmatter on purpose (quarantined in
354
+ // `src/config/discovery/unassigned-artefacts.yml`) and are not commands.
355
+ const commandRoot = _paths_overridden() ? path.join(ROOT, 'commands') : SRC_DOMAINS();
356
+ if (base === 'command.md') {
357
+ return !_relPosix(abs, commandRoot).startsWith('..');
358
+ }
359
+ const rulesRoot = _paths_overridden() ? path.join(ROOT, 'rules') : SRC_RULES();
360
+ return path.dirname(abs) === rulesRoot && base.endsWith('.md');
361
+ }
362
+
363
+ /**
364
+ * Resolve an artefact's pack set. Returns `[]` when it cannot be determined.
365
+ *
366
+ * The rule, in order (the `packages/<pack>/…` container the original gate read
367
+ * no longer exists, so attribution is declaration-first):
368
+ *
369
+ * 1. the artefact's own `packs:` frontmatter;
370
+ * 2. else the nearest ancestor `SKILL.md`'s packs — a skill's auxiliary
371
+ * reference files carry no frontmatter and ship with their skill;
372
+ * 3. else, under `src/domains/<pack>/`, the pack home directory it lives in;
373
+ * 4. else UNASSIGNED — contexts, personas, templates and other cross-cutting
374
+ * surfaces that legitimately belong to no pack (registry:
375
+ * `src/config/discovery/unassigned-artefacts.yml`).
376
+ *
377
+ * Fail-safe: an UNASSIGNED artefact is not indexed, so it is never a source and
378
+ * never launders a link as a target — and the count of them is printed in the
379
+ * summary, so the exclusion is visible rather than silent. For the classes that
380
+ * MUST declare a pack (`_is_unit_file`) an unassigned result is reported as an
381
+ * `unresolved-pack` violation: such an artefact cannot be boundary-checked and
382
+ * must not pass by omission. (`lint_artefact_frontmatter` enforces the same
383
+ * `packs:` presence independently, so this is a second lock, not the only one.)
384
+ */
385
+ function _packs_of(abs: string, cache: Map<string, string[]>): string[] {
386
+ const cached = cache.get(abs);
387
+ if (cached !== undefined) {
388
+ return cached;
389
+ }
390
+ let packs = _declared_packs(abs);
391
+
392
+ if (packs.length === 0) {
393
+ // Nearest ancestor SKILL.md.
394
+ let dir = path.dirname(abs);
395
+ const stopAt = path.parse(dir).root;
396
+ while (dir !== stopAt && dir.startsWith(ROOT)) {
397
+ const owner = path.join(dir, 'SKILL.md');
398
+ if (owner !== abs && _isFile(owner)) {
399
+ packs = _declared_packs(owner);
400
+ break;
401
+ }
402
+ dir = path.dirname(dir);
403
+ }
404
+ }
405
+ if (packs.length === 0 && !_paths_overridden()) {
406
+ const rel = _relPosix(abs, SRC_DOMAINS());
407
+ if (!rel.startsWith('..') && rel.includes('/')) {
408
+ packs = [rel.split('/')[0] as string];
409
+ }
410
+ }
411
+ cache.set(abs, packs);
412
+ return packs;
413
+ }
414
+
415
+ /** Map repo-relative POSIX artefact path -> declared pack ids. */
416
+ function _build_artefact_index(): {
417
+ index: Map<string, string[]>;
418
+ unassigned: string[];
419
+ scanned: number;
420
+ } {
421
+ const index = new Map<string, string[]>();
422
+ const unassigned: string[] = [];
423
+ const cache = new Map<string, string[]>();
424
+ const files = _iter_source_files();
425
+ for (const abs of files) {
426
+ const packs = _packs_of(abs, cache);
427
+ const rel = _relPosix(abs, ROOT);
428
+ if (packs.length === 0) {
429
+ unassigned.push(rel);
430
+ continue;
431
+ }
432
+ index.set(rel, packs);
433
+ }
434
+ return { index, unassigned, scanned: files.length };
155
435
  }
156
436
 
157
437
  /** Resolve a markdown link target to a repo-relative path, or null. */
@@ -194,7 +474,7 @@ function _scan_file(p: string): string[] {
194
474
  LINK_RE.lastIndex = 0;
195
475
  let m: RegExpExecArray | null;
196
476
  while ((m = LINK_RE.exec(text)) !== null) {
197
- out.push(m[1]!);
477
+ out.push(m[1] as string);
198
478
  }
199
479
  return out;
200
480
  }
@@ -203,18 +483,37 @@ function _is_allowed(source_pack: string, target_pack: string, requires: string[
203
483
  if (source_pack === target_pack) {
204
484
  return true;
205
485
  }
206
- if (target_pack === 'core') {
486
+ if (target_pack === ALWAYS_INSTALLED) {
207
487
  return true;
208
488
  }
209
489
  return (requires || []).includes(target_pack);
210
490
  }
211
491
 
492
+ /**
493
+ * Set-level allow rule.
494
+ *
495
+ * EVERY source pack must reach SOME target pack: a multi-pack artefact ships
496
+ * in each of its packs independently, so a link that resolves in only one of
497
+ * them is dead in the others. A multi-pack TARGET is present as soon as any one
498
+ * of its packs is reachable.
499
+ */
500
+ function _link_allowed(
501
+ source_packs: readonly string[],
502
+ target_packs: readonly string[],
503
+ closureOf: (pack: string) => Set<string>,
504
+ ): boolean {
505
+ return source_packs.every((s) => {
506
+ const reach = [...closureOf(s)];
507
+ return target_packs.some((t) => _is_allowed(s, t, reach));
508
+ });
509
+ }
510
+
212
511
  /** Mirror Python `json.dump(obj, indent=2)` with `ensure_ascii=True`. */
213
512
  function _json_dumps_ascii(obj: unknown): string {
214
513
  const raw = JSON.stringify(obj, null, 2);
215
514
  let out = '';
216
515
  for (const ch of raw) {
217
- const code = ch.codePointAt(0)!;
516
+ const code = ch.codePointAt(0) as number;
218
517
  if (code < 0x80) {
219
518
  out += ch;
220
519
  } else {
@@ -235,7 +534,7 @@ function parse_args(argv: readonly string[]): ParsedArgs {
235
534
  let format: 'text' | 'json' = 'text';
236
535
  let quiet = false;
237
536
  for (let i = 0; i < argv.length; i++) {
238
- const arg = argv[i]!;
537
+ const arg = argv[i] as string;
239
538
  if (arg === '--format') {
240
539
  const v = argv[++i];
241
540
  if (v === undefined) {
@@ -274,41 +573,75 @@ function _argparse_error(message: string): never {
274
573
  process.exit(2);
275
574
  }
276
575
 
277
- function main(): number {
278
- const args = parse_args(process.argv.slice(2));
576
+ function main(argv?: readonly string[]): number {
577
+ const args = parse_args(argv ?? process.argv.slice(2));
279
578
 
280
- const artefact_pack = _build_artefact_index();
281
- if (artefact_pack.size === 0) {
282
- process.stderr.write('no packages/ tree to lint — skipping\n');
283
- return 0;
284
- }
579
+ const { index: artefact_pack, unassigned, scanned } = _build_artefact_index();
285
580
 
286
- const pack_requires = new Map<string, string[]>();
287
- for (const pkg of _sortedPackageDirs()) {
288
- const meta = _load_pack_meta(pkg);
289
- const pid = _packId(meta, path.basename(pkg));
290
- const req = meta['requires'];
291
- pack_requires.set(pid, Array.isArray(req) ? (req as unknown[]).map(String) : []);
581
+ // Scope assertion: 0 artefacts means the root moved, not that the tree is
582
+ // clean. That was this gate's shipped state until 2026-08-02 — it walked
583
+ // the deleted `packages/` tree and skipped green forever.
584
+ try {
585
+ assertScanned({
586
+ gate: 'lint_pack_boundaries',
587
+ scanned,
588
+ units: 'artefact(s)',
589
+ roots: _scan_roots().map((r) => _relPosix(r, ROOT) || '.'),
590
+ });
591
+ } catch (exc) {
592
+ if (!(exc instanceof DeadScopeError)) {
593
+ throw exc;
594
+ }
595
+ process.stderr.write(`❌ ${exc.message}\n`);
596
+ return 2;
292
597
  }
293
598
 
599
+ const pack_requires = _pack_requires();
600
+ const closureCache = new Map<string, Set<string>>();
601
+ const closureOf = (pack: string): Set<string> => {
602
+ let c = closureCache.get(pack);
603
+ if (c === undefined) {
604
+ c = _requires_closure(pack, pack_requires);
605
+ closureCache.set(pack, c);
606
+ }
607
+ return c;
608
+ };
609
+
294
610
  const violations: ViolationRecord[] = [];
295
- for (const [rel_path, src_pack] of artefact_pack) {
611
+
612
+ // Fail-safe: a unit-defining artefact with no resolvable pack cannot be
613
+ // boundary-checked, so it is a finding rather than a silent exclusion.
614
+ for (const rel of unassigned) {
615
+ if (_is_unit_file(path.join(ROOT, rel))) {
616
+ violations.push({
617
+ kind: 'unresolved-pack',
618
+ source_pack: '(unresolved)',
619
+ target_pack: '',
620
+ source: rel,
621
+ target: '',
622
+ link: '',
623
+ });
624
+ }
625
+ }
626
+
627
+ for (const [rel_path, src_packs] of artefact_pack) {
296
628
  const source_file = path.join(ROOT, rel_path);
297
629
  for (const raw of _scan_file(source_file)) {
298
630
  const target_rel = _resolve_link(source_file, raw);
299
631
  if (target_rel === null) {
300
632
  continue;
301
633
  }
302
- const target_pack = artefact_pack.get(target_rel);
303
- if (target_pack === undefined) {
304
- continue; // link to docs/, scripts/, root files — not pack-scoped
634
+ const target_packs = artefact_pack.get(target_rel);
635
+ if (target_packs === undefined) {
636
+ continue; // docs/, scripts/, root files, unassigned — not pack-scoped
305
637
  }
306
- if (_is_allowed(src_pack, target_pack, pack_requires.get(src_pack) ?? [])) {
638
+ if (_link_allowed(src_packs, target_packs, closureOf)) {
307
639
  continue;
308
640
  }
309
641
  violations.push({
310
- source_pack: src_pack,
311
- target_pack,
642
+ kind: 'cross-pack',
643
+ source_pack: src_packs.join('+'),
644
+ target_pack: target_packs.join('+'),
312
645
  source: rel_path,
313
646
  target: target_rel,
314
647
  link: raw,
@@ -316,33 +649,64 @@ function main(): number {
316
649
  }
317
650
  }
318
651
 
652
+ const verdict = _paths_overridden()
653
+ ? null
654
+ : checkRatchet({
655
+ gate: 'lint_pack_boundaries',
656
+ actual: violations.length,
657
+ repoRoot: ROOT,
658
+ });
659
+ const ok = violations.length === 0 || (verdict !== null && verdict.ok);
660
+
319
661
  if (args.format === 'json') {
320
662
  process.stdout.write(
321
- _json_dumps_ascii({ violations, count: violations.length }) + '\n',
663
+ _json_dumps_ascii({
664
+ violations,
665
+ count: violations.length,
666
+ scanned,
667
+ unassigned: unassigned.length,
668
+ ratchet:
669
+ verdict === null ? null : { status: verdict.status, baseline: verdict.baseline },
670
+ }) + '\n',
322
671
  );
323
- } else {
324
- if (!args.quiet) {
325
- process.stdout.write(
326
- `lint_pack_boundaries: scanned ${artefact_pack.size} artefacts across ` +
327
- `${pack_requires.size} packs\n`,
328
- );
329
- }
330
- for (const v of violations) {
672
+ return ok ? 0 : 1;
673
+ }
674
+
675
+ if (!args.quiet) {
676
+ process.stdout.write(
677
+ `lint_pack_boundaries: scanned ${scanned} artefacts across ` +
678
+ `${pack_requires.size} packs (${unassigned.length} outside pack scope)\n`,
679
+ );
680
+ }
681
+ for (const v of violations) {
682
+ if (v.kind === 'unresolved-pack') {
331
683
  process.stdout.write(
332
- ` ✗ ${v.source_pack} -> ${v.target_pack} : ${v.source} → ${v.target} ` +
333
- `(link: ${v.link})\n`,
684
+ ` ✗ ${v.source} : no \`packs:\` declared and no owning pack — ` +
685
+ 'cannot be boundary-checked\n',
334
686
  );
687
+ continue;
335
688
  }
336
- if (violations.length > 0) {
337
- process.stdout.write(
338
- `\n${violations.length} cross-pack violation(s) — declare 'requires' in ` +
339
- 'pack.yaml or move the artefact\n',
340
- );
341
- } else if (!args.quiet) {
342
- process.stdout.write('OK — no cross-pack drift\n');
689
+ process.stdout.write(
690
+ ` ✗ ${v.source_pack} -> ${v.target_pack} : ${v.source} → ${v.target} ` +
691
+ `(link: ${v.link})\n`,
692
+ );
693
+ }
694
+ if (violations.length > 0) {
695
+ process.stdout.write(
696
+ `\n${violations.length} cross-pack violation(s) — declare 'requires' in ` +
697
+ 'pack.yaml or move the artefact\n',
698
+ );
699
+ if (verdict !== null) {
700
+ if (verdict.ok) {
701
+ process.stdout.write(`⚠️ ${verdict.message}\n`);
702
+ } else {
703
+ process.stderr.write(`❌ ${verdict.message}\n`);
704
+ }
343
705
  }
706
+ } else if (!args.quiet) {
707
+ process.stdout.write('OK — no cross-pack drift\n');
344
708
  }
345
- return violations.length > 0 ? 1 : 0;
709
+ return ok ? 0 : 1;
346
710
  }
347
711
 
348
712
  function _isCliEntry(): boolean {
@@ -372,14 +736,20 @@ if (_isCliEntry() || process.argv[1] === _HERE) {
372
736
  }
373
737
 
374
738
  export {
739
+ type ViolationKind,
375
740
  type ViolationRecord,
376
741
  ROOT,
377
- PACKAGES,
378
742
  LINK_RE,
379
743
  _build_artefact_index,
380
744
  _resolve_link,
381
745
  _scan_file,
382
746
  _is_allowed,
747
+ _link_allowed,
383
748
  _load_pack_meta,
749
+ _pack_requires,
750
+ _requires_closure,
751
+ _packs_of,
752
+ _scan_roots,
753
+ _set_paths_for_test,
384
754
  main,
385
755
  };