@event4u/agent-config 9.25.0 → 9.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +58 -143
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/conformance.md +21 -2
- package/dist/agent-src/commands/review/changes.md +6 -5
- package/dist/agent-src/commands/roadmap/next.md +256 -0
- package/dist/agent-src/commands/roadmap.md +12 -4
- package/dist/agent-src/contexts/execution/subagent-routing.md +4 -1
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/analysis-skill-routing.md +2 -0
- package/dist/agent-src/rules/architecture.md +2 -0
- package/dist/agent-src/rules/artifact-drafting-protocol.md +2 -0
- package/dist/agent-src/rules/artifact-engagement-recording.md +2 -0
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- package/dist/agent-src/rules/autonomous-execution.md +2 -0
- package/dist/agent-src/rules/brand-consistency.md +2 -0
- package/dist/agent-src/rules/brand-source-of-truth.md +2 -0
- package/dist/agent-src/rules/broken-access-control.md +2 -0
- package/dist/agent-src/rules/cli-output-handling.md +2 -0
- package/dist/agent-src/rules/code-comment-discipline.md +2 -0
- package/dist/agent-src/rules/code-provenance.md +2 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +2 -0
- package/dist/agent-src/rules/commit-conventions.md +2 -0
- package/dist/agent-src/rules/communication-through-line.md +2 -0
- package/dist/agent-src/rules/content-quoting-floor.md +2 -0
- package/dist/agent-src/rules/context-hygiene.md +10 -0
- package/dist/agent-src/rules/copilot-routing.md +2 -0
- package/dist/agent-src/rules/cross-source-consistency.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -0
- package/dist/agent-src/rules/delegation-policy.md +5 -2
- package/dist/agent-src/rules/design-fidelity.md +19 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +120 -0
- package/dist/agent-src/rules/devcontainer-routing.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
- package/dist/agent-src/rules/docker-commands.md +2 -0
- package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +2 -0
- package/dist/agent-src/rules/domain-safety-pii.md +2 -0
- package/dist/agent-src/rules/domain-safety-retention.md +2 -0
- package/dist/agent-src/rules/downstream-changes.md +2 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/evaluator-independence.md +19 -3
- package/dist/agent-src/rules/external-code-graph-interop.md +2 -0
- package/dist/agent-src/rules/external-reference-deep-dive.md +2 -0
- package/dist/agent-src/rules/fast-path-marker-visibility.md +2 -0
- package/dist/agent-src/rules/finance-safety-floor.md +2 -0
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +2 -0
- package/dist/agent-src/rules/git-history-discipline.md +3 -1
- package/dist/agent-src/rules/guidelines.md +2 -0
- package/dist/agent-src/rules/history-discipline.md +2 -0
- package/dist/agent-src/rules/icon-consistency.md +2 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +2 -0
- package/dist/agent-src/rules/improve-before-implement.md +2 -0
- package/dist/agent-src/rules/invite-challenge.md +2 -0
- package/dist/agent-src/rules/laravel-routing.md +2 -0
- package/dist/agent-src/rules/laravel-translations.md +2 -0
- package/dist/agent-src/rules/legal-safety-floor.md +2 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +2 -0
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +2 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +2 -0
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -0
- package/dist/agent-src/rules/media-governance-routing.md +2 -0
- package/dist/agent-src/rules/media-sync-ground-truth.md +2 -0
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
- package/dist/agent-src/rules/missing-tool-handling.md +2 -0
- package/dist/agent-src/rules/model-recommendation.md +2 -0
- package/dist/agent-src/rules/no-attribution-footers.md +2 -0
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +2 -0
- package/dist/agent-src/rules/no-pr-progress-comments.md +2 -0
- package/dist/agent-src/rules/no-roadmap-references.md +2 -0
- package/dist/agent-src/rules/notes-first-reasoning.md +2 -0
- package/dist/agent-src/rules/onboarding-gate.md +2 -0
- package/dist/agent-src/rules/output-discipline.md +2 -0
- package/dist/agent-src/rules/package-ci-checks.md +2 -0
- package/dist/agent-src/rules/persona-governance.md +2 -0
- package/dist/agent-src/rules/php-coding.md +2 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +2 -0
- package/dist/agent-src/rules/preservation-guard.md +2 -0
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -0
- package/dist/agent-src/rules/question-not-instruction.md +2 -0
- package/dist/agent-src/rules/reviewer-awareness.md +2 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +2 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
- package/dist/agent-src/rules/role-mode-adherence.md +2 -0
- package/dist/agent-src/rules/rule-type-governance.md +2 -0
- package/dist/agent-src/rules/runtime-safety.md +2 -0
- package/dist/agent-src/rules/scale-discipline.md +2 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
- package/dist/agent-src/rules/senior-engineering-discipline.md +2 -0
- package/dist/agent-src/rules/session-canary.md +63 -19
- package/dist/agent-src/rules/settings-ask-protocol.md +180 -0
- package/dist/agent-src/rules/size-enforcement.md +2 -0
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -0
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/slash-command-routing-policy.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +2 -0
- package/dist/agent-src/rules/source-discovery-gate.md +2 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +2 -0
- package/dist/agent-src/rules/symfony-routing.md +2 -0
- package/dist/agent-src/rules/think-before-action.md +2 -0
- package/dist/agent-src/rules/token-budget-discipline.md +8 -3
- package/dist/agent-src/rules/token-efficiency.md +2 -0
- package/dist/agent-src/rules/token-optimizer-maintenance.md +2 -0
- package/dist/agent-src/rules/tool-safety.md +2 -0
- package/dist/agent-src/rules/ui-audit-gate.md +7 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -0
- package/dist/agent-src/rules/upstream-proposal.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +5 -2
- package/dist/agent-src/rules/user-interrupt-priority.md +2 -0
- package/dist/agent-src/skills/recursive-verification/SKILL.md +13 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-SJQMJI7M.js → chunk-3KJIMFTB.js} +1 -1
- package/dist/cli-delegate/{chunk-BSLUHV2F.js → chunk-BCPIOAGV.js} +148 -133
- package/dist/cli-delegate/cmd_conformance.js +1 -1
- package/dist/cli-delegate/cmd_doctor.js +1 -1
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +4 -1
- package/dist/cli-delegate/cmd_route_explain.js +4 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +191 -120
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +11 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +9 -6
- package/dist/hooks/dispatch.js +1148 -349
- package/dist/install/install.mjs +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +571 -417
- package/dist/router.json +1 -1
- package/dist/scripts/condense.js +33 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/io/yamlIO.js +85 -0
- package/dist/server/io/yamlIO.js.map +1 -1
- package/dist/server/nicknameResolver.js +116 -0
- package/dist/server/nicknameResolver.js.map +1 -0
- package/dist/server/routes/ping.js +29 -11
- package/dist/server/routes/ping.js.map +1 -1
- package/dist/server/routes/settings.js +1 -12
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/wizard.js +52 -2
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/shared/interactiveContext.js +73 -0
- package/dist/shared/interactiveContext.js.map +1 -0
- package/dist/shared/nicknamePrefill.js +59 -0
- package/dist/shared/nicknamePrefill.js.map +1 -0
- package/dist/shared/settingsAsks.js +128 -0
- package/dist/shared/settingsAsks.js.map +1 -0
- package/dist/shared/settingsCarveOut.js +118 -0
- package/dist/shared/settingsCarveOut.js.map +1 -0
- package/dist/shared/settingsConsent.js +93 -0
- package/dist/shared/settingsConsent.js.map +1 -0
- package/dist/shared/settingsSurface.js +7 -1
- package/dist/shared/settingsSurface.js.map +1 -1
- package/dist/ui/assets/index-DmR0mbk4.js.map +1 -1
- package/package.json +1 -1
- package/src/config/agents-paths.yml +15 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +29 -1
- package/src/config/gate-violation-baselines.json +13 -7
- package/src/scripts/_cli/cmd_doctor.ts +6 -21
- package/src/scripts/_cli/cmd_route_audit.ts +4 -1
- package/src/scripts/_cli/cmd_route_explain.ts +9 -1
- package/src/scripts/_dispatch.bash +18 -0
- package/src/scripts/_lib/git_common_dir.ts +128 -0
- package/src/scripts/_lib/obligation_frequency.ts +391 -0
- package/src/scripts/_lib/session_register.ts +361 -0
- package/src/scripts/ai-video/stitch.sh +27 -9
- package/src/scripts/before_complete_hook.ts +23 -4
- package/src/scripts/bench_ab_v2_run.ts +272 -16
- package/src/scripts/bench_ab_v2_stats.ts +156 -3
- package/src/scripts/check_completion_review.ts +80 -3
- package/src/scripts/check_corpus_staleness.ts +692 -0
- package/src/scripts/check_enforcement_coverage.ts +192 -7
- package/src/scripts/check_gate_coverage.ts +67 -0
- package/src/scripts/check_hook_bundle_freshness.ts +183 -0
- package/src/scripts/check_rule_projection_integrity.ts +364 -0
- package/src/scripts/condense.ts +36 -2
- package/src/scripts/conformance_scan.ts +82 -17
- package/src/scripts/dispatch_r2_reviewer.ts +31 -2
- package/src/scripts/generate_settings_reference.ts +232 -0
- package/src/scripts/git_authorization_hook.ts +75 -10
- package/src/scripts/hook_manifest.yaml +87 -27
- package/src/scripts/hooks/block_no_verify.ts +59 -2
- package/src/scripts/hooks/block_unauthorized_git.ts +199 -16
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/design_slop_hook.ts +13 -1
- package/src/scripts/hooks/dispatch_hook.ts +97 -2
- package/src/scripts/hooks/evidence_independence.ts +40 -6
- package/src/scripts/language_mirror_hook.ts +256 -17
- package/src/scripts/lint_abstraction_thresholds.ts +41 -8
- package/src/scripts/lint_agents_layout.ts +2 -0
- package/src/scripts/lint_hook_manifest.ts +29 -0
- package/src/scripts/memory_learn_hook.ts +109 -6
- package/src/scripts/orchestration_backfill.ts +354 -0
- package/src/scripts/pr_url_reminder_hook.ts +17 -2
- package/src/scripts/release.ts +180 -37
- package/src/scripts/schemas/review-findings.schema.json +99 -0
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/session_canary_hook.ts +35 -3
- package/src/scripts/session_register_hook.ts +288 -0
- package/src/scripts/sessions_cli.ts +140 -0
- package/src/scripts/validate_frontmatter.ts +68 -0
- package/src/server/io/yamlIO.ts +87 -0
- package/src/shared/interactiveContext.ts +98 -0
- package/src/shared/nicknamePrefill.ts +96 -0
- package/src/shared/settingsAsks.ts +176 -0
- package/src/shared/settingsCarveOut.ts +143 -0
- package/src/shared/settingsConsent.ts +136 -0
- package/src/shared/settingsSurface.ts +7 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
3
|
"mcpName": "io.github.event4u-app/agent-config",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.27.0",
|
|
5
5
|
"description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including \"zero runtime daemon\".",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"private": false,
|
|
@@ -114,6 +114,21 @@
|
|
|
114
114
|
writer: /team-knowledge:bootstrap skill
|
|
115
115
|
rationale: Deterministic template pages; review-then-commit flow (nothing here is the artifact)
|
|
116
116
|
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# Self-improvement proposals (TRACKED — listed for classification, not ignored)
|
|
119
|
+
# ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
- path: /agents/proposals/
|
|
122
|
+
scope: both
|
|
123
|
+
policy: tracked
|
|
124
|
+
writer: learning-to-rule-or-skill skill (drafts) → upstream-contribute (PR)
|
|
125
|
+
rationale: |
|
|
126
|
+
Proposal drafts must be committed — the proposal-drift workflow reads their
|
|
127
|
+
stage: frontmatter in CI, and upstream-contribute opens a PR from them. Listed
|
|
128
|
+
here because agents-layout.md requires every new top-level agents/ entry to
|
|
129
|
+
appear in this manifest; the entry is inert for the gitignore gate, which reads
|
|
130
|
+
policy: ignored only.
|
|
131
|
+
|
|
117
132
|
# ---------------------------------------------------------------------------
|
|
118
133
|
# Ghostwriter profiles
|
|
119
134
|
# ---------------------------------------------------------------------------
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"deterministic": false
|
|
59
59
|
},
|
|
60
60
|
"cli_help_command_count": {
|
|
61
|
-
"max":
|
|
62
|
-
"last_measured":
|
|
63
|
-
"last_measured_at": "2026-08-
|
|
61
|
+
"max": 88,
|
|
62
|
+
"last_measured": 88,
|
|
63
|
+
"last_measured_at": "2026-08-07",
|
|
64
64
|
"method": "registry enumeration — count of `{ name: '...', disposition` entries in src/cli/registry.ts (NOT --help prose parsing; methods historically disagreed 74 vs 76 vs 79)",
|
|
65
|
-
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86."
|
|
65
|
+
"baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88."
|
|
66
66
|
},
|
|
67
67
|
"mcp_public_tool_count": {
|
|
68
68
|
"max": 19,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
# ----------------------------------------------------------
|
|
45
45
|
# 240 `lint_*` / `check_*` / `audit_*` scripts live under `src/scripts/`
|
|
46
46
|
# (the count is computed, not asserted — `check_gate_coverage.count_gate_scripts`).
|
|
47
|
-
# **
|
|
47
|
+
# **32 of them emit the machine-readable `scanned: <N>` line under their
|
|
48
48
|
# CI-identical argv, and all 31 are listed below.** The manifest is therefore
|
|
49
49
|
# complete with respect to its own contract, and covers ~13 % of the population.
|
|
50
50
|
#
|
|
@@ -599,3 +599,31 @@ gates:
|
|
|
599
599
|
check_kernel_prefix_stability). The canary is what distinguishes that from
|
|
600
600
|
a gate scanning nothing — it plants the removal-permitting class with no
|
|
601
601
|
evidence and the gate reds.
|
|
602
|
+
|
|
603
|
+
- id: check_corpus_staleness
|
|
604
|
+
argv: ["--quiet", "--today", "2026-08-06"]
|
|
605
|
+
min_scanned: 5
|
|
606
|
+
corpus: "src/skills/*/data/manifest.json — grounding-corpus manifests (6 at baseline; brand, database, accessibility-auditor, api-design, design-intelligence, threat-modeling)"
|
|
607
|
+
status: enforced
|
|
608
|
+
canary:
|
|
609
|
+
class: missing-declared-csv
|
|
610
|
+
path: src/skills/zz-canary-corpus/data/manifest.json
|
|
611
|
+
content: |
|
|
612
|
+
{
|
|
613
|
+
"manifest_version": 1,
|
|
614
|
+
"refresh_cadence": "quarterly",
|
|
615
|
+
"upstream": { "last_checked": "2026-07-01" },
|
|
616
|
+
"domains": { "d": { "file": "nope.csv", "search_cols": ["a"], "output_cols": ["b"] } }
|
|
617
|
+
}
|
|
618
|
+
note: >
|
|
619
|
+
`--today` is PINNED in argv on purpose, and it is the whole reason this
|
|
620
|
+
gate is testable at all: the five upstream-vendored corpora share
|
|
621
|
+
`last_checked: 2026-06-07`, so an unpinned reference date makes this row
|
|
622
|
+
flip from green to red on 2026-09-15 with no diff behind it. The pinned
|
|
623
|
+
date keeps the coverage guard measuring COVERAGE; the real calendar check
|
|
624
|
+
is the workflow step, which runs unpinned and is meant to red when the
|
|
625
|
+
cadence is actually missed. Changing the pin is how you re-baseline after a
|
|
626
|
+
re-vendor, and it should be visible in a diff.
|
|
627
|
+
The canary plants a manifest whose declared CSV does not exist — the exact
|
|
628
|
+
gap `corpus-grounding/scripts/schema_validator.ts` leaves open, since it
|
|
629
|
+
computes the path and never opens the file.
|
|
@@ -1,36 +1,42 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Violation ratchet for gates whose dead scan root was repaired. A repair REVEALS pre-existing debt; it does not create it. Each entry records the count revealed at repair time
|
|
2
|
+
"$comment": "Violation ratchet for gates whose dead scan root was repaired. A repair REVEALS pre-existing debt; it does not create it. Each entry records the count revealed at repair time — the gate fails only when its count RISES. Lowering a count is a normal commit; raising one is a defect. Entries expire: a baseline that has not dropped within 56 days of `landed` (or of `reaffirmed.date`) fails its gate, because a number that never moves is suppression with extra steps. Mechanism + rationale: src/scripts/_lib/gate_baseline.ts. Decision: AI council 2026-08-02, roadmap road-to-gates-that-can-fail blocker `dead-gate-finding-triage`.",
|
|
3
3
|
"gates": {
|
|
4
4
|
"check_no_new_legacy_path:hardcoded-scan-roots": {
|
|
5
5
|
"count": 49,
|
|
6
6
|
"landed": "2026-08-04",
|
|
7
|
-
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)`
|
|
7
|
+
"note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` — a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts → 147 string-literal lines → 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant — gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 — a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56→51 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51→49 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver — two gates that had been reading the retired container and scoring 0 of 288 skills."
|
|
8
8
|
},
|
|
9
9
|
"audit_user_type_axis": {
|
|
10
10
|
"count": 1,
|
|
11
11
|
"landed": "2026-08-02",
|
|
12
|
-
"note": "One orphan user-type value: `legal`. Five legal-review-prep skills (contract-review, dpa-review, nda-triage, legal-intake-triage, legal-practice-profile) declare `recommended_for_user_types: [legal]`, but there is no `user-types/legal.yml`
|
|
12
|
+
"note": "One orphan user-type value: `legal`. Five legal-review-prep skills (contract-review, dpa-review, nda-triage, legal-intake-triage, legal-practice-profile) declare `recommended_for_user_types: [legal]`, but there is no `user-types/legal.yml` — the pack shipped an axis value with no user-type definition behind it, and the dead scan root hid it (the audit reported used=0 orphans=0 while reading zero skills; it now reads 288 and reports used=8). Clearing this entry is a product call, not a copy edit: either author `user-types/legal.yml` (tagline, recommended packs, install-path hint) or drop `legal` from those five skills. Not decided here because both options change shipped pack behaviour."
|
|
13
13
|
},
|
|
14
14
|
"lint_handoffs": {
|
|
15
15
|
"count": 18,
|
|
16
16
|
"landed": "2026-08-02",
|
|
17
|
-
"note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset')
|
|
17
|
+
"note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset') — e.g. build-buy-partner → adr-create, customer-research → po-discovery, gated-reach → threat-modeling. This is a tier-metadata backfill backlog on the LINKED-TO skills, not a broken link. The one genuinely dangling link revealed by the same repair (competitive-positioning → a non-existent ../analyze-reference-repo/SKILL.md; it is a command, not a skill) was FIXED in the repairing commit rather than baselined. Clearing this entry means backfilling `tier` on the linked-to skills, or deciding that `tier: unset` on a link target is not a violation and narrowing the rule."
|
|
18
18
|
},
|
|
19
19
|
"lint_pack_boundaries": {
|
|
20
20
|
"count": 337,
|
|
21
21
|
"landed": "2026-08-02",
|
|
22
|
-
"note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach
|
|
22
|
+
"note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach — revealed when the scan root moved off the deleted packages/ tree to the live corpus (0 -> 753 artefacts scanned). 82 distinct pack pairs across 131 source files; largest single class is engineering-base -> meta (73), skills in a consumer-installable pack citing this package's own maintenance skills. Each is a link that dangles for a consumer who installs the source pack without the target's. Judged real drift rather than an over-strict gate because it is long-tailed — top bucket 22%, no single systematic cause — unlike the lint_artefact_frontmatter case, where one required shape had 0-of-288 adoption. Fix per finding: add the edge to packs.yml requires, retarget the link, or move the artefact."
|
|
23
23
|
},
|
|
24
24
|
"check_gate_completeness": {
|
|
25
25
|
"count": 217,
|
|
26
26
|
"landed": "2026-08-05",
|
|
27
|
-
"note": "Ledger adoption ratchet. 217 of 221 CI-registered gates do not yet carry per-target completeness accounting (`_lib/gate_ledger.ts`) or a `// ledger-exempt:` marker. This is deliberately NOT a sweep: road-to-skill-ecosystem-gate-integrity Phase 1 adopts exactly three gates (lint_framework_leakage, check_references, lint_roadmap_complexity) plus the checker itself to prove the interface, and the remainder migrates as gates are touched. Shrink-only from here
|
|
27
|
+
"note": "Ledger adoption ratchet. 217 of 221 CI-registered gates do not yet carry per-target completeness accounting (`_lib/gate_ledger.ts`) or a `// ledger-exempt:` marker. This is deliberately NOT a sweep: road-to-skill-ecosystem-gate-integrity Phase 1 adopts exactly three gates (lint_framework_leakage, check_references, lint_roadmap_complexity) plus the checker itself to prove the interface, and the remainder migrates as gates are touched. Shrink-only from here — the number may not grow, so a NEW gate must adopt or exempt.",
|
|
28
28
|
"falsifier": "./scripts-run src/scripts/check_gate_completeness"
|
|
29
29
|
},
|
|
30
30
|
"check_depth_budget": {
|
|
31
31
|
"count": 4,
|
|
32
32
|
"landed": "2026-08-06",
|
|
33
|
-
"note": "Four depth files exceed the 16,000-char per-file ceiling: rule-body-migration-inventory.md (23,782), design-antipatterns.md (20,707), roadmap-process-loop.md (20,360), orchestration-telemetry.md (16,155). Recorded rather than fixed because splitting four large reference documents is unrelated to the change that introduced the ceiling, and a gate that lands as four instant blockers is the shape this repository has already recorded as a failure. Shrink-only from here: a FIFTH over-ceiling file reds. roadmap-process-loop.md is the file that motivated the gate
|
|
33
|
+
"note": "Four depth files exceed the 16,000-char per-file ceiling: rule-body-migration-inventory.md (23,782), design-antipatterns.md (20,707), roadmap-process-loop.md (20,360), orchestration-telemetry.md (16,155). Recorded rather than fixed because splitting four large reference documents is unrelated to the change that introduced the ceiling, and a gate that lands as four instant blockers is the shape this repository has already recorded as a failure. Shrink-only from here: a FIFTH over-ceiling file reds. roadmap-process-loop.md is the file that motivated the gate — it states 'Size budget: <= 4,000 chars' in its own header and is 5x over it, which is what a declared budget with nothing measuring it decays into. The ceiling is a GROWTH RATCHET, not a measured quality threshold: the 7,308-trajectory study behind the 3,500-token skill ceiling (ADR-217) was taken on procedural always-co-loaded skills, and this layer is declarative and loaded one or two files at a time. Replace the number when someone measures comprehension on THIS layer."
|
|
34
|
+
},
|
|
35
|
+
"gate-self-test:registered-non-adopters": {
|
|
36
|
+
"count": 24,
|
|
37
|
+
"landed": "2026-08-06",
|
|
38
|
+
"note": "Self-test adoption ratchet, expressed as a shrink-only NON-adopter count. 24 of the 32 gates registered enforced in gate-coverage.yml carry neither a `--self-test` (`_lib/gate_self_test.ts`) nor a `// self-test-exempt: <reason>` marker, so nothing proves they DISCRIMINATE — an enforced `scanned:` floor proves a gate read something, only a self-test proves the reading changes the verdict. Deliberately NOT an adoption column ratcheted upward: check_gate_coverage.ts's own report_hardening_ratchet rejects that shape in this same file (\"grades the solution instead of the problem\"), and the sibling adoption ratchet (check_gate_completeness) is already a non-adopter count. Population is the manifest, not every script under src/scripts: padding the manifest to move this number would mean adding a floor per row. Shrink-only from here — a NEW registered gate must adopt or exempt. Migration mechanism, same as the ledger ratchet above: gates adopt as they are touched, not in a sweep — the eight current adopters were each added alongside a real change to that gate. The 56-day non-stagnation clause applies unchanged, so a count parked here fails on its own.",
|
|
39
|
+
"falsifier": "./scripts-run src/scripts/check_gate_coverage"
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
}
|
|
@@ -90,6 +90,7 @@ import * as installed_tools from '../_lib/installed_tools.js';
|
|
|
90
90
|
import * as user_global_paths from '../_lib/user_global_paths.js';
|
|
91
91
|
import * as global_deploy_inventory from '../_lib/global_deploy_inventory.js';
|
|
92
92
|
import { censusDuplicateScope } from '../_lib/duplicate_scope_census.js';
|
|
93
|
+
import { git_common_dir } from '../_lib/git_common_dir.js';
|
|
93
94
|
import * as sync_gitattributes from '../sync_gitattributes.js';
|
|
94
95
|
import {
|
|
95
96
|
PROJECT_ROOT_ENV,
|
|
@@ -897,27 +898,11 @@ const _PLACEHOLDER_EMAIL_RE = /^(t@t\.t|.*@example\.(com|org)|.*@localhost)$/i;
|
|
|
897
898
|
const _PLACEHOLDER_NAME_RE = /^(t|test|user|nobody|x)$/i;
|
|
898
899
|
|
|
899
900
|
export function _git_config_path(project_root: string): string | null {
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
// Worktree: `.git` is a file "gitdir: <path>".
|
|
907
|
-
const m = readText(gd).match(/^gitdir:\s*(.+)\s*$/m);
|
|
908
|
-
if (m === null) {
|
|
909
|
-
return null;
|
|
910
|
-
}
|
|
911
|
-
const gdPath = path.resolve(project_root, m[1]!.trim());
|
|
912
|
-
const commondirFile = path.join(gdPath, 'commondir');
|
|
913
|
-
if (pathExists(commondirFile)) {
|
|
914
|
-
const common = path.resolve(gdPath, readText(commondirFile).trim());
|
|
915
|
-
return path.join(common, 'config');
|
|
916
|
-
}
|
|
917
|
-
return path.join(gdPath, 'config');
|
|
918
|
-
} catch {
|
|
919
|
-
return null;
|
|
920
|
-
}
|
|
901
|
+
// The `.git`-file / `commondir` walk this used to inline now lives in
|
|
902
|
+
// `_lib/git_common_dir.ts`, so the session register and this check cannot
|
|
903
|
+
// drift into two different answers to "where is the common dir".
|
|
904
|
+
const common = git_common_dir(project_root);
|
|
905
|
+
return common === null ? null : path.join(common, 'config');
|
|
921
906
|
}
|
|
922
907
|
|
|
923
908
|
function _parse_git_user(configText: string): { name: string | null; email: string | null } {
|
|
@@ -36,8 +36,11 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
36
36
|
import { match_prompt, type Router } from '../_lib/router_match.js';
|
|
37
37
|
import { load_agent_settings } from '../_lib/agent_settings.js';
|
|
38
38
|
import { read_entries } from '../chat_history.js';
|
|
39
|
+
import { resolvePackageRoot } from '../_lib/package_root.js';
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
// Marker-anchored, not hop-counted — see the sibling note in cmd_route_explain.ts.
|
|
42
|
+
// Both routing commands were the last two `_cli` entries still counting hops.
|
|
43
|
+
const REPO_ROOT = resolvePackageRoot(import.meta.url);
|
|
41
44
|
const ROUTER_JSON = path.join(REPO_ROOT, 'dist', 'router.json');
|
|
42
45
|
|
|
43
46
|
// cache-version: v1 — rebuildable audit log: delete-and-rerun rebuilds it from
|
|
@@ -31,8 +31,16 @@ import {
|
|
|
31
31
|
} from '../_lib/router_match.js';
|
|
32
32
|
import { measure, method_note } from '../_lib/token_count.js';
|
|
33
33
|
import { load_agent_settings } from '../_lib/agent_settings.js';
|
|
34
|
+
import { resolvePackageRoot } from '../_lib/package_root.js';
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// Marker-anchored, not hop-counted: this module runs from `src/scripts/_cli/`
|
|
37
|
+
// (three levels down) AND from the precompiled `dist/cli-delegate/` (two), and
|
|
38
|
+
// a fixed hop count is right in exactly one of them. Three hops from the bundle
|
|
39
|
+
// landed on `<pkg>/..` — `node_modules/@event4u` for a scoped install — so
|
|
40
|
+
// `route:explain` and `route:audit` reported dist/router.json as missing on
|
|
41
|
+
// every invocation through the shipped binary while both worked under `tsx`.
|
|
42
|
+
// The resolver exists precisely for this and 12 sibling commands already use it.
|
|
43
|
+
const REPO_ROOT = resolvePackageRoot(import.meta.url);
|
|
36
44
|
const ROUTER_JSON = path.join(REPO_ROOT, 'dist', 'router.json');
|
|
37
45
|
const RULES_DIST_DIR = path.join(REPO_ROOT, 'dist', 'agent-src', 'rules');
|
|
38
46
|
|
|
@@ -177,6 +177,10 @@ Tier 2 — maintenance / internal (hooks, MCP, memory, telemetry):
|
|
|
177
177
|
projection (from the pinned token baseline). Flags: --format
|
|
178
178
|
code-graph Deterministic code-graph engine (ADR-124, Class A).
|
|
179
179
|
Usage: code-graph build|validate|detect|query|explain|affected|path [options]
|
|
180
|
+
sessions:list List live agent sessions on this repository (shared
|
|
181
|
+
session register). Flags: --json
|
|
182
|
+
sessions:claim Claim a roadmap for this session so other sessions skip
|
|
183
|
+
it; --release clears the claim
|
|
180
184
|
roadmap:progress Regenerate agents/roadmaps-progress.md from open roadmaps
|
|
181
185
|
roadmap:progress-check Fail if agents/roadmaps-progress.md is stale (for CI)
|
|
182
186
|
roadmap:archive Archive completed roadmaps (branch-touched by default;
|
|
@@ -579,6 +583,18 @@ cmd_mcp_run() {
|
|
|
579
583
|
exec_ts "$server_main" "$@"
|
|
580
584
|
}
|
|
581
585
|
|
|
586
|
+
# Shared session register (road-to-parallel-session-coordination). Resolved from
|
|
587
|
+
# PACKAGE_ROOT, not the consumer projection: the CLI imports the register library
|
|
588
|
+
# under src/scripts/_lib/, which is package-internal and never shipped into
|
|
589
|
+
# dist/agent-src/scripts/. Same shape as cmd_settings_set.
|
|
590
|
+
cmd_sessions_list() {
|
|
591
|
+
exec_ts "$PACKAGE_ROOT/src/scripts/sessions_cli.ts" list "$@"
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
cmd_sessions_claim() {
|
|
595
|
+
exec_ts "$PACKAGE_ROOT/src/scripts/sessions_cli.ts" claim "$@"
|
|
596
|
+
}
|
|
597
|
+
|
|
582
598
|
cmd_roadmap_progress() {
|
|
583
599
|
local script
|
|
584
600
|
script="$(resolve_script "dist/agent-src/scripts/update_roadmap_progress.ts" ".augment/scripts/update_roadmap_progress.ts")"
|
|
@@ -1252,6 +1268,8 @@ main() {
|
|
|
1252
1268
|
benchmark) cmd_benchmark "$@" ;;
|
|
1253
1269
|
code-graph) cmd_code_graph "$@" ;;
|
|
1254
1270
|
conformance:behavior) cmd_conformance_behavior "$@" ;;
|
|
1271
|
+
sessions:list) cmd_sessions_list "$@" ;;
|
|
1272
|
+
sessions:claim) cmd_sessions_claim "$@" ;;
|
|
1255
1273
|
roadmap:progress) cmd_roadmap_progress "$@" ;;
|
|
1256
1274
|
roadmap:progress-check) cmd_roadmap_progress_check "$@" ;;
|
|
1257
1275
|
roadmap:archive) cmd_roadmap_archive "$@" ;;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a repository's **common git directory** — the one directory every
|
|
3
|
+
* worktree of a repo shares.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `_cli/cmd_doctor.ts::_git_config_path`, which has resolved the
|
|
6
|
+
* `commondir` file this way since the git-identity check shipped. It is
|
|
7
|
+
* extracted rather than re-implemented on purpose: a repo with two different
|
|
8
|
+
* answers to "where is the common dir" is a bug waiting for a symlinked parent,
|
|
9
|
+
* and the worktree-cleanup work already hit that class once.
|
|
10
|
+
*
|
|
11
|
+
* ## Why this reads files instead of shelling out to git
|
|
12
|
+
*
|
|
13
|
+
* `git rev-parse --git-common-dir` is the obvious implementation and is wrong
|
|
14
|
+
* for the callers here, twice over:
|
|
15
|
+
*
|
|
16
|
+
* 1. **Inherited `GIT_DIR` overrides discovery.** Git hooks export `GIT_DIR`,
|
|
17
|
+
* and every child inherits it, so `execFileSync('git', …, { cwd })` silently
|
|
18
|
+
* resolves against the *hook's* repository rather than `cwd` — in a linked
|
|
19
|
+
* worktree those differ, and the symptom is wrong data, not an error. That
|
|
20
|
+
* is exactly what `_lib/git_env.ts` exists to strip. A file-based resolution
|
|
21
|
+
* has nothing to override and needs no such guard.
|
|
22
|
+
* 2. **The raw output is not comparable across checkouts.** Measured
|
|
23
|
+
* 2026-08-07: from a main checkout `git rev-parse --git-common-dir` prints
|
|
24
|
+
* the **relative** `.git`; from a linked worktree it prints an absolute
|
|
25
|
+
* path. A consumer comparing the raw strings concludes the two checkouts
|
|
26
|
+
* have different common dirs. Only the resolved realpath is a repo identity.
|
|
27
|
+
*
|
|
28
|
+
* ## Symlinked parents converge
|
|
29
|
+
*
|
|
30
|
+
* Measured on a throwaway repo reached both directly and through a symlinked
|
|
31
|
+
* ancestor: all four accesses (main / worktree × real / symlinked) resolve to
|
|
32
|
+
* the same directory, because the returned path is realpath-normalised here.
|
|
33
|
+
* This is the opposite of the worktree-cleanup finding that motivated the
|
|
34
|
+
* check — there realpath reporting caused a mis-classification; here it is the
|
|
35
|
+
* property that makes one shared register possible.
|
|
36
|
+
*
|
|
37
|
+
* Never throws: every caller treats "no common dir" as a reason to degrade,
|
|
38
|
+
* not as an error worth failing a hook over.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import fs from 'node:fs';
|
|
42
|
+
import path from 'node:path';
|
|
43
|
+
|
|
44
|
+
/** `fs.realpathSync` that falls back to the input when the path is unreadable. */
|
|
45
|
+
function realpath_or_self(p: string): string {
|
|
46
|
+
try {
|
|
47
|
+
return fs.realpathSync(p);
|
|
48
|
+
} catch {
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The **per-worktree** git directory for `project_root` — `.git` in a plain
|
|
55
|
+
* checkout, the linked gitdir in a worktree. This is where `HEAD` lives, so it
|
|
56
|
+
* is the right anchor for "which branch is THIS checkout on", as opposed to
|
|
57
|
+
* `git_common_dir` which is deliberately shared across worktrees.
|
|
58
|
+
*/
|
|
59
|
+
export function git_dir(project_root: string): string | null {
|
|
60
|
+
const dot_git = path.join(project_root, '.git');
|
|
61
|
+
try {
|
|
62
|
+
const st = fs.statSync(dot_git);
|
|
63
|
+
if (st.isDirectory()) {
|
|
64
|
+
return realpath_or_self(dot_git);
|
|
65
|
+
}
|
|
66
|
+
const m = fs.readFileSync(dot_git, 'utf-8').match(/^gitdir:\s*(.+)\s*$/m);
|
|
67
|
+
if (m === null) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return realpath_or_self(path.resolve(project_root, m[1]!.trim()));
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Current branch name for `project_root`, or `null` on a detached HEAD or
|
|
78
|
+
* outside a repo.
|
|
79
|
+
*
|
|
80
|
+
* Reads `<git-dir>/HEAD` directly rather than shelling out, for the same reason
|
|
81
|
+
* as everything else in this module: hooks export `GIT_DIR`, and an inherited
|
|
82
|
+
* one silently redirects `git` to the wrong repository.
|
|
83
|
+
*/
|
|
84
|
+
export function current_branch(project_root: string): string | null {
|
|
85
|
+
const gd = git_dir(project_root);
|
|
86
|
+
if (gd === null) return null;
|
|
87
|
+
try {
|
|
88
|
+
const head = fs.readFileSync(path.join(gd, 'HEAD'), 'utf-8').trim();
|
|
89
|
+
const m = head.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
90
|
+
return m === null ? null : m[1]!.trim();
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The common git directory for `project_root`, realpath-normalised, or `null`
|
|
98
|
+
* when `project_root` is not inside a git repository.
|
|
99
|
+
*
|
|
100
|
+
* - Plain checkout → `<project_root>/.git`.
|
|
101
|
+
* - Linked worktree → the `commondir` target of the worktree's gitdir, i.e. the
|
|
102
|
+
* main checkout's `.git`, which is identical from every worktree of the repo.
|
|
103
|
+
* - Worktree gitdir without a `commondir` file → the gitdir itself (degenerate,
|
|
104
|
+
* but the historical behaviour and not this change's to alter).
|
|
105
|
+
*/
|
|
106
|
+
export function git_common_dir(project_root: string): string | null {
|
|
107
|
+
const dot_git = path.join(project_root, '.git');
|
|
108
|
+
try {
|
|
109
|
+
const st = fs.statSync(dot_git);
|
|
110
|
+
if (st.isDirectory()) {
|
|
111
|
+
return realpath_or_self(dot_git);
|
|
112
|
+
}
|
|
113
|
+
// Linked worktree: `.git` is a FILE containing "gitdir: <path>".
|
|
114
|
+
const m = fs.readFileSync(dot_git, 'utf-8').match(/^gitdir:\s*(.+)\s*$/m);
|
|
115
|
+
if (m === null) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const gitdir = path.resolve(project_root, m[1]!.trim());
|
|
119
|
+
const commondir_file = path.join(gitdir, 'commondir');
|
|
120
|
+
if (fs.existsSync(commondir_file)) {
|
|
121
|
+
const common = path.resolve(gitdir, fs.readFileSync(commondir_file, 'utf-8').trim());
|
|
122
|
+
return realpath_or_self(common);
|
|
123
|
+
}
|
|
124
|
+
return realpath_or_self(gitdir);
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|