@codedrifters/configulator 0.0.402 → 0.0.403

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.js CHANGED
@@ -4674,6 +4674,35 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4674
4674
  "schema and consumer example. `status:deferred` is a valid",
4675
4675
  "override value reserved for this exact use case.",
4676
4676
  "",
4677
+ "### The `status:deferred` invariant",
4678
+ "",
4679
+ "**No agent, procedure, or sweep ever removes `status:deferred`.",
4680
+ "Only a human promotes a deferred issue.**",
4681
+ "",
4682
+ "`status:deferred` records a deliberate human decision to park",
4683
+ "work. Automation may read it, count it, and log it \u2014 but the",
4684
+ "label is cleared exclusively by a human (or by a scheduled task",
4685
+ "a human configured for that purpose). Concretely:",
4686
+ "",
4687
+ "- **Unblock sweeps skip it.** Both `check-blocked.sh unblock`",
4688
+ " and `unblock-dependents.sh` leave a `status:deferred` +",
4689
+ " `status:blocked` issue blocked when its dependencies close,",
4690
+ " emitting a `SKIP_DEFERRED #<n>` line instead of flipping to",
4691
+ " `status:ready`. Dependency resolution is not a promotion",
4692
+ " signal for parked work.",
4693
+ "- **Dispatch scans exclude it.** `check-blocked.sh eligible`",
4694
+ " drops any issue carrying `status:deferred`, so a stray",
4695
+ " `status:ready` + `status:deferred` pairing never reaches a",
4696
+ " worker.",
4697
+ "- **No sweep writes it either.** Automation adds",
4698
+ " `status:deferred` only at filing time via the configured",
4699
+ " `issueDefaults` \u2014 never as a runtime triage decision.",
4700
+ "",
4701
+ "An issue that legitimately needs to leave the parked backlog is",
4702
+ "promoted by a human removing `status:deferred` and setting the",
4703
+ "appropriate base status. Any automation that removes the label",
4704
+ "is a bug.",
4705
+ "",
4677
4706
  "### Blocking Rules",
4678
4707
  "",
4679
4708
  "Two rules force `status:blocked` \u2014 both are non-negotiable:",
@@ -15166,13 +15195,16 @@ function renderUnblockDependentsSection(ud) {
15166
15195
  "",
15167
15196
  "1. Searches open issues for `Depends on: #<closed>` references in",
15168
15197
  " their body.",
15169
- "2. For each match, re-reads every dependency listed across",
15198
+ "2. Skips any match carrying `status:deferred`, emitting a",
15199
+ " `SKIP_DEFERRED` line. A human-parked issue is never promoted by",
15200
+ " a sweep, no matter how its dependencies resolve.",
15201
+ "3. For each remaining match, re-reads every dependency listed across",
15170
15202
  " **all** `Depends on:` lines in the body (bodies routinely list",
15171
15203
  " one dependency per line) and checks whether they are all closed.",
15172
- "3. If **all** dependencies are closed, flips the dependent from",
15204
+ "4. If **all** dependencies are closed, flips the dependent from",
15173
15205
  " `status:blocked` to `status:ready` and posts a one-line comment",
15174
15206
  " citing the resolving issue.",
15175
- "4. If **some** dependencies are still open, leaves the dependent",
15207
+ "5. If **some** dependencies are still open, leaves the dependent",
15176
15208
  " as `status:blocked` and optionally posts a partial-unblock",
15177
15209
  " comment (see the **Partial unblock behaviour** subsection",
15178
15210
  " below).",
@@ -15206,6 +15238,7 @@ function renderUnblockDependentsSection(ud) {
15206
15238
  'UNBLOCKED #<dep> \u2014 all deps closed (<closed-list>) \u2014 "<title>"',
15207
15239
  'UNBLOCK_FAILED #<dep> \u2014 label flip failed (all deps closed: <closed-list>) \u2014 "<title>"',
15208
15240
  'STILL_BLOCKED #<dep> \u2014 waiting on <open-list> \u2014 "<title>"',
15241
+ 'SKIP_DEFERRED #<dep> \u2014 status:deferred; human-parked, not promoting \u2014 "<title>"',
15209
15242
  "NO_DEPENDENTS #<closed>",
15210
15243
  "```",
15211
15244
  "",
@@ -15215,7 +15248,10 @@ function renderUnblockDependentsSection(ud) {
15215
15248
  "error, permissions, or the dependent went stale between the",
15216
15249
  "search and the edit) \u2014 a human needs to retry or flip the label",
15217
15250
  "manually. `STILL_BLOCKED` lines mean the dependent stays blocked",
15218
- "pending other open deps. `NO_DEPENDENTS` means no open issue",
15251
+ "pending other open deps. `SKIP_DEFERRED` lines mean the dependent",
15252
+ "carries `status:deferred` and was deliberately left blocked even",
15253
+ "though its dependencies resolved \u2014 the sweep never promotes a",
15254
+ "human-parked issue. `NO_DEPENDENTS` means no open issue",
15219
15255
  "references the just-closed issue in a `Depends on:` line.",
15220
15256
  "",
15221
15257
  "### Partial unblock behaviour",
@@ -15366,7 +15402,7 @@ function renderUnblockDependentsScript(ud) {
15366
15402
  "# `status:blocked` \u2192 `status:ready` directly on the overflow.",
15367
15403
  'dependents=$(gh issue list --label "status:blocked" --state open \\',
15368
15404
  ' --search "in:body \\"Depends on:\\"" \\',
15369
- ' --json number,title,body --limit 100 2>/dev/null || echo "[]")',
15405
+ ' --json number,title,body,labels --limit 100 2>/dev/null || echo "[]")',
15370
15406
  "",
15371
15407
  `count=$(echo "$dependents" | jq 'length')`,
15372
15408
  'if [[ "$count" -eq 0 ]]; then',
@@ -15374,6 +15410,18 @@ function renderUnblockDependentsScript(ud) {
15374
15410
  " exit 0",
15375
15411
  "fi",
15376
15412
  "",
15413
+ "# Human-parked candidates (`status:deferred`). Collected jq-side into a",
15414
+ "# space-delimited lookup string rather than threaded through the",
15415
+ "# tab-separated records below: an extra TSV field would either sit after",
15416
+ "# dep_line (displacing the mandatory-last optional field) or before it",
15417
+ "# (reintroducing the #884 IFS tab-collapse bug). The skip itself happens",
15418
+ "# inside the loop, after the closed-issue reference test, so an unrelated",
15419
+ "# deferred issue in the search window never emits a line. No agent or",
15420
+ "# sweep ever removes `status:deferred` \u2014 only a human promotes it.",
15421
+ `deferred_set=" $(echo "$dependents" | jq -r '`,
15422
+ ' .[] | select(.labels | map(.name) | index("status:deferred")) | .number',
15423
+ `' | tr '\\n' ' ')"`,
15424
+ "",
15377
15425
  "# Union every `Depends on:` line per candidate (a body may list one",
15378
15426
  "# dependency per line) into a single space-joined dep string and stream",
15379
15427
  "# as tab-separated number / title / dep-line tuples.",
@@ -15409,6 +15457,14 @@ function renderUnblockDependentsScript(ud) {
15409
15457
  "",
15410
15458
  " found_any=true",
15411
15459
  "",
15460
+ " # Deliberately-parked dependents never get promoted by a sweep, even",
15461
+ " # when every dependency has closed. Only a human clears",
15462
+ " # `status:deferred`.",
15463
+ ' if [[ "$deferred_set" == *" ${num} "* ]]; then',
15464
+ ' echo "SKIP_DEFERRED #${num} \u2014 status:deferred; human-parked, not promoting \u2014 \\"${title}\\""',
15465
+ " continue",
15466
+ " fi",
15467
+ "",
15412
15468
  " # Re-check every dep in the list. Fully-closed \u2192 unblock.",
15413
15469
  " all_closed=true",
15414
15470
  ' open_deps=""',
@@ -15598,15 +15654,26 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
15598
15654
  " # position.",
15599
15655
  " local issues",
15600
15656
  ' issues=$(gh issue list --label "status:blocked" --state open \\',
15601
- ' --json number,body --limit 1000 2>/dev/null || echo "[]")',
15657
+ ' --json number,body,labels --limit 1000 2>/dev/null || echo "[]")',
15602
15658
  "",
15603
15659
  " local count",
15604
15660
  ` count=$(echo "$issues" | jq 'length')`,
15605
15661
  ' if [[ "$count" -eq 0 ]]; then',
15606
- ' echo "TRIAGE_DONE unblocked=0 still_blocked=0"',
15662
+ ' echo "TRIAGE_DONE unblocked=0 still_blocked=0 deferred_skipped=0"',
15607
15663
  " return 0",
15608
15664
  " fi",
15609
15665
  "",
15666
+ " # Human-parked candidates (`status:deferred`). Collected jq-side into",
15667
+ " # a space-delimited lookup string rather than threaded through the",
15668
+ " # tab-separated records below: an extra TSV field would either sit",
15669
+ " # after dep_line (displacing the mandatory-last optional field) or",
15670
+ " # before it (reintroducing the #884 IFS tab-collapse bug). No agent",
15671
+ " # or sweep ever removes `status:deferred` \u2014 only a human promotes it.",
15672
+ " local deferred_set",
15673
+ ` deferred_set=" $(echo "$issues" | jq -r '`,
15674
+ ' .[] | select(.labels | map(.name) | index("status:deferred")) | .number',
15675
+ ` ' | tr '\\n' ' ')"`,
15676
+ "",
15610
15677
  " local issue_data",
15611
15678
  ` issue_data=$(echo "$issues" | jq -r '`,
15612
15679
  " .[] |",
@@ -15619,10 +15686,20 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
15619
15686
  " # mirroring unblock-dependents.sh.",
15620
15687
  " local unblocked_count=0",
15621
15688
  " local still_blocked_count=0",
15689
+ " local deferred_skipped_count=0",
15622
15690
  "",
15623
15691
  " while IFS=$'\\t' read -r num dep_line; do",
15624
15692
  ' [[ -z "$num" ]] && continue',
15625
15693
  "",
15694
+ " # Deliberately-parked issues never get promoted by a sweep, even",
15695
+ " # when every dependency has closed. Only a human clears",
15696
+ " # `status:deferred`.",
15697
+ ' if [[ "$deferred_set" == *" ${num} "* ]]; then',
15698
+ ' echo "SKIP_DEFERRED #${num} \u2014 status:deferred; human-parked, not promoting"',
15699
+ " deferred_skipped_count=$((deferred_skipped_count + 1))",
15700
+ " continue",
15701
+ " fi",
15702
+ "",
15626
15703
  ' if [[ -z "$dep_line" ]]; then',
15627
15704
  ' echo "BLOCKED #${num} \u2014 no Depends on field found"',
15628
15705
  " still_blocked_count=$((still_blocked_count + 1))",
@@ -15683,7 +15760,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
15683
15760
  ' done <<< "$issue_data"',
15684
15761
  "",
15685
15762
  " # Single summary line consumed by the orchestrator.",
15686
- ' echo "TRIAGE_DONE unblocked=${unblocked_count} still_blocked=${still_blocked_count}"',
15763
+ ' echo "TRIAGE_DONE unblocked=${unblocked_count} still_blocked=${still_blocked_count} deferred_skipped=${deferred_skipped_count}"',
15687
15764
  "}",
15688
15765
  "",
15689
15766
  "cmd_eligible() {",
@@ -15707,11 +15784,26 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
15707
15784
  " continue",
15708
15785
  " fi",
15709
15786
  "",
15787
+ " # Dispatch exclusions. `gh issue list` has no negative-label filter",
15788
+ " # for a label-filtered (non-search) listing, so both exclusions run",
15789
+ " # jq-side over the labels already fetched above \u2014 no new TSV field",
15790
+ " # is needed, and the mandatory-last dep_line ordering is untouched.",
15791
+ " # - `status:needs-attention` is additive (it no longer replaces the",
15792
+ " # base status), so a scope-gate-flagged issue keeps `status:ready`",
15793
+ " # and would re-surface in every scan until a human clears the flag",
15794
+ " # (#901). It is never dispatchable, so drop it from the scan.",
15795
+ " # - `status:deferred` is human-parked: captured for provenance and",
15796
+ " # never auto-dispatched. `status:ready` + `status:deferred` is",
15797
+ " # reachable (e.g. after an unblock or a manual edit), so exclude",
15798
+ " # it here as the dispatch-side half of the #887 guard.",
15710
15799
  " local issue_data",
15711
15800
  ` issue_data=$(echo "$issues" | jq -r '`,
15712
15801
  " .[] |",
15802
+ " (.labels | map(.name)) as $names |",
15803
+ ' select($names | index("status:needs-attention") | not) |',
15804
+ ' select($names | index("status:deferred") | not) |',
15713
15805
  ' (.body | split("\\n") | map(select(test("Depends on:"; "i"))) | join(" ")) as $dep_line |',
15714
- ' (.labels | map(.name) | map(select(startswith("type:"))) | .[0] // "") as $type_label |',
15806
+ ' ($names | map(select(startswith("type:"))) | .[0] // "") as $type_label |',
15715
15807
  ' "\\(.number)\\t\\(.title)\\t\\($type_label)\\t\\($dep_line)"',
15716
15808
  " ')",
15717
15809
  "",
@@ -16355,7 +16447,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
16355
16447
  function buildCheckBlockedProcedure(tiers, scopeGate = resolveScopeGate(), runRatio = resolveRunRatio()) {
16356
16448
  return {
16357
16449
  name: "check-blocked.sh",
16358
- description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, lease-reconcile, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M` summary line; the lease-reconcile subcommand auto-reconciles stuck `review:fixing` PR leases \u2014 re-applying `review:needs-worker` on an orphaned lease (fix-list stale, no worker report) so the Phase B1 drain retries, and removing `review:needs-worker` on a consumed-but-uncleared wedge (branch HEAD advanced past the fix-list, marker still set, no worker report) so the reviewer confirm pass can merge, always posting an audit-trail note comment and emitting a single `LEASE_RECONCILE orphaned=N consumed_uncleared=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, folds in the lease-reconcile sweep, and emits a `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line followed by the `LEASE_RECONCILE` line.",
16450
+ description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, lease-reconcile, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc, excluding issues carrying `status:needs-attention` or `status:deferred`; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, skips human-parked `status:deferred` candidates with a `SKIP_DEFERRED` line, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M deferred_skipped=K` summary line; the lease-reconcile subcommand auto-reconciles stuck `review:fixing` PR leases \u2014 re-applying `review:needs-worker` on an orphaned lease (fix-list stale, no worker report) so the Phase B1 drain retries, and removing `review:needs-worker` on a consumed-but-uncleared wedge (branch HEAD advanced past the fix-list, marker still set, no worker report) so the reviewer confirm pass can merge, always posting an audit-trail note comment and emitting a single `LEASE_RECONCILE orphaned=N consumed_uncleared=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, folds in the lease-reconcile sweep, and emits a `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line followed by the `LEASE_RECONCILE` line.",
16359
16451
  content: buildCheckBlockedScript(tiers, scopeGate, runRatio)
16360
16452
  };
16361
16453
  }
@@ -17037,14 +17129,20 @@ var orchestratorSubAgent = {
17037
17129
  "The script emits one summary line in this shape:",
17038
17130
  "",
17039
17131
  "```",
17040
- "TRIAGE_DONE unblocked=<N> still_blocked=<M>",
17132
+ "TRIAGE_DONE unblocked=<N> still_blocked=<M> deferred_skipped=<K>",
17041
17133
  "```",
17042
17134
  "",
17043
17135
  "Per-issue informational lines (`UNBLOCKED #N`, `UNBLOCK_FAILED #N`,",
17044
- "`STILL_BLOCKED #N`, `BLOCKED #N \u2014 no Depends on field found`) are",
17045
- "emitted for log visibility but are **not** load-bearing for the",
17046
- "orchestrator \u2014 partial failures (one bad `gh` call) do not abort",
17047
- "the sweep, they are simply counted toward `still_blocked`.",
17136
+ "`STILL_BLOCKED #N`, `SKIP_DEFERRED #N`, `BLOCKED #N \u2014 no Depends on",
17137
+ "field found`) are emitted for log visibility but are **not**",
17138
+ "load-bearing for the orchestrator \u2014 partial failures (one bad `gh`",
17139
+ "call) do not abort the sweep, they are simply counted toward",
17140
+ "`still_blocked`.",
17141
+ "",
17142
+ "`deferred_skipped` counts candidates the sweep deliberately left",
17143
+ "blocked because they carry `status:deferred`. Those issues are",
17144
+ "human-parked: no agent or sweep ever removes `status:deferred`, so",
17145
+ "a non-zero count is expected steady-state noise, not a failure.",
17048
17146
  "",
17049
17147
  "This phase is the **fallback safety net** for agent-driven",
17050
17148
  "unblocking. Every agent that applies `status:done` already runs",
@@ -18224,9 +18322,11 @@ var checkBlockedCommand = {
18224
18322
  "reference, applies the `status:blocked` \u2192 `status:ready` label flip",
18225
18323
  "itself, posts the canned `Dependencies resolved \u2014 unblocking.`",
18226
18324
  "comment, and emits a single",
18227
- "`TRIAGE_DONE unblocked=<N> still_blocked=<M>` summary line. Per-issue",
18228
- "informational lines (`UNBLOCKED`, `UNBLOCK_FAILED`, `STILL_BLOCKED`)",
18229
- "are also emitted for log visibility.",
18325
+ "`TRIAGE_DONE unblocked=<N> still_blocked=<M> deferred_skipped=<K>`",
18326
+ "summary line. Candidates carrying `status:deferred` are skipped",
18327
+ "rather than promoted \u2014 only a human clears that label. Per-issue",
18328
+ "informational lines (`UNBLOCKED`, `UNBLOCK_FAILED`, `STILL_BLOCKED`,",
18329
+ "`SKIP_DEFERRED`) are also emitted for log visibility.",
18230
18330
  "",
18231
18331
  "Summarise the output (the `TRIAGE_DONE` counts and the first few",
18232
18332
  "per-issue lines) \u2014 do **not** apply additional label flips yourself;",