@codedrifters/configulator 0.0.414 → 0.0.415

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/lib/index.mjs CHANGED
@@ -5830,6 +5830,58 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS, conventions = DEFAULT_BASE
5830
5830
  }
5831
5831
  var baseBundle = buildBaseBundle();
5832
5832
 
5833
+ // src/agent/bundles/issue-close.ts
5834
+ var ISSUE_CLOSE_SECTION_TITLE = "Issue closing";
5835
+ var ISSUE_CLOSE_RULE_REFERENCE = `per the **${ISSUE_CLOSE_SECTION_TITLE}** rule`;
5836
+ function renderIssueClosePolicySection() {
5837
+ return [
5838
+ `## ${ISSUE_CLOSE_SECTION_TITLE}`,
5839
+ "",
5840
+ "**Never close a phase issue that your PR is going to close for**",
5841
+ "**you.** Most projects put a closing keyword (`Closes #<n>`) in the",
5842
+ "PR body, so the issue closes when the PR merges \u2014 and that merge is",
5843
+ "what drives the documented `status:ready-for-review` \u2192",
5844
+ "`status:done` transition.",
5845
+ "",
5846
+ "Closing the issue yourself at the end of a phase pre-empts all of",
5847
+ "that:",
5848
+ "",
5849
+ "- the PR's `Closes #<n>` line becomes a no-op \u2014 nothing happens at",
5850
+ " merge time;",
5851
+ "- the issue closes while still carrying `status:in-progress` or",
5852
+ " `status:ready-for-review`, so its labels describe a state it has",
5853
+ " already left;",
5854
+ "- any caller that applies a status label afterwards is labelling a",
5855
+ " closed issue, and a caller that verifies workflow state has to",
5856
+ " reopen the issue to put it back in the pipeline.",
5857
+ "",
5858
+ "So whenever a phase step tells you to close its issue, resolve it",
5859
+ "against your project's PR workflow first:",
5860
+ "",
5861
+ "1. **The PR closes it.** Your PR body carries `Closes #<n>` for this",
5862
+ " issue \u2014 commit, push, open the PR, and leave the issue **open**.",
5863
+ " Post the phase outcome the step asks for as an ordinary comment",
5864
+ " on the issue, not as a closing comment, and let the merge perform",
5865
+ " the close.",
5866
+ "2. **The PR does not close it.** There is no closing keyword for",
5867
+ " this issue, or the phase lands no PR at all \u2014 close the issue",
5868
+ " yourself, with the outcome comment the step describes.",
5869
+ "",
5870
+ "### Always close directly",
5871
+ "",
5872
+ "Two cases never wait on a merge:",
5873
+ "",
5874
+ "- **Aborts.** A phase that stops without a deliverable \u2014 nothing",
5875
+ " relevant found, a duplicate, an ambiguity handed off with",
5876
+ " `status:needs-attention` \u2014 closes its issue directly. No PR will",
5877
+ " ever reference it.",
5878
+ "- **Someone else's issue.** Closing an issue other than the one you",
5879
+ " are working (a parent issue your phase resolves, a superseded",
5880
+ " sibling) is bookkeeping, not the workflow close. A closing keyword",
5881
+ " only ever covers the issues your PR body names."
5882
+ ];
5883
+ }
5884
+
5833
5885
  // src/agent/bundles/bcm-writer.ts
5834
5886
  function buildBcmWriterSubAgent(paths, issueDefaults) {
5835
5887
  return {
@@ -6025,7 +6077,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6025
6077
  " branch per your project's branch-naming convention.",
6026
6078
  "3. Execute the phase handler that matches the issue's `bcm:*` label.",
6027
6079
  "4. Commit, push, open a PR (if applicable), and close the issue per",
6028
- " your project's PR workflow.",
6080
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
6081
+ " section below before you close anything yourself.",
6029
6082
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
6030
6083
  " **Origin label** section below.",
6031
6084
  "",
@@ -6039,6 +6092,10 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6039
6092
  "",
6040
6093
  "---",
6041
6094
  "",
6095
+ ...renderIssueClosePolicySection(),
6096
+ "",
6097
+ "---",
6098
+ "",
6042
6099
  "## Phase 1: Outline (`bcm:outline`)",
6043
6100
  "",
6044
6101
  "**Goal:** Identify the capability (name-as-noun, business object, tier)",
@@ -6127,7 +6184,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6127
6184
  " `Depends on: #<outline-issue>`. Its body references the outline",
6128
6185
  " file path.",
6129
6186
  "",
6130
- "10. **Commit and push** the outline file. Close the outline issue.",
6187
+ "10. **Commit and push** the outline file. Close the outline issue",
6188
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
6131
6189
  "",
6132
6190
  "---",
6133
6191
  "",
@@ -6214,7 +6272,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6214
6272
  " `Depends on: #<scaffold-issue>`. Its body references the BCM",
6215
6273
  " document path and the outline file path.",
6216
6274
  "",
6217
- "5. **Commit and push** the BCM document. Close the scaffold issue.",
6275
+ "5. **Commit and push** the BCM document. Close the scaffold issue",
6276
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
6218
6277
  "",
6219
6278
  "---",
6220
6279
  "",
@@ -6303,7 +6362,7 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6303
6362
  " those into downstream issues.",
6304
6363
  "",
6305
6364
  "11. **Commit and push** the updated BCM document. Close the context",
6306
- " issue.",
6365
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
6307
6366
  "",
6308
6367
  "---",
6309
6368
  "",
@@ -6397,7 +6456,7 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
6397
6456
  "",
6398
6457
  "8. **Commit and push** the registry update, capability-map update,",
6399
6458
  " cross-link edits, and BCM-document revision-history row. Close the",
6400
- " connect issue.",
6459
+ ` connect issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
6401
6460
  "",
6402
6461
  "---",
6403
6462
  "",
@@ -7335,7 +7394,8 @@ function buildBusinessModelsAnalystSubAgent(paths) {
7335
7394
  "3. Execute the phase handler that matches the issue's",
7336
7395
  " `business-models:*` label.",
7337
7396
  "4. Commit, push, open a PR (if applicable), and close the issue per",
7338
- " your project's PR workflow.",
7397
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
7398
+ " section below before you close anything yourself.",
7339
7399
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
7340
7400
  " **Origin label** section below.",
7341
7401
  "",
@@ -7349,6 +7409,10 @@ function buildBusinessModelsAnalystSubAgent(paths) {
7349
7409
  "",
7350
7410
  "---",
7351
7411
  "",
7412
+ ...renderIssueClosePolicySection(),
7413
+ "",
7414
+ "---",
7415
+ "",
7352
7416
  "## Phase 1: Scan (`business-models:scan`)",
7353
7417
  "",
7354
7418
  "**Goal:** Read upstream industry and profile artifacts to identify",
@@ -7427,7 +7491,8 @@ function buildBusinessModelsAnalystSubAgent(paths) {
7427
7491
  " references the scan report, the industry, the segment name, and",
7428
7492
  " the authorized source list.",
7429
7493
  "",
7430
- "8. **Commit and push** the scan report. Close the scan issue.",
7494
+ "8. **Commit and push** the scan report. Close the scan issue",
7495
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
7431
7496
  "",
7432
7497
  "---",
7433
7498
  "",
@@ -7499,7 +7564,8 @@ function buildBusinessModelsAnalystSubAgent(paths) {
7499
7564
  " `Depends on: #<canvas-issue>`. Its body references the path to",
7500
7565
  " the canvas document and names the industry and segment.",
7501
7566
  "",
7502
- "9. **Commit and push** the canvas document. Close the canvas issue.",
7567
+ "9. **Commit and push** the canvas document. Close the canvas issue",
7568
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
7503
7569
  "",
7504
7570
  "---",
7505
7571
  "",
@@ -7630,7 +7696,7 @@ function buildBusinessModelsAnalystSubAgent(paths) {
7630
7696
  " summary: value-stream count, variation coverage, and the list of",
7631
7697
  " `bcm:outline` issues created.",
7632
7698
  "",
7633
- "12. **Close the complete issue.**",
7699
+ `12. **Close the complete issue** ${ISSUE_CLOSE_RULE_REFERENCE}.`,
7634
7700
  "",
7635
7701
  "---",
7636
7702
  "",
@@ -8244,7 +8310,8 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8244
8310
  "3. Execute the phase handler that matches the issue's `company:*`",
8245
8311
  " label.",
8246
8312
  "4. Commit, push, open a PR (if applicable), and close the issue per",
8247
- " your project's PR workflow.",
8313
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
8314
+ " section below before you close anything yourself.",
8248
8315
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
8249
8316
  " **Origin label** section below.",
8250
8317
  "",
@@ -8258,6 +8325,10 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8258
8325
  "",
8259
8326
  "---",
8260
8327
  "",
8328
+ ...renderIssueClosePolicySection(),
8329
+ "",
8330
+ "---",
8331
+ "",
8261
8332
  "## Phase 1: Research (`company:research`)",
8262
8333
  "",
8263
8334
  "**Goal:** Gather public sources into a bounded research-notes file.",
@@ -8323,7 +8394,8 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8323
8394
  " Its body references the notes file path and the requested company",
8324
8395
  " type.",
8325
8396
  "",
8326
- "6. **Commit and push** the notes file. Close the research issue.",
8397
+ "6. **Commit and push** the notes file. Close the research issue",
8398
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8327
8399
  "",
8328
8400
  "---",
8329
8401
  "",
@@ -8433,7 +8505,8 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8433
8505
  " no business-model canvases at all (Phase 4 will detect and exit",
8434
8506
  " gracefully in that case).",
8435
8507
  "",
8436
- "7. **Commit and push** the profile file. Close the draft issue.",
8508
+ "7. **Commit and push** the profile file. Close the draft issue",
8509
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8437
8510
  "",
8438
8511
  "---",
8439
8512
  "",
@@ -8529,7 +8602,7 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8529
8602
  " because a profile already exists).",
8530
8603
  "",
8531
8604
  "8. **Commit and push** (if the profile was updated). Close the",
8532
- " followup issue.",
8605
+ ` followup issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8533
8606
  "",
8534
8607
  "---",
8535
8608
  "",
@@ -8578,7 +8651,7 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8578
8651
  ` the consuming project declares in \`${paths.docsRoot}/project-context.md\`).`,
8579
8652
  " If the directory does not exist or contains no canvases, exit",
8580
8653
  " gracefully: add a short note to the profile's `## Risks / Open",
8581
- " Questions` section and close the issue.",
8654
+ ` Questions\` section and close the issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8582
8655
  "",
8583
8656
  "4. **For each candidate canvas, score the match.** For each canvas:",
8584
8657
  " - Read the Customer Segments, Key Activities, Value Propositions,",
@@ -8649,8 +8722,9 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8649
8722
  " | YYYY-MM-DD | Matched to business models: <comma-separated segment list> |",
8650
8723
  " ```",
8651
8724
  "",
8652
- "9. **Commit and push.** Close the match issue with a short comment",
8653
- " summarizing the matched segments.",
8725
+ "9. **Commit and push.** Report the matched segments on the match",
8726
+ " issue with a short comment, and close it",
8727
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8654
8728
  "",
8655
8729
  "---",
8656
8730
  "",
@@ -8742,8 +8816,9 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8742
8816
  " update the corresponding entry under `referencedIn` and the",
8743
8817
  " research-area doc that links to this profile.",
8744
8818
  "",
8745
- "9. **Commit and push.** Close the refresh issue with a short comment",
8746
- " summarizing the delta (or `no material change`).",
8819
+ "9. **Commit and push.** Report the delta on the refresh issue with",
8820
+ " a short comment (or `no material change`), and close it",
8821
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8747
8822
  "",
8748
8823
  "---",
8749
8824
  "",
@@ -8857,8 +8932,9 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
8857
8932
  " from a profile to the analysis document should be added by a",
8858
8933
  " follow-up `company:match` pass, not by this phase.",
8859
8934
  "",
8860
- "7. **Commit and push.** Close the analyze issue with a short",
8861
- " comment naming the analysis document path.",
8935
+ "7. **Commit and push.** Name the analysis document path on the",
8936
+ " analyze issue with a short comment, and close it",
8937
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
8862
8938
  "",
8863
8939
  "---",
8864
8940
  "",
@@ -9695,7 +9771,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
9695
9771
  "3. Execute the phase handler that matches the issue's `customer:*`",
9696
9772
  " label.",
9697
9773
  "4. Commit, push, open a PR (if applicable), and close the issue per",
9698
- " your project's PR workflow.",
9774
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
9775
+ " section below before you close anything yourself.",
9699
9776
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
9700
9777
  " **Origin label** section below.",
9701
9778
  "",
@@ -9709,6 +9786,10 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
9709
9786
  "",
9710
9787
  "---",
9711
9788
  "",
9789
+ ...renderIssueClosePolicySection(),
9790
+ "",
9791
+ "---",
9792
+ "",
9712
9793
  "## Phase 1: Discover (`customer:discover`)",
9713
9794
  "",
9714
9795
  "**Goal:** Identify and segment the customer archetypes relevant to",
@@ -9794,7 +9875,7 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
9794
9875
  " priority archetype.",
9795
9876
  "",
9796
9877
  "7. **Commit and push** the discovery report. Close the discover",
9797
- " issue.",
9878
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
9798
9879
  "",
9799
9880
  "---",
9800
9881
  "",
@@ -9873,7 +9954,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
9873
9954
  "",
9874
9955
  "10. **Verify all handoffs were created** before committing.",
9875
9956
  "",
9876
- "11. **Commit and push** the archetype page. Close the profile issue.",
9957
+ "11. **Commit and push** the archetype page. Close the profile issue",
9958
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
9877
9959
  "",
9878
9960
  "---",
9879
9961
  "",
@@ -10006,7 +10088,7 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
10006
10088
  ...renderIssueTypeAssignmentStep(),
10007
10089
  "",
10008
10090
  "10. **Commit and push** the competitor-analysis page and the",
10009
- " updated archetype page. Close the competitors issue.",
10091
+ ` updated archetype page. Close the competitors issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
10010
10092
  "",
10011
10093
  "---",
10012
10094
  "",
@@ -12653,7 +12735,8 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
12653
12735
  "3. Execute the phase handler that matches the issue's `industry:*`",
12654
12736
  " label.",
12655
12737
  "4. Commit, push, open a PR (if applicable), and close the issue per",
12656
- " your project's PR workflow.",
12738
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
12739
+ " section below before you close anything yourself.",
12657
12740
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
12658
12741
  " **Origin label** section below.",
12659
12742
  "",
@@ -12667,6 +12750,10 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
12667
12750
  "",
12668
12751
  "---",
12669
12752
  "",
12753
+ ...renderIssueClosePolicySection(),
12754
+ "",
12755
+ "---",
12756
+ "",
12670
12757
  "## Phase 1: Discover (`industry:discover`)",
12671
12758
  "",
12672
12759
  "**Goal:** Enumerate candidate industry verticals into a bounded",
@@ -12731,7 +12818,8 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
12731
12818
  " file path and the fit rubric source (invoking issue, project",
12732
12819
  " context, or scaffold).",
12733
12820
  "",
12734
- "6. **Commit and push** the candidate file. Close the discover issue.",
12821
+ "6. **Commit and push** the candidate file. Close the discover issue",
12822
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
12735
12823
  "",
12736
12824
  "---",
12737
12825
  "",
@@ -12792,7 +12880,8 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
12792
12880
  " `Depends on: #<evaluate-issue>`. Its body references the evaluation",
12793
12881
  " file path and lists the verticals that clear the threshold (if any).",
12794
12882
  "",
12795
- "6. **Commit and push** the evaluation file. Close the evaluate issue.",
12883
+ "6. **Commit and push** the evaluation file. Close the evaluate issue",
12884
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
12796
12885
  "",
12797
12886
  "---",
12798
12887
  "",
@@ -12855,7 +12944,8 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
12855
12944
  " table so each row references its newly-created `research:scope`",
12856
12945
  " issue number.",
12857
12946
  "",
12858
- "6. **Commit and push** the plan file. Close the plan issue.",
12947
+ "6. **Commit and push** the plan file. Close the plan issue",
12948
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
12859
12949
  "",
12860
12950
  "---",
12861
12951
  "",
@@ -13218,7 +13308,8 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
13218
13308
  "3. Execute the phase handler that matches the issue's `maint:*`",
13219
13309
  " label.",
13220
13310
  "4. Commit, push, open a PR (if applicable), and close the issue per",
13221
- " your project's PR workflow.",
13311
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
13312
+ " section below before you close anything yourself.",
13222
13313
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
13223
13314
  " **Origin label** section below.",
13224
13315
  "",
@@ -13234,6 +13325,10 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
13234
13325
  "",
13235
13326
  "---",
13236
13327
  "",
13328
+ ...renderIssueClosePolicySection(),
13329
+ "",
13330
+ "---",
13331
+ "",
13237
13332
  "## Phase 1: Scan (`maint:scan`)",
13238
13333
  "",
13239
13334
  "**Goal:** Walk the configured doc tree, check every cross-reference",
@@ -13330,11 +13425,13 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
13330
13425
  "5. **Decide the next step:**",
13331
13426
  " - **No findings** \u2192 comment on the scan issue noting a clean",
13332
13427
  " audit, commit the (still valuable) empty report, close the",
13333
- " issue. Do not create a `maint:fix` issue.",
13428
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}. Do not create a`,
13429
+ " `maint:fix` issue.",
13334
13430
  " - **All findings need human judgment** \u2192 commit the report,",
13335
13431
  " comment on the scan issue summarizing the findings, apply",
13336
- " `status:needs-attention`, and close the issue. Do not create",
13337
- " a `maint:fix` or `maint:verify` issue.",
13432
+ " `status:needs-attention`, and close the issue",
13433
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}. Do not create a \`maint:fix\` or`,
13434
+ " `maint:verify` issue.",
13338
13435
  " - **At least one auto-fixable finding** \u2192 create a `maint:fix`",
13339
13436
  " issue (blocked on this scan issue via `Depends on: #N`). The",
13340
13437
  " fix issue body must reference the audit report path, enumerate",
@@ -13449,9 +13546,9 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
13449
13546
  "",
13450
13547
  " If the fix phase applied **zero** auto-fixes (every finding was",
13451
13548
  " `stale-finding` or `flag-for-human`), skip the verify issue \u2014",
13452
- " there is nothing to verify. Close the fix issue with a summary,",
13453
- " comment on the scan issue, and let a human decide whether to",
13454
- " re-scan.",
13549
+ " there is nothing to verify. Summarize on the fix issue and close",
13550
+ ` it ${ISSUE_CLOSE_RULE_REFERENCE}, comment on the scan issue, and`,
13551
+ " let a human decide whether to re-scan.",
13455
13552
  "",
13456
13553
  "9. **Commit and push.**",
13457
13554
  "",
@@ -13557,8 +13654,8 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
13557
13654
  " re-scope the cycle. Do not auto-close the parent scan issue",
13558
13655
  " in this case.",
13559
13656
  "",
13560
- "6. **Commit and push.** Close the verify issue with a one-line",
13561
- " summary of the verdict.",
13657
+ "6. **Commit and push.** Comment the verdict on the verify issue in",
13658
+ ` one line, and close it ${ISSUE_CLOSE_RULE_REFERENCE}.`,
13562
13659
  "",
13563
13660
  "---",
13564
13661
  "",
@@ -13836,7 +13933,9 @@ function buildMeetingAnalystSubAgent(tier) {
13836
13933
  "",
13837
13934
  "1. Each meeting produces up to 4 GitHub issues (one per phase)",
13838
13935
  "2. Each issue carries a `meeting:*` label identifying the phase",
13839
- "3. You pick up one issue, execute that phase, commit/push, then close the issue",
13936
+ "3. You pick up one issue, execute that phase, commit/push, then close",
13937
+ ` the issue \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}** section below`,
13938
+ " before you close anything yourself",
13840
13939
  "4. Phase 1 (Extract) creates the downstream phase issues for phases 2-4",
13841
13940
  "5. Each downstream issue includes `Depends on: #N` linking to its predecessor",
13842
13941
  "",
@@ -14130,6 +14229,10 @@ function buildMeetingAnalystSubAgent(tier) {
14130
14229
  "",
14131
14230
  "---",
14132
14231
  "",
14232
+ ...renderIssueClosePolicySection(),
14233
+ "",
14234
+ "---",
14235
+ "",
14133
14236
  "## Phase 1: Extract (`meeting:extract`)",
14134
14237
  "",
14135
14238
  "**Goal:** Read the available meeting inputs (notes, transcript, or both)",
@@ -14271,7 +14374,8 @@ function buildMeetingAnalystSubAgent(tier) {
14271
14374
  " commit-path verification step (`git show HEAD:<index-path>`",
14272
14375
  " + grep count) against that commit before pushing.",
14273
14376
  "",
14274
- "9. **Push and close.** Push the branch and close the extract issue.",
14377
+ "9. **Push and close.** Push the branch, then close the extract issue",
14378
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
14275
14379
  "",
14276
14380
  "---",
14277
14381
  "",
@@ -14369,7 +14473,7 @@ function buildMeetingAnalystSubAgent(tier) {
14369
14473
  " commit** whose only file is the shared index. Run the",
14370
14474
  " commit-path verification step against that commit before",
14371
14475
  " pushing.",
14372
- "7. Push and close the notes issue.",
14476
+ `7. Push, then close the notes issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
14373
14477
  "",
14374
14478
  "---",
14375
14479
  "",
@@ -14401,7 +14505,8 @@ function buildMeetingAnalystSubAgent(tier) {
14401
14505
  " - Stated preferences or decisions",
14402
14506
  " - Status: Proposed or Decided",
14403
14507
  "5. Summarize product/strategy document updates needed.",
14404
- "6. Commit, push, and close the draft issue.",
14508
+ "6. Commit, push, and close the draft issue",
14509
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
14405
14510
  "",
14406
14511
  "---",
14407
14512
  "",
@@ -14513,7 +14618,8 @@ function buildMeetingAnalystSubAgent(tier) {
14513
14618
  " meeting.",
14514
14619
  "9. Comment on the parent extract issue with a summary linking to all",
14515
14620
  " created artifacts.",
14516
- "10. Commit and push (if any file changes were made), then close the link issue.",
14621
+ "10. Commit and push (if any file changes were made), then close the",
14622
+ ` link issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
14517
14623
  "",
14518
14624
  "---",
14519
14625
  "",
@@ -20163,7 +20269,8 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20163
20269
  "3. Execute the phase handler that matches the issue's `people:*`",
20164
20270
  " label.",
20165
20271
  "4. Commit, push, open a PR (if applicable), and close the issue per",
20166
- " your project's PR workflow.",
20272
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
20273
+ " section below before you close anything yourself.",
20167
20274
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
20168
20275
  " **Origin label** section below.",
20169
20276
  "",
@@ -20177,6 +20284,10 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20177
20284
  "",
20178
20285
  "---",
20179
20286
  "",
20287
+ ...renderIssueClosePolicySection(),
20288
+ "",
20289
+ "---",
20290
+ "",
20180
20291
  "## Phase 1: Research (`people:research`)",
20181
20292
  "",
20182
20293
  "**Goal:** Gather public sources into a bounded research-notes file.",
@@ -20247,7 +20358,8 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20247
20358
  " Its body references the notes file path, the requested role, and",
20248
20359
  " any refresh-mode flags.",
20249
20360
  "",
20250
- "7. **Commit and push** the notes file. Close the research issue.",
20361
+ "7. **Commit and push** the notes file. Close the research issue",
20362
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
20251
20363
  "",
20252
20364
  "---",
20253
20365
  "",
@@ -20349,7 +20461,8 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20349
20461
  " followup when the profile surfaced no cross-reference candidates",
20350
20462
  " at all; note this in the draft issue's closing comment.",
20351
20463
  "",
20352
- "5. **Commit and push** the profile file. Close the draft issue.",
20464
+ "5. **Commit and push** the profile file. Close the draft issue",
20465
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
20353
20466
  "",
20354
20467
  "---",
20355
20468
  "",
@@ -20481,7 +20594,7 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20481
20594
  " enqueued for research).",
20482
20595
  "",
20483
20596
  "11. **Commit and push** the updated profile. Close the followup",
20484
- " issue.",
20597
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
20485
20598
  "",
20486
20599
  "---",
20487
20600
  "",
@@ -20565,8 +20678,9 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
20565
20678
  " even if a search surfaces them. Privacy guardrails from Phase 1",
20566
20679
  " apply to every refresh.",
20567
20680
  "",
20568
- "8. **Commit and push.** Close the refresh issue with a short comment",
20569
- " summarizing the delta (or `no material change`).",
20681
+ "8. **Commit and push.** Report the delta on the refresh issue with",
20682
+ " a short comment (or `no material change`), and close it",
20683
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
20570
20684
  "",
20571
20685
  "---",
20572
20686
  "",
@@ -25009,7 +25123,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
25009
25123
  "3. Execute the phase handler that matches the issue's `regulatory:*`",
25010
25124
  " label.",
25011
25125
  "4. Commit, push, open a PR (if applicable), and close the issue per",
25012
- " your project's PR workflow.",
25126
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
25127
+ " section below before you close anything yourself.",
25013
25128
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
25014
25129
  " **Origin label** section below.",
25015
25130
  "",
@@ -25023,6 +25138,10 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
25023
25138
  "",
25024
25139
  "---",
25025
25140
  "",
25141
+ ...renderIssueClosePolicySection(),
25142
+ "",
25143
+ "---",
25144
+ "",
25026
25145
  "## Phase 1: Scan (`regulatory:scan`)",
25027
25146
  "",
25028
25147
  "**Goal:** Enumerate regulations applicable to a given scope \u2014",
@@ -25140,7 +25259,7 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
25140
25259
  " page H1.",
25141
25260
  "",
25142
25261
  "8. **Commit and push** the scan report and the scope index page.",
25143
- " Close the scan issue.",
25262
+ ` Close the scan issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
25144
25263
  "",
25145
25264
  "---",
25146
25265
  "",
@@ -25214,7 +25333,7 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
25214
25333
  "9. **Verify all handoffs were created** before committing.",
25215
25334
  "",
25216
25335
  "10. **Commit and push** the regulation page. Close the research",
25217
- " issue.",
25336
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
25218
25337
  "",
25219
25338
  "---",
25220
25339
  "",
@@ -25358,7 +25477,7 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
25358
25477
  ...renderIssueTypeAssignmentStep(),
25359
25478
  "",
25360
25479
  "7. **Commit and push** the updated regulation page. Close the",
25361
- " impact issue.",
25480
+ ` impact issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
25362
25481
  "",
25363
25482
  "---",
25364
25483
  "",
@@ -30862,7 +30981,8 @@ function buildResearchAnalystSubAgent(paths) {
30862
30981
  "3. Execute the phase handler that matches the issue's `research:*`",
30863
30982
  " label.",
30864
30983
  "4. Commit, push, open a PR (if applicable), and close the issue per",
30865
- " your project's PR workflow.",
30984
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
30985
+ " section below before you close anything yourself.",
30866
30986
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
30867
30987
  " **Origin label** section below.",
30868
30988
  "",
@@ -30876,6 +30996,10 @@ function buildResearchAnalystSubAgent(paths) {
30876
30996
  "",
30877
30997
  "---",
30878
30998
  "",
30999
+ ...renderIssueClosePolicySection(),
31000
+ "",
31001
+ "---",
31002
+ "",
30879
31003
  "## Phase 1: Scope (`research:scope`)",
30880
31004
  "",
30881
31005
  "**Goal:** Turn a natural-language research question into a bounded",
@@ -30951,7 +31075,8 @@ function buildResearchAnalystSubAgent(paths) {
30951
31075
  " issues. Its body references the scope file and lists every slice",
30952
31076
  " output path that verify must read.",
30953
31077
  "",
30954
- "7. **Commit and push** the scope file. Close the scope issue.",
31078
+ "7. **Commit and push** the scope file. Close the scope issue",
31079
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
30955
31080
  "",
30956
31081
  "---",
30957
31082
  "",
@@ -31008,7 +31133,8 @@ function buildResearchAnalystSubAgent(paths) {
31008
31133
  " cut and flag it for the verify phase \u2014 do not expand into other",
31009
31134
  " slices' territory.",
31010
31135
  "",
31011
- "6. **Commit and push** the slice note. Close the slice issue.",
31136
+ "6. **Commit and push** the slice note. Close the slice issue",
31137
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
31012
31138
  "",
31013
31139
  "---",
31014
31140
  "",
@@ -31073,7 +31199,8 @@ function buildResearchAnalystSubAgent(paths) {
31073
31199
  "6. **Comment on the scope issue** with a summary linking to the",
31074
31200
  " deliverable and verification report.",
31075
31201
  "",
31076
- "7. **Commit and push.** Close the verify issue.",
31202
+ "7. **Commit and push.** Close the verify issue",
31203
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
31077
31204
  "",
31078
31205
  "---",
31079
31206
  "",
@@ -31613,7 +31740,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
31613
31740
  "3. Execute the phase handler that matches the issue's `software:*`",
31614
31741
  " label.",
31615
31742
  "4. Commit, push, open a PR (if applicable), and close the issue per",
31616
- " your project's PR workflow.",
31743
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
31744
+ " section below before you close anything yourself.",
31617
31745
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
31618
31746
  " **Origin label** section below.",
31619
31747
  "",
@@ -31627,6 +31755,10 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
31627
31755
  "",
31628
31756
  "---",
31629
31757
  "",
31758
+ ...renderIssueClosePolicySection(),
31759
+ "",
31760
+ "---",
31761
+ "",
31630
31762
  "## Phase 1: Research (`software:research`)",
31631
31763
  "",
31632
31764
  "**Goal:** Gather public sources into a bounded research-notes file.",
@@ -31693,7 +31825,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
31693
31825
  " `Depends on: #<research-issue>`. Its body references the notes",
31694
31826
  " file path and the requested software type.",
31695
31827
  "",
31696
- "6. **Commit and push** the notes file. Close the research issue.",
31828
+ "6. **Commit and push** the notes file. Close the research issue",
31829
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
31697
31830
  "",
31698
31831
  "---",
31699
31832
  "",
@@ -31788,7 +31921,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
31788
31921
  " path, the matrix file path, and the segment-weights source",
31789
31922
  ` (\`${paths.docsRoot}/project-context.md\` or an explicit override).`,
31790
31923
  "",
31791
- "5. **Commit and push** the profile file. Close the profile issue.",
31924
+ "5. **Commit and push** the profile file. Close the profile issue",
31925
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
31792
31926
  "",
31793
31927
  "---",
31794
31928
  "",
@@ -31898,7 +32032,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
31898
32032
  " count on the product slug as the unique marker) against",
31899
32033
  " that commit before pushing.",
31900
32034
  "",
31901
- "9. **Push and close.** Push the branch and close the matrix issue.",
32035
+ "9. **Push and close.** Push the branch, then close the matrix issue",
32036
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
31902
32037
  "",
31903
32038
  "---",
31904
32039
  "",
@@ -32020,7 +32155,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
32020
32155
  " could not be routed \u2014 never invent an alternative label",
32021
32156
  " taxonomy.",
32022
32157
  "",
32023
- "10. **Commit and push** the updated profile. Close the map issue.",
32158
+ "10. **Commit and push** the updated profile. Close the map issue",
32159
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
32024
32160
  "",
32025
32161
  "---",
32026
32162
  "",
@@ -32140,7 +32276,7 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
32140
32276
  " were enqueued for research).",
32141
32277
  "",
32142
32278
  "9. **Commit and push** (if the profile was updated). Close the",
32143
- " followup issue.",
32279
+ ` followup issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
32144
32280
  "",
32145
32281
  "---",
32146
32282
  "",
@@ -32757,7 +32893,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
32757
32893
  "3. Execute the phase handler that matches the issue's `standards:*`",
32758
32894
  " label.",
32759
32895
  "4. Commit, push, open a PR (if applicable), and close the issue per",
32760
- " your project's PR workflow.",
32896
+ ` your project's PR workflow \u2014 see the **${ISSUE_CLOSE_SECTION_TITLE}**`,
32897
+ " section below before you close anything yourself.",
32761
32898
  " Stamp every PR you open with the `origin:agent` label \u2014 see the",
32762
32899
  " **Origin label** section below.",
32763
32900
  "",
@@ -32771,6 +32908,10 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
32771
32908
  "",
32772
32909
  "---",
32773
32910
  "",
32911
+ ...renderIssueClosePolicySection(),
32912
+ "",
32913
+ "---",
32914
+ "",
32774
32915
  "## Phase 1: Scope (`standards:scope`)",
32775
32916
  "",
32776
32917
  "**Goal:** Plan the research campaign for a standard \u2014 identify which",
@@ -32855,7 +32996,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
32855
32996
  " in parallel with research issues \u2014 they do not depend on",
32856
32997
  " research completing.",
32857
32998
  "",
32858
- "8. **Commit and push** the query plan. Close the scope issue.",
32999
+ "8. **Commit and push** the query plan. Close the scope issue",
33000
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
32859
33001
  "",
32860
33002
  "---",
32861
33003
  "",
@@ -33004,7 +33146,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
33004
33146
  " entity in both tables, confirm an existing profile or a fresh",
33005
33147
  " handoff issue exists. Do not commit with missing handoffs.",
33006
33148
  "",
33007
- "8. **Commit and push** the version page. Close the research issue.",
33149
+ "8. **Commit and push** the version page. Close the research issue",
33150
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
33008
33151
  "",
33009
33152
  "---",
33010
33153
  "",
@@ -33070,7 +33213,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
33070
33213
  " entity. This handoff is optional \u2014 if no domain entities show",
33071
33214
  " gaps, skip it.",
33072
33215
  "",
33073
- "6. **Commit and push** the overview page. Close the compare issue.",
33216
+ "6. **Commit and push** the overview page. Close the compare issue",
33217
+ ` ${ISSUE_CLOSE_RULE_REFERENCE}.`,
33074
33218
  "",
33075
33219
  "---",
33076
33220
  "",
@@ -33208,7 +33352,7 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
33208
33352
  "8. **Create `<EXTENSIONS_DIR>`** if it does not yet exist.",
33209
33353
  "",
33210
33354
  "9. **Commit and push** the extension analysis. Close the extension",
33211
- " issue.",
33355
+ ` issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
33212
33356
  "",
33213
33357
  "---",
33214
33358
  "",
@@ -33309,7 +33453,7 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
33309
33453
  ...renderIssueTypeAssignmentStep(),
33310
33454
  "",
33311
33455
  "7. **Commit and push** the organization page. Close the",
33312
- " organizations issue.",
33456
+ ` organizations issue ${ISSUE_CLOSE_RULE_REFERENCE}.`,
33313
33457
  "",
33314
33458
  "---",
33315
33459
  "",