@event4u/agent-config 9.14.0 → 9.16.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 +118 -99
- package/README.md +8 -0
- 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 +5 -2
- package/dist/agent-src/commands/optimize/skills.md +5 -5
- 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/mcp/content.js +1 -1
- package/dist/cli/mcp/content.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-GCVFLBP2.js → chunk-H574KOUH.js} +338 -494
- 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 +127 -95
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +729 -430
- package/dist/install/install.mjs +52 -11
- package/dist/install/rule_scope.js +18 -2
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +518 -411
- 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 +3 -1
- 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/shared/userMd/utils.js +1 -1
- package/dist/shared/userMd/utils.js.map +1 -1
- package/dist/ui/assets/index-DmR0mbk4.js +26 -0
- package/dist/ui/assets/index-DmR0mbk4.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 +14 -14
- 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 +61 -11
- package/src/config/budget-routing.json +7 -0
- 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/gate_baseline.ts +213 -0
- package/src/scripts/_lib/scoped_projection.ts +50 -0
- package/src/scripts/_lib/tier_budget_routing.ts +360 -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/anchor_scoring_run.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/bench_persona_placebo.ts +1 -1
- package/src/scripts/bench_quality_run.ts +1 -1
- package/src/scripts/build_mcp_catalog.ts +12 -1
- package/src/scripts/check_always_budget.ts +122 -11
- package/src/scripts/check_augment_description_cap.ts +24 -3
- package/src/scripts/check_ci_strict_superset.ts +150 -0
- package/src/scripts/check_cli_registry_budget_sync.ts +168 -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 +338 -2
- 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_quality_golden.ts +1 -1
- package/src/scripts/check_token_regression.ts +9 -2
- package/src/scripts/condense.ts +155 -12
- package/src/scripts/cost/budget.mjs +77 -2
- 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 +2 -2
- 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 +214 -7
- 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 +560 -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 +9 -28
- 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 +1 -1
- 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/src/shared/userMd/utils.ts +1 -1
- 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
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
|
*
|
|
@@ -573,13 +634,16 @@ function git(args: readonly string[], opts: { capture?: boolean } = {}): string
|
|
|
573
634
|
* A short grace period gives GitHub time to register workflow runs on a
|
|
574
635
|
* freshly-pushed branch.
|
|
575
636
|
*/
|
|
576
|
-
function watch_pr_checks(): void {
|
|
637
|
+
function watch_pr_checks(branch: string): void {
|
|
577
638
|
// time.sleep(5) — blocking grace period. Never reached on any test path.
|
|
578
639
|
const until = Date.now() + 5000;
|
|
579
640
|
while (Date.now() < until) {
|
|
580
641
|
// busy-wait stand-in for time.sleep(5) without an event-loop yield.
|
|
581
642
|
}
|
|
582
|
-
|
|
643
|
+
// The branch is passed explicitly — `gh` inferring the PR from HEAD
|
|
644
|
+
// resolved to `main` mid-run once (2026-08-03, 9.16.0 resume) and the
|
|
645
|
+
// whole release died on "no pull requests found for branch main".
|
|
646
|
+
const proc = spawnSync('gh', ['pr', 'checks', branch, '--watch'], {
|
|
583
647
|
cwd: REPO_ROOT,
|
|
584
648
|
encoding: 'utf-8',
|
|
585
649
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -606,9 +670,117 @@ function watch_pr_checks(): void {
|
|
|
606
670
|
if (output) {
|
|
607
671
|
process.stderr.write(output + '\n');
|
|
608
672
|
}
|
|
673
|
+
const summary = spawnSync('gh', ['pr', 'checks', branch, '--json', 'name,bucket'], {
|
|
674
|
+
cwd: REPO_ROOT,
|
|
675
|
+
encoding: 'utf-8',
|
|
676
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
677
|
+
});
|
|
678
|
+
const report = _failed_checks_report(_failed_check_names(summary.stdout ?? ''));
|
|
679
|
+
if (report) {
|
|
680
|
+
process.stderr.write(report + '\n');
|
|
681
|
+
}
|
|
609
682
|
die(`PR checks failed (exit ${returncode})`);
|
|
610
683
|
}
|
|
611
684
|
|
|
685
|
+
/**
|
|
686
|
+
* Push the release branch, integrating a remote that moved under us.
|
|
687
|
+
*
|
|
688
|
+
* A GitHub-side "Update branch" click (or a concurrent resume run) advances
|
|
689
|
+
* `origin/<branch>` while the local ref stays behind; a bare `git push` is
|
|
690
|
+
* then rejected with "fetch first" and the whole release run dies (measured
|
|
691
|
+
* 2026-08-03, 9.15.0). Same-branch commits are never ours to drop, so the
|
|
692
|
+
* recovery is merge-and-retry, never force-push.
|
|
693
|
+
*/
|
|
694
|
+
function push_release_branch(branch: string): void {
|
|
695
|
+
const first = run(['git', 'push', '-u', REMOTE, branch], { check: false });
|
|
696
|
+
if (first.returncode === 0) {
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
process.stdout.write(`↻ ${REMOTE}/${branch} moved — integrating and retrying push\n`);
|
|
700
|
+
run(['git', 'fetch', REMOTE, branch]);
|
|
701
|
+
run(['git', 'merge', '--no-edit', `${REMOTE}/${branch}`]);
|
|
702
|
+
run(['git', 'push', '-u', REMOTE, branch]);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/** mergeStateStatus of the branch's PR ('' when the probe fails). */
|
|
706
|
+
function _pr_merge_state(branch: string): string {
|
|
707
|
+
const r = run(
|
|
708
|
+
['gh', 'pr', 'view', branch, '--json', 'mergeStateStatus', '--jq', '.mergeStateStatus'],
|
|
709
|
+
{
|
|
710
|
+
check: false,
|
|
711
|
+
capture: true,
|
|
712
|
+
},
|
|
713
|
+
);
|
|
714
|
+
return r.returncode === 0 ? r.stdout.trim() : '';
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Bound on update-and-retry rounds in merge_release_pr. Three is deliberate:
|
|
719
|
+
* main receiving unrelated merges three times inside one checks-wait window
|
|
720
|
+
* means the queue is hot and a human should decide, not a loop.
|
|
721
|
+
*/
|
|
722
|
+
const _MERGE_UPDATE_ROUNDS = 3;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Merge the release PR, absorbing a moving base branch.
|
|
726
|
+
*
|
|
727
|
+
* Branch protection requires the head to be up to date with `main`, and
|
|
728
|
+
* `main` moves constantly (dependabot, unrelated merges) — so between the
|
|
729
|
+
* checks-wait and the merge the PR routinely flips to BEHIND and a bare
|
|
730
|
+
* `gh pr merge` dies with "the head branch is not up to date with the base
|
|
731
|
+
* branch" (measured 2026-08-03, 9.16.0). Recovery is mechanical and safe by
|
|
732
|
+
* construction: merging `origin/main` into `release/X.Y.Z` makes the fix
|
|
733
|
+
* files identical on both sides, so the release-PR diff stays inside the
|
|
734
|
+
* version-bump allowlist (docs/contracts/release-pr-gating.md § Mid-release
|
|
735
|
+
* fixes) — do it here instead of aborting the run.
|
|
736
|
+
*/
|
|
737
|
+
function merge_release_pr(branch: string, wait_for_checks: boolean): void {
|
|
738
|
+
if (git(['rev-parse', '--abbrev-ref', 'HEAD'], { capture: true }) !== branch) {
|
|
739
|
+
run(['git', 'checkout', branch]);
|
|
740
|
+
}
|
|
741
|
+
for (let round = 0; round <= _MERGE_UPDATE_ROUNDS; round++) {
|
|
742
|
+
if (_pr_merge_state(branch) !== 'BEHIND') {
|
|
743
|
+
const merged = run(['gh', 'pr', 'merge', branch, '--merge', '--delete-branch'], {
|
|
744
|
+
check: false,
|
|
745
|
+
});
|
|
746
|
+
if (merged.returncode === 0) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
if (_pr_merge_state(branch) !== 'BEHIND') {
|
|
750
|
+
// Not the moving-base failure — surface it unchanged.
|
|
751
|
+
throw new CalledProcessError(merged.returncode, [
|
|
752
|
+
'gh',
|
|
753
|
+
'pr',
|
|
754
|
+
'merge',
|
|
755
|
+
branch,
|
|
756
|
+
'--merge',
|
|
757
|
+
'--delete-branch',
|
|
758
|
+
]);
|
|
759
|
+
}
|
|
760
|
+
// BEHIND appeared between the probe and the merge — fall through
|
|
761
|
+
// to the update below.
|
|
762
|
+
}
|
|
763
|
+
if (round === _MERGE_UPDATE_ROUNDS) {
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
process.stdout.write(
|
|
767
|
+
`↻ head behind ${MAIN_BRANCH} (update round ${round + 1}/${_MERGE_UPDATE_ROUNDS}) — ` +
|
|
768
|
+
`merging ${REMOTE}/${MAIN_BRANCH} into ${branch} and re-running checks\n`,
|
|
769
|
+
);
|
|
770
|
+
run(['git', 'fetch', REMOTE, MAIN_BRANCH]);
|
|
771
|
+
run(['git', 'merge', '--no-edit', `${REMOTE}/${MAIN_BRANCH}`]);
|
|
772
|
+
push_release_branch(branch);
|
|
773
|
+
if (wait_for_checks) {
|
|
774
|
+
watch_pr_checks(branch);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
die(
|
|
778
|
+
`release PR is still behind ${MAIN_BRANCH} after ${_MERGE_UPDATE_ROUNDS} update round(s) — ` +
|
|
779
|
+
`${MAIN_BRANCH} is moving faster than the checks complete. ` +
|
|
780
|
+
'Re-run when the queue quiets down: task release -- --resume --yes',
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
|
|
612
784
|
function have(bin: string): boolean {
|
|
613
785
|
const res = spawnSync('which', [bin], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
614
786
|
if (res.error) {
|
|
@@ -1064,6 +1236,34 @@ function set_package_version(p: string, version: string): void {
|
|
|
1064
1236
|
fs.writeFileSync(p, jsonDumpsIndent(data, 4) + '\n', 'utf-8');
|
|
1065
1237
|
}
|
|
1066
1238
|
|
|
1239
|
+
/**
|
|
1240
|
+
* Update BOTH version fields npm keeps in a lockfile — the top-level one and
|
|
1241
|
+
* the root package entry (`packages[""]`).
|
|
1242
|
+
*
|
|
1243
|
+
* The bump previously touched package.json and left the lock behind, so every
|
|
1244
|
+
* release shipped a `main` whose two files disagreed and every subsequent
|
|
1245
|
+
* local `npm install` produced a spurious modification (measured 2026-08-02:
|
|
1246
|
+
* package.json 9.13.0 vs package-lock.json 9.12.0). Rewriting the two fields
|
|
1247
|
+
* rather than shelling out to `npm install --package-lock-only` keeps the bump
|
|
1248
|
+
* offline and cannot re-resolve a dependency mid-release.
|
|
1249
|
+
* road-to-gates-that-can-fail Phase 5.
|
|
1250
|
+
*/
|
|
1251
|
+
function set_lockfile_version(p: string, version: string): void {
|
|
1252
|
+
if (!fs.existsSync(p)) {
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
const data = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, unknown>;
|
|
1256
|
+
data['version'] = version;
|
|
1257
|
+
const packages = data['packages'];
|
|
1258
|
+
if (typeof packages === 'object' && packages !== null && !Array.isArray(packages)) {
|
|
1259
|
+
const root = (packages as Record<string, unknown>)[''];
|
|
1260
|
+
if (typeof root === 'object' && root !== null && !Array.isArray(root)) {
|
|
1261
|
+
(root as Record<string, unknown>)['version'] = version;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
fs.writeFileSync(p, jsonDumpsIndent(data, 4) + '\n', 'utf-8');
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1067
1267
|
/** Update `metadata.version`; preserve 2-space indentation + UTF-8. */
|
|
1068
1268
|
function set_marketplace_version(p: string, version: string): void {
|
|
1069
1269
|
const data = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, unknown>;
|
|
@@ -1442,8 +1642,13 @@ function execute(
|
|
|
1442
1642
|
if (resume && current_pkg === plan.target) {
|
|
1443
1643
|
_step(2, total, `Files already at ${plan.target} — skip bump`);
|
|
1444
1644
|
} else {
|
|
1445
|
-
_step(
|
|
1645
|
+
_step(
|
|
1646
|
+
2,
|
|
1647
|
+
total,
|
|
1648
|
+
'Bump package.json + package-lock.json + marketplace.json + template pin, prepend CHANGELOG',
|
|
1649
|
+
);
|
|
1446
1650
|
set_package_version(PACKAGE_JSON, plan.target);
|
|
1651
|
+
set_lockfile_version(PACKAGE_LOCK_JSON, plan.target);
|
|
1447
1652
|
set_marketplace_version(MARKETPLACE_JSON, plan.target);
|
|
1448
1653
|
set_template_pin(PROJECT_TEMPLATE, plan.target);
|
|
1449
1654
|
prepend_changelog(CHANGELOG, plan.changelog_entry);
|
|
@@ -1493,9 +1698,10 @@ function execute(
|
|
|
1493
1698
|
_step(4, total, 'PR already merged — skip push');
|
|
1494
1699
|
} else {
|
|
1495
1700
|
// `git push -u` is naturally idempotent — it prints "Everything
|
|
1496
|
-
// up-to-date" when remote already matches.
|
|
1701
|
+
// up-to-date" when remote already matches. push_release_branch
|
|
1702
|
+
// additionally absorbs a remote that moved under us.
|
|
1497
1703
|
_step(4, total, `Push ${branch} to ${REMOTE}`);
|
|
1498
|
-
|
|
1704
|
+
push_release_branch(branch);
|
|
1499
1705
|
}
|
|
1500
1706
|
|
|
1501
1707
|
// ─── 5. PR ──────────────────────────────────────────────────────────────
|
|
@@ -1534,7 +1740,7 @@ function execute(
|
|
|
1534
1740
|
_step(6, total, 'PR already merged — skip checks wait');
|
|
1535
1741
|
} else if (wait_for_checks) {
|
|
1536
1742
|
_step(6, total, 'Wait for PR checks');
|
|
1537
|
-
watch_pr_checks();
|
|
1743
|
+
watch_pr_checks(branch);
|
|
1538
1744
|
} else {
|
|
1539
1745
|
_step(6, total, 'Skip waiting for checks (--no-wait)');
|
|
1540
1746
|
}
|
|
@@ -1544,7 +1750,7 @@ function execute(
|
|
|
1544
1750
|
_step(7, total, `PR #${pr_info!['number']} already merged — skip`);
|
|
1545
1751
|
} else {
|
|
1546
1752
|
_step(7, total, 'Merge pull request (merge commit) and delete branch');
|
|
1547
|
-
|
|
1753
|
+
merge_release_pr(branch, wait_for_checks);
|
|
1548
1754
|
}
|
|
1549
1755
|
|
|
1550
1756
|
// ─── 8. tag main + push tag ─────────────────────────────────────────────
|
|
@@ -2135,6 +2341,7 @@ export {
|
|
|
2135
2341
|
_cap_body,
|
|
2136
2342
|
prepend_changelog,
|
|
2137
2343
|
set_package_version,
|
|
2344
|
+
set_lockfile_version,
|
|
2138
2345
|
set_marketplace_version,
|
|
2139
2346
|
set_template_pin,
|
|
2140
2347
|
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
|
+
}
|
|
@@ -183,6 +183,57 @@ function _fnmatch(name: string, pat: string): boolean {
|
|
|
183
183
|
// ── Trigger matching ─────────────────────────────────────────────────────
|
|
184
184
|
|
|
185
185
|
/** Apply one trigger to a prompt + context; return True on match. */
|
|
186
|
+
/** Unicode word character — letters, digits, underscore (incl. umlauts). */
|
|
187
|
+
const _WORD_CHAR = /[\p{L}\p{N}_]/u;
|
|
188
|
+
|
|
189
|
+
function _isWordChar(c: string | undefined): boolean {
|
|
190
|
+
return c !== undefined && _WORD_CHAR.test(c);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Word-boundary-anchored keyword match (road-to-tested-routing Phase 3).
|
|
195
|
+
*
|
|
196
|
+
* A `keyword` occurrence counts only when its word-character edges sit on
|
|
197
|
+
* word boundaries: `ac` no longer fires inside "black", `plan` no longer
|
|
198
|
+
* fires inside "planet". Two deliberate reliefs:
|
|
199
|
+
*
|
|
200
|
+
* - An edge that is itself a NON-word character (e.g. `__()`, `/image:`,
|
|
201
|
+
* `trans(`, an emoji) carries no boundary requirement on that side —
|
|
202
|
+
* punctuation-shaped keywords keep their exact substring semantics.
|
|
203
|
+
* - The right boundary accepts one optional plural `s` ("icons", "options",
|
|
204
|
+
* "secrets" still fire their singular keyword). Richer inflection (German
|
|
205
|
+
* verb endings: "implementiere", "committen") is a DOCUMENTED accepted
|
|
206
|
+
* recall cost of anchoring — the matrices carry standalone-token phrasings
|
|
207
|
+
* for those languages instead.
|
|
208
|
+
*
|
|
209
|
+
* `phrase` deliberately stays unanchored substring; since this change the
|
|
210
|
+
* two trigger kinds genuinely differ.
|
|
211
|
+
*/
|
|
212
|
+
export function keyword_matches_anchored(prompt_lower: string, kw_lower: string): boolean {
|
|
213
|
+
if (kw_lower === "") {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const needLeft = _isWordChar(kw_lower[0]);
|
|
217
|
+
const needRight = _isWordChar(kw_lower[kw_lower.length - 1]);
|
|
218
|
+
let idx = prompt_lower.indexOf(kw_lower);
|
|
219
|
+
while (idx !== -1) {
|
|
220
|
+
const leftOk = !needLeft || !_isWordChar(prompt_lower[idx - 1]);
|
|
221
|
+
let rightOk = true;
|
|
222
|
+
if (needRight) {
|
|
223
|
+
let end = idx + kw_lower.length;
|
|
224
|
+
if (prompt_lower[end] === "s") {
|
|
225
|
+
end += 1; // optional plural `s`
|
|
226
|
+
}
|
|
227
|
+
rightOk = !_isWordChar(prompt_lower[end]);
|
|
228
|
+
}
|
|
229
|
+
if (leftOk && rightOk) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
idx = prompt_lower.indexOf(kw_lower, idx + 1);
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
186
237
|
export function trigger_matches(
|
|
187
238
|
trigger: Trigger,
|
|
188
239
|
prompt: string,
|
|
@@ -191,7 +242,7 @@ export function trigger_matches(
|
|
|
191
242
|
): boolean {
|
|
192
243
|
const prompt_lower = prompt.toLowerCase();
|
|
193
244
|
if ("keyword" in trigger) {
|
|
194
|
-
return prompt_lower
|
|
245
|
+
return keyword_matches_anchored(prompt_lower, String(trigger["keyword"]).toLowerCase());
|
|
195
246
|
}
|
|
196
247
|
if ("phrase" in trigger) {
|
|
197
248
|
return prompt_lower.includes(String(trigger["phrase"]).toLowerCase());
|