@event4u/agent-config 9.13.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +113 -67
- package/README.md +9 -1
- package/dist/agent-src/commands/agents/audit.md +7 -7
- package/dist/agent-src/commands/agents/optimize.md +1 -1
- package/dist/agent-src/commands/analyze/reference-repo.md +1 -1
- package/dist/agent-src/commands/chat-history.md +1 -0
- package/dist/agent-src/commands/context.md +1 -0
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/ghostwriter.md +1 -1
- package/dist/agent-src/commands/memory.md +2 -1
- package/dist/agent-src/commands/module.md +1 -0
- package/dist/agent-src/commands/optimize/agents-dir.md +1 -1
- package/dist/agent-src/commands/optimize/deep.md +150 -0
- package/dist/agent-src/commands/optimize/skills.md +5 -5
- package/dist/agent-src/commands/optimize.md +12 -6
- package/dist/agent-src/commands/override.md +1 -0
- package/dist/agent-src/commands/prediction-pool.md +4 -4
- package/dist/agent-src/commands/research/deep.md +1 -1
- package/dist/agent-src/commands/roadmap.md +2 -1
- package/dist/agent-src/commands/rule-compliance-audit.md +1 -1
- package/dist/agent-src/commands/tdd.md +1 -0
- package/dist/agent-src/commands/tests.md +1 -0
- package/dist/agent-src/commands/upstream-contribute.md +5 -5
- package/dist/agent-src/commands/video/from-script.md +1 -1
- package/dist/agent-src/commands/video/from-song.md +1 -1
- package/dist/agent-src/commands/video/scene.md +1 -1
- package/dist/agent-src/commands/video/stitch.md +1 -1
- package/dist/agent-src/commands/video/storyboard.md +1 -1
- package/dist/agent-src/commands/worktree/create.md +2 -1
- package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +5 -5
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -3
- package/dist/agent-src/contexts/contracts/emergency-triage-block.md +2 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +4 -3
- package/dist/agent-src/contexts/execution/subagent-routing.md +19 -0
- package/dist/agent-src/contexts/override-system.md +1 -1
- package/dist/agent-src/ghostwriter/fictional-fixture-v1.md +1 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +2 -1
- package/dist/agent-src/rules/brand-consistency.md +1 -0
- package/dist/agent-src/rules/brand-source-of-truth.md +1 -0
- package/dist/agent-src/rules/code-comment-discipline.md +2 -0
- package/dist/agent-src/rules/communication-through-line.md +1 -0
- package/dist/agent-src/rules/content-quoting-floor.md +1 -0
- package/dist/agent-src/rules/cross-source-consistency.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +1 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +1 -0
- package/dist/agent-src/rules/external-reference-deep-dive.md +1 -0
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/improve-before-implement.md +1 -1
- package/dist/agent-src/rules/invite-challenge.md +1 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +4 -3
- package/dist/agent-src/rules/media-sync-ground-truth.md +1 -0
- package/dist/agent-src/rules/no-attribution-footers.md +1 -0
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +1 -0
- package/dist/agent-src/rules/no-pr-progress-comments.md +1 -0
- package/dist/agent-src/rules/onboarding-gate.md +1 -0
- package/dist/agent-src/rules/output-discipline.md +1 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +1 -0
- package/dist/agent-src/rules/preservation-guard.md +1 -0
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +1 -0
- package/dist/agent-src/rules/role-mode-adherence.md +1 -0
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +1 -0
- package/dist/agent-src/rules/session-canary.md +9 -2
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/source-of-truth.md +1 -0
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -0
- package/dist/agent-src/rules/think-before-action.md +1 -0
- package/dist/agent-src/rules/token-budget-discipline.md +1 -0
- package/dist/agent-src/rules/token-efficiency.md +1 -0
- package/dist/agent-src/rules/token-optimizer-maintenance.md +5 -5
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/skills/adr-create/SKILL.md +1 -1
- package/dist/agent-src/skills/check-refs/SKILL.md +1 -1
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +1 -1
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +1 -1
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/github-ci/SKILL.md +1 -0
- package/dist/agent-src/skills/guideline-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/lint-skills/SKILL.md +1 -1
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/roadmap-management/SKILL.md +8 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +4 -4
- package/dist/agent-src/skills/token-optimizer/SKILL.md +4 -4
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +6 -6
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +25 -0
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/command.md +1 -1
- package/dist/agent-src/templates/copilot-instructions.md +3 -3
- package/dist/agent-src/templates/rule.md +2 -2
- package/dist/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
- package/dist/agent-src/templates/skill-archive-note.md +5 -5
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/agent-config.js +66 -19
- package/dist/cli/agent-config.js.map +1 -1
- package/dist/cli/main.js +9 -4
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/python/workspace_drive.js +2 -0
- package/dist/cli/python/workspace_drive.js.map +1 -1
- package/dist/cli/python/workspace_drive_health.js +2 -0
- package/dist/cli/python/workspace_drive_health.js.map +1 -1
- package/dist/cli/python/workspace_hosts.js +2 -0
- package/dist/cli/python/workspace_hosts.js.map +1 -1
- package/dist/cli/python/workspace_sessions.js +2 -0
- package/dist/cli/python/workspace_sessions.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-A3HJ6NTI.js → chunk-63WSP6YZ.js} +2 -1
- package/dist/cli-delegate/{chunk-EJYIGZ3T.js → chunk-BKO2AZ7Z.js} +1 -1
- package/dist/cli-delegate/{chunk-QFKQLQ7X.js → chunk-H574KOUH.js} +340 -462
- package/dist/cli-delegate/chunk-NXFWFAYV.js +339 -0
- package/dist/cli-delegate/{chunk-TEGJU2JX.js → chunk-ZXXJLL5K.js} +2 -2
- package/dist/cli-delegate/cmd_conformance.js +29 -23
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +163 -103
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +729 -430
- package/dist/install/install.mjs +700 -625
- package/dist/install/rule_scope.js +18 -2
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +564 -424
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/claude_settings_hooks.js +30 -5
- package/dist/scripts/_lib/claude_settings_hooks.js.map +1 -1
- package/dist/scripts/_lib/scoped_projection.js +223 -0
- package/dist/scripts/_lib/scoped_projection.js.map +1 -0
- package/dist/scripts/_lib/surface_tiers.js +125 -0
- package/dist/scripts/_lib/surface_tiers.js.map +1 -0
- package/dist/scripts/_lib/token_count.js +166 -0
- package/dist/scripts/_lib/token_count.js.map +1 -0
- package/dist/scripts/_lib/trigger_eval_floors.js +8 -0
- package/dist/scripts/_lib/trigger_eval_floors.js.map +1 -1
- package/dist/scripts/condense.js +139 -9
- package/dist/scripts/condense.js.map +1 -1
- package/dist/scripts/project_thin_rules.js +450 -0
- package/dist/scripts/project_thin_rules.js.map +1 -0
- package/dist/server/routes/workspace.js +2 -0
- package/dist/server/routes/workspace.js.map +1 -1
- package/dist/server/schemas/settings.js +9 -3
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/ui/assets/index-DJY_vQVn.js +40 -0
- package/dist/ui/assets/index-DJY_vQVn.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/package.json +11 -11
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/orchestration.ts +1 -1
- package/src/config/agent-settings.template.yml +59 -11
- package/src/config/ci-local-parity.yml +8 -0
- package/src/config/discovery/unassigned-artefacts.yml +23 -25
- package/src/config/evaluator-budgets.json +35 -5
- package/src/config/gate-coverage.yml +147 -0
- package/src/config/gate-violation-baselines.json +25 -0
- package/src/install/rule_scope.ts +27 -2
- package/src/scripts/_cli/cmd_conformance.ts +13 -24
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +30 -4
- package/src/scripts/_lib/exec_evidence.ts +5 -0
- package/src/scripts/_lib/gate_baseline.ts +213 -0
- package/src/scripts/_lib/scoped_projection.ts +262 -0
- package/src/scripts/_lib/tier_budget_routing.ts +234 -0
- package/src/scripts/_lib/tool_adapter_registry.ts +8 -1
- package/src/scripts/_lib/trigger_eval_floors.ts +9 -0
- package/src/scripts/_lib/trigger_routers.ts +17 -5
- package/src/scripts/adr/regenerate_index.ts +4 -3
- package/src/scripts/ai-video/lib/parse-blueprint.sh +1 -1
- package/src/scripts/ai_council/compile_corpus.ts +1 -1
- package/src/scripts/audit_cloud_compatibility.ts +37 -2
- package/src/scripts/audit_initial_context.ts +53 -19
- package/src/scripts/audit_likelihood.ts +31 -2
- package/src/scripts/audit_user_type_axis.ts +58 -11
- package/src/scripts/bench_hook_latency.ts +172 -41
- package/src/scripts/build_mcp_catalog.ts +12 -1
- package/src/scripts/check_always_budget.ts +122 -11
- package/src/scripts/check_artefact_count_messaging.ts +128 -15
- package/src/scripts/check_augment_description_cap.ts +24 -3
- package/src/scripts/check_ci_strict_superset.ts +150 -0
- package/src/scripts/check_cluster_patterns.ts +100 -0
- package/src/scripts/check_consumer_scope_flip.ts +26 -4
- package/src/scripts/check_evaluator_budgets.ts +198 -19
- package/src/scripts/check_gate_coverage.ts +337 -1
- package/src/scripts/check_generator_output_coverage.ts +2 -1
- package/src/scripts/check_iron_law_prominence.ts +1 -1
- package/src/scripts/check_kernel_rule_bundle.ts +1 -1
- package/src/scripts/check_no_new_legacy_path.ts +167 -3
- package/src/scripts/check_pack_size.ts +18 -4
- package/src/scripts/check_portability.ts +37 -7
- package/src/scripts/check_references.ts +19 -3
- package/src/scripts/check_release_pr_shape.ts +13 -0
- package/src/scripts/check_token_regression.ts +9 -2
- package/src/scripts/condense.ts +155 -12
- package/src/scripts/cost/budget.mjs +63 -2
- package/src/scripts/count_scoped_projection.ts +104 -0
- package/src/scripts/evaluator_umbrella.sh +34 -1
- package/src/scripts/generate_capability_matrix.ts +8 -0
- package/src/scripts/generate_router_coverage_from_matrix.ts +155 -0
- package/src/scripts/hook_manifest.yaml +17 -3
- package/src/scripts/hooks/block_config_weakening.ts +337 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/probe_throttle.ts +75 -0
- package/src/scripts/install-hooks.sh +24 -2
- package/src/scripts/install.ts +15 -92
- package/src/scripts/lint_agents_md.ts +9 -3
- package/src/scripts/lint_archived_skills.ts +1 -1
- package/src/scripts/lint_artefact_frontmatter.ts +185 -37
- package/src/scripts/lint_command_routing.ts +21 -52
- package/src/scripts/lint_command_verbs.ts +47 -28
- package/src/scripts/lint_context_spine_usage.ts +38 -12
- package/src/scripts/lint_framework_leakage.ts +25 -6
- package/src/scripts/lint_handoffs.ts +49 -2
- package/src/scripts/lint_media_policy_linkage.ts +62 -30
- package/src/scripts/lint_namespace.ts +92 -7
- package/src/scripts/lint_new_skill_gate.ts +39 -31
- package/src/scripts/lint_originality_shingles.ts +7 -1
- package/src/scripts/lint_override_kernel_guard.ts +21 -3
- package/src/scripts/lint_pack_boundaries.ts +461 -91
- package/src/scripts/lint_pack_dependencies.ts +24 -57
- package/src/scripts/lint_persona_governance.ts +1 -1
- package/src/scripts/lint_role_experiences.ts +34 -5
- package/src/scripts/lint_trigger_precision.ts +142 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +12 -201
- package/src/scripts/mcp_server/tools.ts +1 -1
- package/src/scripts/prepack-check.mjs +40 -1
- package/src/scripts/prepack_router_targets.d.mts +7 -0
- package/src/scripts/prepack_router_targets.mjs +93 -0
- package/src/scripts/print_required_checks.ts +72 -18
- package/src/scripts/profile_staleness_hook.ts +12 -0
- package/src/scripts/record_evaluator_measurements.mjs +105 -0
- package/src/scripts/recruit_preflight.sh +1 -1
- package/src/scripts/release.ts +105 -1
- package/src/scripts/router_target_paths.d.mts +4 -0
- package/src/scripts/router_target_paths.mjs +69 -0
- package/src/scripts/router_telemetry.ts +52 -1
- package/src/scripts/routing_doctor.ts +485 -0
- package/src/scripts/rule_trigger_eval.ts +403 -0
- package/src/scripts/schemas/rule.schema.json +5 -1
- package/src/scripts/session_canary_hook.ts +96 -5
- package/src/scripts/skill_linter.ts +90 -42
- package/src/scripts/smoke/skills.sh +1 -1
- package/src/scripts/sweep_dead_scan_roots.ts +356 -10
- package/src/scripts/trigger_coverage.ts +13 -2
- package/src/scripts/update_counts.ts +91 -12
- package/src/scripts/validate_telegraph_carveouts.ts +1 -1
- package/src/scripts/wrapper_freshness_hook.ts +14 -0
- package/src/server/schemas/settings.ts +19 -5
- package/dist/cli-delegate/chunk-TJIAM5FW.js +0 -133
- package/dist/ui/assets/index-BpSQt5vm.js +0 -40
- package/dist/ui/assets/index-BpSQt5vm.js.map +0 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* prepack-check.mjs — guard the published artifact.
|
|
4
4
|
*
|
|
5
5
|
* Runs during `npm pack` / `npm publish` AND as a dry-run on every PR
|
|
6
|
-
* (Static Checks workflow).
|
|
6
|
+
* (Static Checks workflow). Four gates:
|
|
7
7
|
*
|
|
8
8
|
* 1. Compiled-bin shape — the TS CLI binary exists, is executable, and
|
|
9
9
|
* carries the Node shebang before the tarball is built. Otherwise a
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* 2. Shipped-import completeness — every relative import reachable from
|
|
13
13
|
* the shipped `src/` trees resolves to a file the `files` whitelist
|
|
14
14
|
* actually ships (the 8.3.0 ERR_MODULE_NOT_FOUND class).
|
|
15
|
+
* 3. Lifecycle-target shape — every consumer-side lifecycle script points
|
|
16
|
+
* at a target that exists and ships (the 9.8.0 dead-postinstall class).
|
|
17
|
+
* 4. Router-target shipping — every `routes_to` target in dist/router.json
|
|
18
|
+
* resolves inside the shipped `files[]` set, so a `files[]` narrowing
|
|
19
|
+
* cannot ship a dead router pointer.
|
|
15
20
|
*
|
|
16
21
|
* Folded from external council pass 2026-05-18 (Phase 1.3 acceptance).
|
|
17
22
|
*
|
|
@@ -176,6 +181,40 @@ if (lifecycleErrors.length > 0) {
|
|
|
176
181
|
}
|
|
177
182
|
process.stderr.write('prepack-check: lifecycle script targets OK\n');
|
|
178
183
|
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// Router-pointer shipping guard (gate 4): every `routes_to` target in
|
|
186
|
+
// dist/router.json must resolve to a file that exists AND is inside the
|
|
187
|
+
// shipped `files[]` set. A `files[]` narrowing that drops a routed target was
|
|
188
|
+
// caught once by a working gate; this makes that catch structural rather than
|
|
189
|
+
// incidental, and moves it to pack time on the causing PR
|
|
190
|
+
// (road-to-gates-that-can-fail Phase 4). The kind→path table is single-sourced
|
|
191
|
+
// from ./router_target_paths.mjs, shared with
|
|
192
|
+
// cmd_conformance.ts::routeTargetPaths — two copies could disagree about where
|
|
193
|
+
// a pointer lives, which is the packaging↔runtime gap this closes.
|
|
194
|
+
//
|
|
195
|
+
// PREPACK_ROUTER_JSON points the gate at a different index (repo-relative or
|
|
196
|
+
// absolute) — used by tests/scripts/prepack_router_targets.test.ts and by the
|
|
197
|
+
// planted-target proof, so dist/router.json itself is never mutated.
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
import { checkRouterTargetsShipped } from './prepack_router_targets.mjs';
|
|
200
|
+
|
|
201
|
+
const routerRel = env.PREPACK_ROUTER_JSON ?? 'dist/router.json';
|
|
202
|
+
const routerResult = checkRouterTargetsShipped({
|
|
203
|
+
routerPath: resolve(routerRel),
|
|
204
|
+
isShipped,
|
|
205
|
+
exists: (relPath) => existsSync(resolve(relPath)),
|
|
206
|
+
readFile: (p) => readFileSync(p, 'utf8'),
|
|
207
|
+
});
|
|
208
|
+
if (routerResult.errors.length > 0) {
|
|
209
|
+
for (const e of routerResult.errors) {
|
|
210
|
+
process.stderr.write(`prepack-check: ${e}\n`);
|
|
211
|
+
}
|
|
212
|
+
die(`${routerResult.errors.length} router target(s) do not resolve inside the shipped set.`);
|
|
213
|
+
}
|
|
214
|
+
process.stderr.write(
|
|
215
|
+
`prepack-check: router targets OK (${routerResult.scanned} routes_to target(s) in ${routerRel})\n`,
|
|
216
|
+
);
|
|
217
|
+
|
|
179
218
|
// Optional: invoked with --verbose dumps the size for tarball-budget bookkeeping.
|
|
180
219
|
if (argv.includes('--verbose')) {
|
|
181
220
|
process.stderr.write(`prepack-check: size=${st.size} bytes\n`);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Type declarations for prepack_router_targets.mjs (prepack gate 4). */
|
|
2
|
+
export declare function checkRouterTargetsShipped(opts: {
|
|
3
|
+
routerPath: string;
|
|
4
|
+
isShipped: (relPath: string) => boolean;
|
|
5
|
+
exists: (relPath: string) => boolean;
|
|
6
|
+
readFile: (absPath: string) => string;
|
|
7
|
+
}): { errors: string[]; scanned: number };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prepack_router_targets.mjs — pure core of prepack gate 4.
|
|
3
|
+
*
|
|
4
|
+
* Every `routes_to` target in `dist/router.json` must resolve to a file that
|
|
5
|
+
* (a) exists and (b) is inside the `files[]` whitelist. A pointer that
|
|
6
|
+
* resolves in the dev tree but is not in the tarball is dead the moment a
|
|
7
|
+
* consumer installs it — `agent-config conformance`'s `router-pointers` check
|
|
8
|
+
* then fails on the consumer's machine, for a defect introduced here.
|
|
9
|
+
*
|
|
10
|
+
* The kind→path table is NOT defined here: it is imported from
|
|
11
|
+
* `router_target_paths.mjs`, which `cmd_conformance.ts::routeTargetPaths` also
|
|
12
|
+
* consumes. One table, two readers — see that file's header for why.
|
|
13
|
+
*
|
|
14
|
+
* Extracted from `prepack-check.mjs` for the same reason
|
|
15
|
+
* `prepack_lifecycle_check.mjs` was: the entry script has top-level side
|
|
16
|
+
* effects and `process.exit`, so it cannot be imported by a test.
|
|
17
|
+
* road-to-gates-that-can-fail Phase 4.
|
|
18
|
+
*/
|
|
19
|
+
import { routeTargetPathsPosix } from './router_target_paths.mjs';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {object} RouterTargetOptions
|
|
23
|
+
* @property {string} routerPath Absolute path to the router index.
|
|
24
|
+
* @property {(relPath: string) => boolean} isShipped `files[]` membership test.
|
|
25
|
+
* @property {(relPath: string) => boolean} exists Existence test, repo-relative.
|
|
26
|
+
* @property {(absPath: string) => string} readFile Reader for `routerPath`.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {RouterTargetOptions} opts
|
|
31
|
+
* @returns {{ errors: string[], scanned: number }}
|
|
32
|
+
*/
|
|
33
|
+
export function checkRouterTargetsShipped(opts) {
|
|
34
|
+
const { routerPath, isShipped, exists, readFile } = opts;
|
|
35
|
+
const errors = [];
|
|
36
|
+
let scanned = 0;
|
|
37
|
+
|
|
38
|
+
let router;
|
|
39
|
+
try {
|
|
40
|
+
router = JSON.parse(readFile(routerPath));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
return {
|
|
43
|
+
errors: [`router index ${routerPath} unreadable or not JSON: ${e.message}`],
|
|
44
|
+
scanned: 0,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const tier of ['tier_1', 'tier_2']) {
|
|
49
|
+
for (const entry of router[tier] ?? []) {
|
|
50
|
+
const ruleId = String(entry?.id ?? '<unnamed rule>');
|
|
51
|
+
for (const raw of entry?.routes_to ?? []) {
|
|
52
|
+
const target = String(raw);
|
|
53
|
+
scanned += 1;
|
|
54
|
+
const candidates = routeTargetPathsPosix(target);
|
|
55
|
+
if (candidates.length === 0) {
|
|
56
|
+
errors.push(
|
|
57
|
+
`${tier}:${ruleId} routes_to ${JSON.stringify(target)} — unparseable ` +
|
|
58
|
+
'target or unknown kind (router_target_paths.mjs has no template ' +
|
|
59
|
+
'for it), so nothing can be verified as shipped',
|
|
60
|
+
);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const present = candidates.filter((rel) => exists(rel));
|
|
64
|
+
if (present.length === 0) {
|
|
65
|
+
errors.push(
|
|
66
|
+
`${tier}:${ruleId} routes_to '${target}' → none of ` +
|
|
67
|
+
`[${candidates.join(', ')}] exists in the tree`,
|
|
68
|
+
);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!present.some((rel) => isShipped(rel))) {
|
|
72
|
+
errors.push(
|
|
73
|
+
`${tier}:${ruleId} routes_to '${target}' → ${present[0]} exists but is ` +
|
|
74
|
+
'NOT in the package.json `files` whitelist — the pointer would ' +
|
|
75
|
+
'ship dead and fail `agent-config conformance` on the consumer',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Zero-scope is a failure (Phase 1 of the same roadmap): a router index
|
|
83
|
+
// that yields no targets means the shape changed under the gate, not that
|
|
84
|
+
// the package is clean.
|
|
85
|
+
if (errors.length === 0 && scanned === 0) {
|
|
86
|
+
errors.push(
|
|
87
|
+
`scanned 0 routes_to target(s) in ${routerPath} — the scan scope is dead or the ` +
|
|
88
|
+
'router schema moved; this gate cannot report clean on nothing',
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { errors, scanned };
|
|
93
|
+
}
|
|
@@ -61,28 +61,75 @@ const DOCS_ONLY_ALLOWED_TOP: ReadonlySet<string> = new Set([
|
|
|
61
61
|
'llms.txt',
|
|
62
62
|
]);
|
|
63
63
|
|
|
64
|
+
// Check names below are the strings GitHub actually REPORTS, verified against
|
|
65
|
+
// `gh pr checks 1108` on 2026-08-02 (road-to-renewal-foundation Phase 1).
|
|
66
|
+
//
|
|
67
|
+
// They previously named a matrix that had drifted into fiction — `Consistency`,
|
|
68
|
+
// `Skill Lint`, `Tests / install-tests`, `Tests / node-tests`,
|
|
69
|
+
// `Public Install Smoke / smoke`, `Migration Dry-Run`,
|
|
70
|
+
// `Release Validation / release-shape`, `Release Guard (post-tag)` and, most
|
|
71
|
+
// clearly, `Tests / python-tests`, which cannot exist at all: the Python→TS
|
|
72
|
+
// migration completed and `no-python-in-src.yml` now enforces its absence. A
|
|
73
|
+
// preview tool that prints names no check will ever report is worse than no
|
|
74
|
+
// preview — it reads as a verified list.
|
|
75
|
+
//
|
|
76
|
+
// Matrix families are printed as ONE line with the axis spelled out rather than
|
|
77
|
+
// as N pinned contexts. Shard counts and runner labels are part of the reported
|
|
78
|
+
// name, so pinning them here would re-create the same drift on the next matrix
|
|
79
|
+
// change — the exact failure this reconciliation removed.
|
|
64
80
|
const FEATURE_CHECKS = [
|
|
65
|
-
'Consistency',
|
|
66
|
-
'Smoke
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
'
|
|
81
|
+
'Sync + Generate Tools Consistency',
|
|
82
|
+
'Smoke — kernel',
|
|
83
|
+
'Smoke — router',
|
|
84
|
+
'Smoke — schema',
|
|
85
|
+
'Smoke — skills',
|
|
86
|
+
'skill-lint',
|
|
87
|
+
'Static Checks (ESLint · typecheck · prepack)',
|
|
88
|
+
'Install Script Tests (matrix: {ubuntu,macos}-latest × shard 1-4/4)',
|
|
89
|
+
'Install Aux Tests (matrix: {ubuntu,macos}-latest)',
|
|
90
|
+
'Node Tests (matrix: {ubuntu,macos}-latest × shard 1-4/4)',
|
|
91
|
+
'Golden Tests (matrix: {ubuntu,macos}-latest)',
|
|
92
|
+
'Workspace Tests (matrix: {ubuntu,macos}-latest)',
|
|
93
|
+
'Public Install Smoke (matrix: {ubuntu,macos,windows}-latest × node {20,22})',
|
|
94
|
+
'Rule backstops',
|
|
95
|
+
'no-python-in-src',
|
|
96
|
+
'lint commit subjects',
|
|
73
97
|
] as const;
|
|
74
98
|
|
|
75
99
|
const RELEASE_CHECKS = [
|
|
76
|
-
'Consistency',
|
|
77
|
-
'Smoke
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
'
|
|
81
|
-
'Release
|
|
82
|
-
'
|
|
100
|
+
'Sync + Generate Tools Consistency',
|
|
101
|
+
'Smoke — kernel',
|
|
102
|
+
'Smoke — router',
|
|
103
|
+
'Smoke — schema',
|
|
104
|
+
'Smoke — skills',
|
|
105
|
+
'Release-PR shape detector',
|
|
106
|
+
'CHANGELOG entry exists for head version',
|
|
107
|
+
'package.json / marketplace.json / pack manifests agree',
|
|
108
|
+
'Release install E2E (pack → install → upgrade → boot)',
|
|
109
|
+
'npm audit (runtime deps, high+)',
|
|
110
|
+
'skill-lint-strict',
|
|
83
111
|
] as const;
|
|
84
112
|
|
|
85
|
-
const DOCS_ONLY_CHECKS = [
|
|
113
|
+
const DOCS_ONLY_CHECKS = [
|
|
114
|
+
'Sync + Generate Tools Consistency',
|
|
115
|
+
'Smoke — kernel',
|
|
116
|
+
'Smoke — router',
|
|
117
|
+
'Smoke — schema',
|
|
118
|
+
'Smoke — skills',
|
|
119
|
+
] as const;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The checks that mechanically BLOCK a merge, per the repository ruleset
|
|
123
|
+
* `main protection` (id 17749383). Everything else above runs and is visible
|
|
124
|
+
* on the PR but does not gate the merge button.
|
|
125
|
+
*
|
|
126
|
+
* Deliberately a constant, not an API read: this script is contractually
|
|
127
|
+
* offline ("never invokes `gh`, never touches the network"). Re-verify with
|
|
128
|
+
* `gh api repos/event4u-app/agent-config/rulesets/17749383` when the ruleset
|
|
129
|
+
* changes — `docs/contracts/branch-protection-policy.md` § Change discipline
|
|
130
|
+
* owns that procedure.
|
|
131
|
+
*/
|
|
132
|
+
const ENFORCED_CHECKS = ['Sync + Generate Tools Consistency'] as const;
|
|
86
133
|
|
|
87
134
|
/** `git rev-parse --abbrev-ref HEAD`, mirroring `_git(check=True)`. */
|
|
88
135
|
function current_branch(): string {
|
|
@@ -161,12 +208,19 @@ function print_set(shape_label: Shape, files: string[]): void {
|
|
|
161
208
|
'docs-only': DOCS_ONLY_CHECKS,
|
|
162
209
|
};
|
|
163
210
|
const checks = table[shape_label];
|
|
211
|
+
const enforced: ReadonlySet<string> = new Set(ENFORCED_CHECKS);
|
|
164
212
|
process.stdout.write(`PR shape: ${shape_label} (${files.length} file(s) in diff)\n`);
|
|
165
|
-
process.stdout.write(`
|
|
213
|
+
process.stdout.write(`Checks this PR will face (${checks.length}):\n`);
|
|
166
214
|
for (const name of checks) {
|
|
167
|
-
|
|
215
|
+
// `!` marks the checks that actually block the merge button; the rest
|
|
216
|
+
// run and are visible but are advisory at the branch-protection layer.
|
|
217
|
+
process.stdout.write(` ${enforced.has(name) ? '!' : '-'} ${name}\n`);
|
|
168
218
|
}
|
|
169
219
|
process.stdout.write('\n');
|
|
220
|
+
process.stdout.write(
|
|
221
|
+
`! = blocks merge (${ENFORCED_CHECKS.length} of ${checks.length}); ` +
|
|
222
|
+
'- = runs, visible, advisory\n',
|
|
223
|
+
);
|
|
170
224
|
process.stdout.write(
|
|
171
225
|
'Contract: docs/contracts/branch-protection-policy.md ' +
|
|
172
226
|
'(per-PR-shape matrix)\n',
|
|
@@ -37,6 +37,9 @@ import {
|
|
|
37
37
|
LOCAL_PROJECT_SUBDIR,
|
|
38
38
|
} from "./_lib/agent_settings.js";
|
|
39
39
|
import { readHookStdin } from "./hooks/hook_stdin.js";
|
|
40
|
+
import { probeRanToday, stampProbeRun } from "./hooks/probe_throttle.js";
|
|
41
|
+
|
|
42
|
+
const THROTTLE_CONCERN = "profile-staleness";
|
|
40
43
|
|
|
41
44
|
// --- inlined session_profiles.stale_notice slice (unported dep) ----------
|
|
42
45
|
|
|
@@ -143,6 +146,15 @@ export function main(argv?: string[]): number {
|
|
|
143
146
|
_readStdinIfNotTty();
|
|
144
147
|
|
|
145
148
|
const root = rootArg !== null ? rootArg : _project_root();
|
|
149
|
+
|
|
150
|
+
// Daily throttle (road-to-hook-latency-repair): the overlay does not
|
|
151
|
+
// change within a day more often than a session ends — one attempt per
|
|
152
|
+
// local calendar day is enough. Skipped probe re-runs tomorrow.
|
|
153
|
+
if (probeRanToday(root, THROTTLE_CONCERN)) {
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
stampProbeRun(root, THROTTLE_CONCERN);
|
|
157
|
+
|
|
146
158
|
let notice: string | null;
|
|
147
159
|
try {
|
|
148
160
|
notice = _stale_notice(root);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* record_evaluator_measurements.mjs — write the committed measurement record.
|
|
4
|
+
*
|
|
5
|
+
* `cli_help_command_count` drifted 74 → 80 against a value frozen at 79 with
|
|
6
|
+
* nobody seeing it, because the only place the real number existed was a
|
|
7
|
+
* transient CI log. The fix (road-to-gates-that-can-fail Phase 5; council route
|
|
8
|
+
* 2026-08-02) is a COMMITTED artifact: the nightly writes the measurement set
|
|
9
|
+
* here, and `check_evaluator_budgets --recorded` compares a later fresh run
|
|
10
|
+
* against it — a contradiction warns on `main` and fails on `release/*`. The
|
|
11
|
+
* review surface that already exists carries the signal; no notification
|
|
12
|
+
* channel a single maintainer would mute.
|
|
13
|
+
*
|
|
14
|
+
* Lives under `agents/evidence/` (the repo's committed-evidence tree), NOT
|
|
15
|
+
* under `src/config/` which ships: this is maintainer evidence with nightly
|
|
16
|
+
* churn, not consumer runtime config, and keeping it out of the tarball also
|
|
17
|
+
* keeps `evaluator-budgets.json` — the policy — reviewable on its own.
|
|
18
|
+
*
|
|
19
|
+
* Sorted keys + 4-space indent + trailing newline: a moved number must be a
|
|
20
|
+
* one-line diff, or the artifact is not reviewable.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* node src/scripts/record_evaluator_measurements.mjs \
|
|
24
|
+
* --measurements <file.json> [--out <file.json>]
|
|
25
|
+
* [--sha <git sha>] [--run-url <url>] [--conditions <text>]
|
|
26
|
+
*/
|
|
27
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
28
|
+
import { dirname, resolve } from 'node:path';
|
|
29
|
+
import { argv, exit, stdout } from 'node:process';
|
|
30
|
+
|
|
31
|
+
/** Default (repo-relative) home of the record. */
|
|
32
|
+
export const RECORD_REL = 'agents/evidence/metrics/evaluator-measurements.json';
|
|
33
|
+
|
|
34
|
+
const RECORD_COMMENT =
|
|
35
|
+
'Written by src/scripts/record_evaluator_measurements.mjs, invoked from ' +
|
|
36
|
+
'src/scripts/evaluator_umbrella.sh when UMBRELLA_RECORD=1 (the nightly). ' +
|
|
37
|
+
'check_evaluator_budgets.ts --recorded compares a fresh measurement set against ' +
|
|
38
|
+
'this file; a contradiction on a DETERMINISTIC metric warns on main and fails on ' +
|
|
39
|
+
'release. Do not hand-edit — refresh it from a real run.';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build the record document. Pure — the caller owns the filesystem.
|
|
43
|
+
*
|
|
44
|
+
* @param {Record<string, unknown>} measurements
|
|
45
|
+
* @param {{ recordedAt?: string, sha?: string, runUrl?: string, conditions?: string }} [meta]
|
|
46
|
+
*/
|
|
47
|
+
export function buildRecord(measurements, meta = {}) {
|
|
48
|
+
const sorted = {};
|
|
49
|
+
for (const key of Object.keys(measurements).sort()) {
|
|
50
|
+
sorted[key] = measurements[key];
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
schema_version: 1,
|
|
54
|
+
_comment: RECORD_COMMENT,
|
|
55
|
+
recorded_at: meta.recordedAt ?? new Date().toISOString(),
|
|
56
|
+
git_sha: meta.sha || null,
|
|
57
|
+
run_url: meta.runUrl || null,
|
|
58
|
+
conditions: meta.conditions || null,
|
|
59
|
+
measurements: sorted,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Canonical serialization — stable so an unchanged run produces no diff. */
|
|
64
|
+
export function serializeRecord(doc) {
|
|
65
|
+
return `${JSON.stringify(doc, null, 4)}\n`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function argValue(args, flag) {
|
|
69
|
+
const i = args.indexOf(flag);
|
|
70
|
+
return i >= 0 ? args[i + 1] : undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function main(args = argv.slice(2)) {
|
|
74
|
+
const measurementsPath = argValue(args, '--measurements');
|
|
75
|
+
if (measurementsPath === undefined) {
|
|
76
|
+
process.stderr.write(
|
|
77
|
+
'usage: record_evaluator_measurements --measurements <file.json> ' +
|
|
78
|
+
'[--out <file.json>] [--sha <sha>] [--run-url <url>] [--conditions <text>]\n',
|
|
79
|
+
);
|
|
80
|
+
return 2;
|
|
81
|
+
}
|
|
82
|
+
const out = resolve(argValue(args, '--out') ?? RECORD_REL);
|
|
83
|
+
let measurements;
|
|
84
|
+
try {
|
|
85
|
+
measurements = JSON.parse(readFileSync(resolve(measurementsPath), 'utf8'));
|
|
86
|
+
} catch (e) {
|
|
87
|
+
process.stderr.write(`record_evaluator_measurements: ${e.message}\n`);
|
|
88
|
+
return 2;
|
|
89
|
+
}
|
|
90
|
+
const doc = buildRecord(measurements, {
|
|
91
|
+
sha: argValue(args, '--sha'),
|
|
92
|
+
runUrl: argValue(args, '--run-url'),
|
|
93
|
+
conditions: argValue(args, '--conditions'),
|
|
94
|
+
});
|
|
95
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
96
|
+
writeFileSync(out, serializeRecord(doc));
|
|
97
|
+
stdout.write(
|
|
98
|
+
`recorded ${Object.keys(doc.measurements).length} measurement(s) → ${out}\n`,
|
|
99
|
+
);
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (process.argv[1] !== undefined && resolve(process.argv[1]).endsWith('record_evaluator_measurements.mjs')) {
|
|
104
|
+
exit(main());
|
|
105
|
+
}
|
|
@@ -107,7 +107,7 @@ fi
|
|
|
107
107
|
# exists. /tmp/agent-config-ci-start.txt is written by _ci-start
|
|
108
108
|
# at the start of every 'task ci' run; /tmp/agent-config-ci-end.txt
|
|
109
109
|
# by _ci-end on success. Pre-flight passes when both exist AND
|
|
110
|
-
# end > start AND no
|
|
110
|
+
# end > start AND no src/ file is newer than end.
|
|
111
111
|
START_MARKER="/tmp/agent-config-ci-start.txt"
|
|
112
112
|
END_MARKER="/tmp/agent-config-ci-end.txt"
|
|
113
113
|
if [ ! -f "$START_MARKER" ] || [ ! -f "$END_MARKER" ]; then
|
package/src/scripts/release.ts
CHANGED
|
@@ -169,6 +169,8 @@ class CalledProcessError extends Error {
|
|
|
169
169
|
// _lib/ and install.ts's REPO_ROOT computation).
|
|
170
170
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
171
171
|
const PACKAGE_JSON = path.join(REPO_ROOT, 'package.json');
|
|
172
|
+
// Bumped alongside package.json — see set_lockfile_version for why.
|
|
173
|
+
const PACKAGE_LOCK_JSON = path.join(REPO_ROOT, 'package-lock.json');
|
|
172
174
|
const MARKETPLACE_JSON = path.join(REPO_ROOT, '.claude-plugin', 'marketplace.json');
|
|
173
175
|
// Source-of-truth project-settings template. Carries an `agent_config_version`
|
|
174
176
|
// pin that check_template_pin_drift requires to equal package.json.version. We
|
|
@@ -562,6 +564,65 @@ function git(args: readonly string[], opts: { capture?: boolean } = {}): string
|
|
|
562
564
|
return capture ? r.stdout.trim() : '';
|
|
563
565
|
}
|
|
564
566
|
|
|
567
|
+
/**
|
|
568
|
+
* One name per failing check, from `gh pr checks --json name,bucket` output.
|
|
569
|
+
*
|
|
570
|
+
* Pure over the JSON text so the shape is testable without gh. Returns []
|
|
571
|
+
* when the payload is unparseable or nothing sits in the `fail` bucket —
|
|
572
|
+
* the caller then falls back to the raw watch output alone.
|
|
573
|
+
*/
|
|
574
|
+
export function _failed_check_names(jsonText: string): string[] {
|
|
575
|
+
let parsed: unknown;
|
|
576
|
+
try {
|
|
577
|
+
parsed = JSON.parse(jsonText);
|
|
578
|
+
} catch {
|
|
579
|
+
return [];
|
|
580
|
+
}
|
|
581
|
+
if (!Array.isArray(parsed)) {
|
|
582
|
+
return [];
|
|
583
|
+
}
|
|
584
|
+
const names: string[] = [];
|
|
585
|
+
for (const entry of parsed) {
|
|
586
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
const e = entry as Record<string, unknown>;
|
|
590
|
+
if (e['bucket'] === 'fail' && typeof e['name'] === 'string') {
|
|
591
|
+
names.push(e['name']);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return names;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Remediation lines for a set of failing check names.
|
|
599
|
+
*
|
|
600
|
+
* The watch table scrolls failures out of view on a busy PR, so the operator
|
|
601
|
+
* repeatedly saw only `pass`/`skipping` rows plus "PR checks failed" — the
|
|
602
|
+
* 9.14.0 failure mode, twice. Name the red checks explicitly and, for the
|
|
603
|
+
* shape detector, say where the fix belongs (main, never the release branch).
|
|
604
|
+
*/
|
|
605
|
+
export function _failed_checks_report(names: readonly string[]): string {
|
|
606
|
+
if (names.length === 0) {
|
|
607
|
+
return '';
|
|
608
|
+
}
|
|
609
|
+
const lines: string[] = ['', 'Failing check(s):'];
|
|
610
|
+
for (const name of names) {
|
|
611
|
+
lines.push(` ❌ ${name}`);
|
|
612
|
+
}
|
|
613
|
+
if (names.includes('Release-PR shape detector')) {
|
|
614
|
+
lines.push(
|
|
615
|
+
'',
|
|
616
|
+
'Release-PR shape: a release PR may only contain the version-bump',
|
|
617
|
+
'allowlist. Land the out-of-shape files on main via their own PR, then',
|
|
618
|
+
'merge main into the release branch — their release-PR diff becomes',
|
|
619
|
+
'empty (docs/contracts/release-pr-gating.md § Mid-release fixes).',
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
lines.push('', 'After fixing, resume with: task release -- --resume --yes', '');
|
|
623
|
+
return lines.join('\n');
|
|
624
|
+
}
|
|
625
|
+
|
|
565
626
|
/**
|
|
566
627
|
* Watch PR checks and tolerate the 'no checks' case.
|
|
567
628
|
*
|
|
@@ -606,6 +667,15 @@ function watch_pr_checks(): void {
|
|
|
606
667
|
if (output) {
|
|
607
668
|
process.stderr.write(output + '\n');
|
|
608
669
|
}
|
|
670
|
+
const summary = spawnSync('gh', ['pr', 'checks', '--json', 'name,bucket'], {
|
|
671
|
+
cwd: REPO_ROOT,
|
|
672
|
+
encoding: 'utf-8',
|
|
673
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
674
|
+
});
|
|
675
|
+
const report = _failed_checks_report(_failed_check_names(summary.stdout ?? ''));
|
|
676
|
+
if (report) {
|
|
677
|
+
process.stderr.write(report + '\n');
|
|
678
|
+
}
|
|
609
679
|
die(`PR checks failed (exit ${returncode})`);
|
|
610
680
|
}
|
|
611
681
|
|
|
@@ -1064,6 +1134,34 @@ function set_package_version(p: string, version: string): void {
|
|
|
1064
1134
|
fs.writeFileSync(p, jsonDumpsIndent(data, 4) + '\n', 'utf-8');
|
|
1065
1135
|
}
|
|
1066
1136
|
|
|
1137
|
+
/**
|
|
1138
|
+
* Update BOTH version fields npm keeps in a lockfile — the top-level one and
|
|
1139
|
+
* the root package entry (`packages[""]`).
|
|
1140
|
+
*
|
|
1141
|
+
* The bump previously touched package.json and left the lock behind, so every
|
|
1142
|
+
* release shipped a `main` whose two files disagreed and every subsequent
|
|
1143
|
+
* local `npm install` produced a spurious modification (measured 2026-08-02:
|
|
1144
|
+
* package.json 9.13.0 vs package-lock.json 9.12.0). Rewriting the two fields
|
|
1145
|
+
* rather than shelling out to `npm install --package-lock-only` keeps the bump
|
|
1146
|
+
* offline and cannot re-resolve a dependency mid-release.
|
|
1147
|
+
* road-to-gates-that-can-fail Phase 5.
|
|
1148
|
+
*/
|
|
1149
|
+
function set_lockfile_version(p: string, version: string): void {
|
|
1150
|
+
if (!fs.existsSync(p)) {
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
const data = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, unknown>;
|
|
1154
|
+
data['version'] = version;
|
|
1155
|
+
const packages = data['packages'];
|
|
1156
|
+
if (typeof packages === 'object' && packages !== null && !Array.isArray(packages)) {
|
|
1157
|
+
const root = (packages as Record<string, unknown>)[''];
|
|
1158
|
+
if (typeof root === 'object' && root !== null && !Array.isArray(root)) {
|
|
1159
|
+
(root as Record<string, unknown>)['version'] = version;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
fs.writeFileSync(p, jsonDumpsIndent(data, 4) + '\n', 'utf-8');
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1067
1165
|
/** Update `metadata.version`; preserve 2-space indentation + UTF-8. */
|
|
1068
1166
|
function set_marketplace_version(p: string, version: string): void {
|
|
1069
1167
|
const data = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, unknown>;
|
|
@@ -1442,8 +1540,13 @@ function execute(
|
|
|
1442
1540
|
if (resume && current_pkg === plan.target) {
|
|
1443
1541
|
_step(2, total, `Files already at ${plan.target} — skip bump`);
|
|
1444
1542
|
} else {
|
|
1445
|
-
_step(
|
|
1543
|
+
_step(
|
|
1544
|
+
2,
|
|
1545
|
+
total,
|
|
1546
|
+
'Bump package.json + package-lock.json + marketplace.json + template pin, prepend CHANGELOG',
|
|
1547
|
+
);
|
|
1446
1548
|
set_package_version(PACKAGE_JSON, plan.target);
|
|
1549
|
+
set_lockfile_version(PACKAGE_LOCK_JSON, plan.target);
|
|
1447
1550
|
set_marketplace_version(MARKETPLACE_JSON, plan.target);
|
|
1448
1551
|
set_template_pin(PROJECT_TEMPLATE, plan.target);
|
|
1449
1552
|
prepend_changelog(CHANGELOG, plan.changelog_entry);
|
|
@@ -2135,6 +2238,7 @@ export {
|
|
|
2135
2238
|
_cap_body,
|
|
2136
2239
|
prepend_changelog,
|
|
2137
2240
|
set_package_version,
|
|
2241
|
+
set_lockfile_version,
|
|
2138
2242
|
set_marketplace_version,
|
|
2139
2243
|
set_template_pin,
|
|
2140
2244
|
resolve_bump,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Type declarations for router_target_paths.mjs (the shared kind→path table). */
|
|
2
|
+
export declare const ROUTE_TARGET_TEMPLATES: Readonly<Record<string, readonly string[]>>;
|
|
3
|
+
export declare function parseRouteTarget(target: string): { kind: string; id: string } | null;
|
|
4
|
+
export declare function routeTargetPathsPosix(target: string): string[];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* router_target_paths.mjs — the ONE kind→path table for `dist/router.json`
|
|
3
|
+
* `routes_to` targets.
|
|
4
|
+
*
|
|
5
|
+
* Two consumers read it and they must not disagree:
|
|
6
|
+
* * `src/scripts/_cli/cmd_conformance.ts::routeTargetPaths` — resolves a
|
|
7
|
+
* pointer against the INSTALLED package tree at runtime.
|
|
8
|
+
* * `src/scripts/prepack-check.mjs` gate 4 — asserts the same pointer lands
|
|
9
|
+
* inside the `files[]` whitelist BEFORE the tarball is built.
|
|
10
|
+
*
|
|
11
|
+
* A copied table would let one side ship a target the other cannot see, which
|
|
12
|
+
* is exactly the packaging↔runtime gap the pack gate exists to close
|
|
13
|
+
* (road-to-gates-that-can-fail Phase 4). Plain `.mjs` because `prepack-check`
|
|
14
|
+
* runs as raw Node during the npm lifecycle and cannot load TypeScript; the
|
|
15
|
+
* TS side reads the sibling `router_target_paths.d.mts` declarations. Same
|
|
16
|
+
* shape as `prepack_lifecycle_check.mjs`.
|
|
17
|
+
*
|
|
18
|
+
* Templates are POSIX-relative with a single `{id}` placeholder. Callers that
|
|
19
|
+
* need platform separators split on `/` and `path.join` the segments.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Candidate homes per target kind, in resolution order — the FIRST existing
|
|
24
|
+
* candidate wins.
|
|
25
|
+
*
|
|
26
|
+
* `contract:` has two legitimate homes in the shipped tree: the public
|
|
27
|
+
* contract pages under `docs/contracts/` (per the rule-router contract) and
|
|
28
|
+
* the agent-facing contract contexts under
|
|
29
|
+
* `dist/agent-src/contexts/contracts/` (e.g. artifact-engagement-flow).
|
|
30
|
+
*/
|
|
31
|
+
export const ROUTE_TARGET_TEMPLATES = Object.freeze({
|
|
32
|
+
skill: Object.freeze(['dist/agent-src/skills/{id}/SKILL.md']),
|
|
33
|
+
command: Object.freeze(['dist/agent-src/commands/{id}.md']),
|
|
34
|
+
guideline: Object.freeze(['docs/guidelines/{id}.md']),
|
|
35
|
+
contract: Object.freeze([
|
|
36
|
+
'docs/contracts/{id}.md',
|
|
37
|
+
'dist/agent-src/contexts/contracts/{id}.md',
|
|
38
|
+
]),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Split a `<kind>:<id>` target. Returns `null` for a malformed target (no
|
|
43
|
+
* colon, empty kind, empty id, or an unknown kind).
|
|
44
|
+
*
|
|
45
|
+
* @param {string} target
|
|
46
|
+
* @returns {{ kind: string, id: string } | null}
|
|
47
|
+
*/
|
|
48
|
+
export function parseRouteTarget(target) {
|
|
49
|
+
const sep = target.indexOf(':');
|
|
50
|
+
if (sep <= 0) return null;
|
|
51
|
+
const kind = target.slice(0, sep);
|
|
52
|
+
const id = target.slice(sep + 1);
|
|
53
|
+
if (!id) return null;
|
|
54
|
+
if (!Object.prototype.hasOwnProperty.call(ROUTE_TARGET_TEMPLATES, kind)) return null;
|
|
55
|
+
return { kind, id };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* POSIX package-relative candidate paths for one `routes_to` target.
|
|
60
|
+
* Empty array = the target is unparseable or its kind is unknown.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} target
|
|
63
|
+
* @returns {string[]}
|
|
64
|
+
*/
|
|
65
|
+
export function routeTargetPathsPosix(target) {
|
|
66
|
+
const parsed = parseRouteTarget(target);
|
|
67
|
+
if (parsed === null) return [];
|
|
68
|
+
return ROUTE_TARGET_TEMPLATES[parsed.kind].map((tpl) => tpl.replace('{id}', parsed.id));
|
|
69
|
+
}
|