@event4u/agent-config 9.16.0 → 9.18.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/AGENTS.md +1 -1
- package/CHANGELOG.md +80 -130
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +100 -48
- package/dist/agent-src/commands/challenge-me/vision.md +5 -0
- package/dist/agent-src/commands/commit.md +1 -1
- package/dist/agent-src/commands/condense.md +19 -64
- package/dist/agent-src/commands/evals/agent-handoff.json +13 -1
- package/dist/agent-src/commands/evals/rule-compliance-audit.json +46 -0
- package/dist/agent-src/commands/feature/plan.md +20 -0
- package/dist/agent-src/commands/feature/roadmap.md +19 -0
- package/dist/agent-src/commands/memory/promote.md +14 -1
- package/dist/agent-src/commands/mode.md +9 -5
- package/dist/agent-src/commands/optimize/deep.md +72 -11
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/roadmap/create.md +29 -0
- package/dist/agent-src/commands/rule-compliance-audit.md +28 -5
- package/dist/agent-src/contexts/authority/commit-mechanics.md +5 -5
- package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +4 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +27 -1
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +133 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +5 -2
- package/dist/agent-src/profiles/agency.yml +3 -3
- package/dist/agent-src/profiles/content_creator.yml +2 -2
- package/dist/agent-src/profiles/developer.yml +2 -2
- package/dist/agent-src/profiles/finance.yml +1 -1
- package/dist/agent-src/profiles/founder.yml +2 -2
- package/dist/agent-src/profiles/ops.yml +2 -2
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/architecture.md +4 -2
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/brand-consistency.md +10 -62
- package/dist/agent-src/rules/brand-source-of-truth.md +62 -11
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/cli-output-handling.md +5 -0
- package/dist/agent-src/rules/code-comment-discipline.md +3 -0
- package/dist/agent-src/rules/commit-conventions.md +2 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -2
- package/dist/agent-src/rules/cross-source-consistency.md +3 -0
- package/dist/agent-src/rules/design-fidelity.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
- package/dist/agent-src/rules/docker-commands.md +4 -0
- package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +5 -2
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +9 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +4 -0
- package/dist/agent-src/rules/improve-before-implement.md +4 -0
- package/dist/agent-src/rules/laravel-routing.md +4 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
- package/dist/agent-src/rules/media-governance-routing.md +5 -0
- package/dist/agent-src/rules/minimal-safe-diff.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/output-discipline.md +9 -2
- package/dist/agent-src/rules/php-coding.md +2 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +3 -0
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +5 -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/rule-type-governance.md +2 -0
- package/dist/agent-src/rules/scale-discipline.md +3 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +9 -2
- package/dist/agent-src/rules/senior-engineering-discipline.md +6 -0
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +4 -0
- package/dist/agent-src/rules/source-discovery-gate.md +3 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +2 -0
- package/dist/agent-src/rules/think-before-action.md +5 -0
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/rules/ui-audit-gate.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +3 -4
- package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +4 -4
- package/dist/agent-src/skills/copilot-config/SKILL.md +1 -1
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +7 -4
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +6 -180
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +100 -0
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +91 -0
- package/dist/agent-src/skills/design-review/SKILL.md +4 -141
- package/dist/agent-src/skills/design-review/references/review-communication.md +92 -0
- package/dist/agent-src/skills/design-review/references/verification-automation.md +61 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -27
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +31 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +4 -289
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +227 -0
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +75 -0
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +2 -1
- package/dist/agent-src/skills/roadmap-management/SKILL.md +10 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +12 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +4 -2
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +2 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +6 -3
- package/dist/agent-src/templates/agent-settings.md +13 -15
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +6 -2
- package/dist/agent-src/templates/persona.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +13 -1
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-AIIUU73N.js +2040 -0
- package/dist/cli-delegate/{chunk-ZXXJLL5K.js → chunk-BSLUHV2F.js} +127 -1487
- package/dist/cli-delegate/{chunk-H574KOUH.js → chunk-ELMFOQPW.js} +35 -1
- package/dist/cli-delegate/chunk-LF2KKJ4Q.js +183 -0
- package/dist/cli-delegate/chunk-VSYT7OHO.js +1382 -0
- package/dist/cli-delegate/chunk-XGA2NTU4.js +3727 -0
- package/dist/cli-delegate/cmd_conformance.js +4 -3
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -2
- package/dist/cli-delegate/cmd_explain.js +36 -36
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +1169 -0
- package/dist/cli-delegate/cmd_memory_get.js +35 -3754
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +249 -0
- package/dist/cli-delegate/cmd_route_explain.js +285 -0
- 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_update.js +3 -3
- package/dist/cli-delegate/cmd_upgrade.js +3 -3
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +3 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +84 -84
- 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 +602 -507
- package/dist/install/install.mjs +34 -0
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +25 -3
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +39 -6
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/server/schemas/settings.js +25 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/guidelines/abstraction-thresholds.md +53 -0
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -1
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +7 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +2 -2
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +5 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +8 -2
- package/docs/guidelines/component-oriented-and-oop-development.md +11 -6
- package/docs/guidelines/docs/readme-size-and-splitting.md +5 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/src/config/agent-settings.template.yml +68 -0
- package/src/config/evaluator-budgets.json +8 -11
- package/src/config/gate-coverage.yml +70 -0
- package/src/scripts/_cli/cmd_explain.ts +41 -36
- package/src/scripts/_cli/cmd_handoff.ts +405 -0
- package/src/scripts/_cli/cmd_route_audit.ts +290 -0
- package/src/scripts/_cli/cmd_route_explain.ts +269 -0
- package/src/scripts/_cli/handoff_generate.ts +453 -0
- package/src/scripts/_cli/handoff_sessions.ts +435 -0
- package/src/scripts/_dispatch.bash +32 -0
- package/src/scripts/_lib/agent_src.ts +36 -6
- package/src/scripts/_lib/git_env.ts +40 -0
- package/src/scripts/_lib/md_table.ts +27 -0
- package/src/scripts/_lib/planning_settings.ts +43 -0
- package/src/scripts/_lib/release_material.ts +156 -0
- package/src/scripts/_lib/router_match.ts +301 -0
- package/src/scripts/annotate_r1_outcomes.ts +258 -0
- package/src/scripts/check_completion_review.ts +1140 -0
- package/src/scripts/check_condensation.ts +2 -1
- package/src/scripts/check_finding_dispositions.ts +278 -0
- package/src/scripts/check_pack_size.ts +4 -3
- package/src/scripts/check_references.ts +1 -0
- package/src/scripts/check_release_highlights.ts +300 -0
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_release_surface_equality.ts +132 -0
- package/src/scripts/check_reply_consistency.ts +187 -138
- package/src/scripts/compile_router.ts +20 -3
- package/src/scripts/dispatch_r2_reviewer.ts +968 -0
- package/src/scripts/eval_ui_triviality.ts +156 -0
- package/src/scripts/handoff_context_hook.ts +148 -0
- package/src/scripts/hook_manifest.yaml +17 -7
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/lint_abstraction_thresholds.ts +327 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +931 -0
- package/src/scripts/lint_profile_personas.ts +153 -0
- package/src/scripts/lint_token_budget_discipline.ts +148 -0
- package/src/scripts/lint_trigger_collisions.ts +257 -0
- package/src/scripts/release.ts +156 -32
- package/src/scripts/release_drill.ts +491 -0
- package/src/scripts/router_telemetry.ts +16 -290
- package/src/scripts/schemas/command.schema.json +33 -0
- package/src/scripts/schemas/rule.schema.json +10 -0
- package/src/scripts/self_review_gate.ts +41 -3
- package/src/scripts/skill_linter.ts +3 -1
- package/src/scripts/smoke/router.sh +1 -1
- package/src/scripts/update_counts.ts +60 -12
- package/src/server/schemas/settings.ts +41 -0
- package/dist/cli-delegate/{chunk-XX6TOPD7.js → chunk-WR6GTRHJ.js} +3 -3
package/src/scripts/release.ts
CHANGED
|
@@ -118,6 +118,12 @@ import {
|
|
|
118
118
|
perform_split,
|
|
119
119
|
plan_split,
|
|
120
120
|
} from './_lib/changelog_eras.js';
|
|
121
|
+
import {
|
|
122
|
+
extract_changelog_section,
|
|
123
|
+
pr_body_from_section,
|
|
124
|
+
release_notes_from_section,
|
|
125
|
+
tag_message_from_section,
|
|
126
|
+
} from './_lib/release_material.js';
|
|
121
127
|
|
|
122
128
|
// `__doc__.splitlines()[0]` in `_parse_args` — the argparse description. Kept
|
|
123
129
|
// as a referenceable constant so the first docstring line is preserved exactly.
|
|
@@ -517,6 +523,22 @@ interface RunResult {
|
|
|
517
523
|
* stderr so release preflight failures are diagnosable without re-running with
|
|
518
524
|
* a debugger.
|
|
519
525
|
*/
|
|
526
|
+
/**
|
|
527
|
+
* Drill/test seam — when set, every external command run() would spawn is
|
|
528
|
+
* answered by this function instead. The check/die/CalledProcessError
|
|
529
|
+
* semantics of run() still apply to the simulated result, so the drill
|
|
530
|
+
* exercises the REAL error paths of the orchestration (release_drill.ts).
|
|
531
|
+
*/
|
|
532
|
+
type ExecOverride = (args: readonly string[]) => {
|
|
533
|
+
status: number;
|
|
534
|
+
stdout: string;
|
|
535
|
+
stderr: string;
|
|
536
|
+
};
|
|
537
|
+
let _exec_override: ExecOverride | null = null;
|
|
538
|
+
function _set_exec_override(fn: ExecOverride | null): void {
|
|
539
|
+
_exec_override = fn;
|
|
540
|
+
}
|
|
541
|
+
|
|
520
542
|
function run(
|
|
521
543
|
args: readonly string[],
|
|
522
544
|
opts: { check?: boolean; capture?: boolean; cwd?: string | null } = {},
|
|
@@ -526,13 +548,15 @@ function run(
|
|
|
526
548
|
const cwd = opts.cwd ?? REPO_ROOT;
|
|
527
549
|
|
|
528
550
|
const [cmd, ...rest] = args;
|
|
529
|
-
const res =
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
551
|
+
const res = _exec_override
|
|
552
|
+
? { ..._exec_override(args), error: undefined as Error | undefined }
|
|
553
|
+
: spawnSync(cmd as string, rest, {
|
|
554
|
+
cwd,
|
|
555
|
+
encoding: 'utf-8',
|
|
556
|
+
// capture_output=True → pipe; else inherit so child writes straight to
|
|
557
|
+
// this process's stdout/stderr (text mode, matching subprocess text=True).
|
|
558
|
+
stdio: capture ? ['ignore', 'pipe', 'pipe'] : ['inherit', 'inherit', 'inherit'],
|
|
559
|
+
});
|
|
536
560
|
|
|
537
561
|
if (res.error) {
|
|
538
562
|
// FileNotFoundError analogue (ENOENT) and other spawn failures — Python
|
|
@@ -619,6 +643,31 @@ export function _failed_checks_report(names: readonly string[]): string {
|
|
|
619
643
|
'empty (docs/contracts/release-pr-gating.md § Mid-release fixes).',
|
|
620
644
|
);
|
|
621
645
|
}
|
|
646
|
+
if (names.includes('PR body equals CHANGELOG entry')) {
|
|
647
|
+
lines.push(
|
|
648
|
+
'',
|
|
649
|
+
'Surface equality: the PR body drifted from the CHANGELOG entry. A',
|
|
650
|
+
'resume run refreshes it from the branch head (release-truth Phase 1);',
|
|
651
|
+
'never hand-edit the PR body away from the changelog section.',
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
if (names.includes('Curated highlights plausible against the span')) {
|
|
655
|
+
lines.push(
|
|
656
|
+
'',
|
|
657
|
+
'Highlights: a curated `_none_` field contradicts the release span.',
|
|
658
|
+
'Fill the curated head in CHANGELOG.md on the release branch — the',
|
|
659
|
+
'gate output lists the deriving commits (release-truth Phase 2).',
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
if (names.includes('Blocking review findings dispositioned')) {
|
|
663
|
+
lines.push(
|
|
664
|
+
'',
|
|
665
|
+
'Dispositions: a blocking/high self-review finding has no committed',
|
|
666
|
+
'disposition. Ingest + adjudicate it in',
|
|
667
|
+
'agents/evidence/release-findings/<version>.json (release-truth Phase 3):',
|
|
668
|
+
' ./scripts-run src/scripts/check_finding_dispositions --ingest <findings.json>',
|
|
669
|
+
);
|
|
670
|
+
}
|
|
622
671
|
lines.push('', 'After fixing, resume with: task release -- --resume --yes', '');
|
|
623
672
|
return lines.join('\n');
|
|
624
673
|
}
|
|
@@ -635,24 +684,24 @@ export function _failed_checks_report(names: readonly string[]): string {
|
|
|
635
684
|
* freshly-pushed branch.
|
|
636
685
|
*/
|
|
637
686
|
function watch_pr_checks(branch: string): void {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
//
|
|
687
|
+
if (_exec_override === null) {
|
|
688
|
+
// time.sleep(5) — blocking grace period for GitHub to register runs
|
|
689
|
+
// on a freshly-pushed branch. Skipped under the drill seam: there is
|
|
690
|
+
// no GitHub to wait for, and 5s per simulated wait adds up.
|
|
691
|
+
const until = Date.now() + 5000;
|
|
692
|
+
while (Date.now() < until) {
|
|
693
|
+
// busy-wait stand-in for time.sleep(5) without an event-loop yield.
|
|
694
|
+
}
|
|
642
695
|
}
|
|
643
696
|
// The branch is passed explicitly — `gh` inferring the PR from HEAD
|
|
644
697
|
// resolved to `main` mid-run once (2026-08-03, 9.16.0 resume) and the
|
|
645
698
|
// whole release died on "no pull requests found for branch main".
|
|
646
|
-
const proc =
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
699
|
+
const proc = run(['gh', 'pr', 'checks', branch, '--watch'], {
|
|
700
|
+
check: false,
|
|
701
|
+
capture: true,
|
|
650
702
|
});
|
|
651
|
-
if (proc.error) {
|
|
652
|
-
throw proc.error;
|
|
653
|
-
}
|
|
654
703
|
const output = ((proc.stdout || '') + (proc.stderr || '')).trim();
|
|
655
|
-
const returncode = proc.
|
|
704
|
+
const returncode = proc.returncode;
|
|
656
705
|
if (returncode === 0) {
|
|
657
706
|
if (output) {
|
|
658
707
|
process.stdout.write(output + '\n');
|
|
@@ -670,10 +719,9 @@ function watch_pr_checks(branch: string): void {
|
|
|
670
719
|
if (output) {
|
|
671
720
|
process.stderr.write(output + '\n');
|
|
672
721
|
}
|
|
673
|
-
const summary =
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
722
|
+
const summary = run(['gh', 'pr', 'checks', branch, '--json', 'name,bucket'], {
|
|
723
|
+
check: false,
|
|
724
|
+
capture: true,
|
|
677
725
|
});
|
|
678
726
|
const report = _failed_checks_report(_failed_check_names(summary.stdout ?? ''));
|
|
679
727
|
if (report) {
|
|
@@ -734,11 +782,45 @@ const _MERGE_UPDATE_ROUNDS = 3;
|
|
|
734
782
|
* version-bump allowlist (docs/contracts/release-pr-gating.md § Mid-release
|
|
735
783
|
* fixes) — do it here instead of aborting the run.
|
|
736
784
|
*/
|
|
785
|
+
/**
|
|
786
|
+
* Re-derive the release-PR body from the CHANGELOG section at the current
|
|
787
|
+
* release-branch head and push it to the PR (release-truth Phase 1: one
|
|
788
|
+
* final source — late commits and maintainer edits on the branch must reach
|
|
789
|
+
* the PR body instead of leaving it frozen at plan time). Best-effort sync
|
|
790
|
+
* of the local branch first; a no-op when the derived body is unchanged.
|
|
791
|
+
*/
|
|
792
|
+
function _target_from_branch(branch: string): string {
|
|
793
|
+
return branch.replace(/^release\//u, '');
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
function _refresh_pr_body_from_head(branch: string, target: string): void {
|
|
797
|
+
run(['git', 'pull', '--ff-only', REMOTE, branch], { check: false });
|
|
798
|
+
const changelog = fs.readFileSync(CHANGELOG, 'utf-8');
|
|
799
|
+
const section = extract_changelog_section(changelog, target);
|
|
800
|
+
if (!section) {
|
|
801
|
+
die(`CHANGELOG.md at ${branch} head carries no section for ${target} — cannot derive PR body`);
|
|
802
|
+
}
|
|
803
|
+
const capped = _cap_body(section!.body, GH_PR_BODY_LIMIT - 200, '`CHANGELOG.md` in this PR');
|
|
804
|
+
const body = pr_body_from_section(capped, target);
|
|
805
|
+
const live = run(['gh', 'pr', 'view', branch, '--json', 'body', '-q', '.body'], {
|
|
806
|
+
check: false,
|
|
807
|
+
capture: true,
|
|
808
|
+
});
|
|
809
|
+
if (live.returncode === 0 && live.stdout.replace(/\r\n/gu, '\n').trim() === body.trim()) {
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
run(['gh', 'pr', 'edit', branch, '--body', body]);
|
|
813
|
+
}
|
|
814
|
+
|
|
737
815
|
function merge_release_pr(branch: string, wait_for_checks: boolean): void {
|
|
738
816
|
if (git(['rev-parse', '--abbrev-ref', 'HEAD'], { capture: true }) !== branch) {
|
|
739
817
|
run(['git', 'checkout', branch]);
|
|
740
818
|
}
|
|
741
819
|
for (let round = 0; round <= _MERGE_UPDATE_ROUNDS; round++) {
|
|
820
|
+
// One final generation step at the final head: every merge attempt
|
|
821
|
+
// first re-derives the PR body from the branch-head CHANGELOG, so
|
|
822
|
+
// update rounds and maintainer edits can never desynchronize it.
|
|
823
|
+
_refresh_pr_body_from_head(branch, _target_from_branch(branch));
|
|
742
824
|
if (_pr_merge_state(branch) !== 'BEHIND') {
|
|
743
825
|
const merged = run(['gh', 'pr', 'merge', branch, '--merge', '--delete-branch'], {
|
|
744
826
|
check: false,
|
|
@@ -1708,18 +1790,27 @@ function execute(
|
|
|
1708
1790
|
if (pr_merged) {
|
|
1709
1791
|
_step(5, total, `PR #${pr_info!['number']} already merged — skip`);
|
|
1710
1792
|
} else if (resume && pr_state === 'OPEN') {
|
|
1711
|
-
|
|
1793
|
+
// One final source: a resumed run re-derives the body from the
|
|
1794
|
+
// branch-head CHANGELOG instead of leaving the plan-time snapshot —
|
|
1795
|
+
// this was the 9.14.0 test-count desync (resume re-rendered from a
|
|
1796
|
+
// later HEAD while the changelog kept the branch's entry).
|
|
1797
|
+
_step(5, total, `PR already open: ${pr_info!['url']} — refresh body from branch head`);
|
|
1798
|
+
_refresh_pr_body_from_head(branch, plan.target);
|
|
1712
1799
|
} else {
|
|
1713
1800
|
_step(5, total, 'Open pull request');
|
|
1801
|
+
// Derive the PR body from the CHANGELOG section step 2 just wrote —
|
|
1802
|
+
// the file is the single source; the in-memory plan is only its
|
|
1803
|
+
// author (release-truth Phase 1).
|
|
1804
|
+
const section = extract_changelog_section(fs.readFileSync(CHANGELOG, 'utf-8'), plan.target);
|
|
1805
|
+
if (!section) {
|
|
1806
|
+
die(`CHANGELOG.md carries no section for ${plan.target} — cannot derive PR body`);
|
|
1807
|
+
}
|
|
1714
1808
|
const pr_changelog = _cap_body(
|
|
1715
|
-
|
|
1809
|
+
section!.body,
|
|
1716
1810
|
GH_PR_BODY_LIMIT - 200, // leave room for the prefix + footer
|
|
1717
1811
|
'`CHANGELOG.md` in this PR',
|
|
1718
1812
|
);
|
|
1719
|
-
const pr_body =
|
|
1720
|
-
`Release ${plan.target}.\n\n` +
|
|
1721
|
-
`${pr_changelog}\n\n` +
|
|
1722
|
-
'Created by `scripts/release.py`.';
|
|
1813
|
+
const pr_body = pr_body_from_section(pr_changelog, plan.target);
|
|
1723
1814
|
run([
|
|
1724
1815
|
'gh',
|
|
1725
1816
|
'pr',
|
|
@@ -1770,8 +1861,21 @@ function execute(
|
|
|
1770
1861
|
run(['git', 'push', REMOTE, plan.target]);
|
|
1771
1862
|
}
|
|
1772
1863
|
} else {
|
|
1773
|
-
|
|
1774
|
-
|
|
1864
|
+
// Sequencing is load-bearing (release-truth Phase 1, council
|
|
1865
|
+
// 2026-08-03): merge FIRST (step 7), pull main (above), THEN derive
|
|
1866
|
+
// the tag message from the MERGED changelog — tagging before the
|
|
1867
|
+
// merge would read a section that does not exist yet. The annotated
|
|
1868
|
+
// tag replaces the previous lightweight one so tag metadata is a
|
|
1869
|
+
// fourth surface carrying the same single-source content.
|
|
1870
|
+
_step(8, total, `Tag merge commit (annotated, from merged CHANGELOG) and push ${plan.target}`);
|
|
1871
|
+
const merged = extract_changelog_section(fs.readFileSync(CHANGELOG, 'utf-8'), plan.target);
|
|
1872
|
+
if (!merged) {
|
|
1873
|
+
die(
|
|
1874
|
+
`CHANGELOG.md on ${MAIN_BRANCH} carries no section for ${plan.target} — ` +
|
|
1875
|
+
'refusing to tag a release whose changelog entry is missing',
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
run(['git', 'tag', '-a', plan.target, '-m', tag_message_from_section(merged!.body, plan.target)]);
|
|
1775
1879
|
run(['git', 'push', REMOTE, plan.target]);
|
|
1776
1880
|
}
|
|
1777
1881
|
|
|
@@ -1786,8 +1890,19 @@ function execute(
|
|
|
1786
1890
|
? 'Create GitHub Release (tag push under GITHUB_TOKEN triggers nothing — dispatching next)'
|
|
1787
1891
|
: 'Create GitHub Release (triggers publish-npm on the tag)',
|
|
1788
1892
|
);
|
|
1893
|
+
// One final source: the notes come from the CHANGELOG as recorded AT
|
|
1894
|
+
// THE TAG — never from the plan-time render (whose scope can differ
|
|
1895
|
+
// from the merged content; that was the 9.14.0 desync).
|
|
1896
|
+
const tagged_changelog = git(['show', `${plan.target}:CHANGELOG.md`], { capture: true });
|
|
1897
|
+
const tagged_section = extract_changelog_section(tagged_changelog, plan.target);
|
|
1898
|
+
if (!tagged_section) {
|
|
1899
|
+
die(
|
|
1900
|
+
`CHANGELOG.md at tag ${plan.target} carries no section for ${plan.target} — ` +
|
|
1901
|
+
'refusing to publish release notes from a different source',
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1789
1904
|
const notes = _cap_body(
|
|
1790
|
-
|
|
1905
|
+
release_notes_from_section(tagged_section!.body, plan.target),
|
|
1791
1906
|
GH_RELEASE_NOTES_LIMIT,
|
|
1792
1907
|
'`CHANGELOG.md`',
|
|
1793
1908
|
);
|
|
@@ -2363,5 +2478,14 @@ export {
|
|
|
2363
2478
|
SEMVER_RE,
|
|
2364
2479
|
_RELEASE_BRANCH_RE,
|
|
2365
2480
|
MODULE_DOC_FIRST_LINE,
|
|
2481
|
+
// Drill seam (release_drill.ts) — the step machinery under a simulated
|
|
2482
|
+
// git/gh world, so orchestration bugs surface in vitest, not mid-release.
|
|
2483
|
+
execute,
|
|
2484
|
+
_set_exec_override,
|
|
2485
|
+
push_release_branch,
|
|
2486
|
+
merge_release_pr,
|
|
2487
|
+
watch_pr_checks,
|
|
2488
|
+
_pr_merge_state,
|
|
2489
|
+
_MERGE_UPDATE_ROUNDS,
|
|
2366
2490
|
};
|
|
2367
2491
|
export type { Args };
|