pi-gauntlet 5.3.3 → 5.3.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.3.5 - 2026-09-08
4
+
5
+ - `linear`: section 3 gains a `Download` row (`linearis files download <url> --output <path>`); section 8 gains a row for the linearis 2026.7.0/2026.8.0 Bearer-prefix bug on personal API keys (a 401 on `files download` while `issues read` works is not an auth problem - do not re-auth; [linearis-oss/linearis#300](https://github.com/linearis-oss/linearis/issues/300)), and the generic 401 row defers to it.
6
+
7
+ ## v5.3.4 - 2026-09-07
8
+
9
+ - `spec-council-member`, `spec-council-synthesizer`, `conformance-reviewer`: the `over-spec` rules rewritten as short numbered imperatives so smaller council/closure models follow them; no semantic change (verified by an independent parity review).
10
+
3
11
  ## v5.3.3 - 2026-09-07
4
12
 
5
13
  - Subtractive review pass: `spec-council-member` gains the `over-spec` finding kind (three-leg predicate: outside the problem, unrequested by human input, unnecessary to deliver; never cuts verbatim human input) and a mandatory `lean:` close line; `spec-council-synthesizer` preserves `over-spec:` clusters, adjudicates them against leg-3 rebuttals only, and tallies `lean:`. `roasting-the-spec` passes the verbatim human input to members and chair, requires `^lean:` in both probes, and applies an accepted over-spec cluster as a cut with an `Applied: over-spec: ... -> cut (was adds: ...)` audit line; `shape-ticket`'s probe follows. Closure: `conformance-reviewer` reports spec-laundered excess once as `UNAUTHORIZED` (origin literal unchanged; provenance in `evidence:`), and `UNAUTHORIZED` rows now follow `recommended:` like every other verdict - contained removals auto-run in the fix loop with the spec path added to `touched-files`. `scripts/ci.mjs` pins the new tokens and the retired always-defer rule. Spec: `doc/specs/2026-09-06-subtractive-review-pass.md`.
@@ -32,10 +32,16 @@ Work flows `origin (prompt + spec) → plan → code/doc`. Every hop is lossy: a
32
32
 
33
33
  1. **Reconstruct the origin.** Read the spec and the verbatim original prompt. Extract a flat list of every requirement: explicit acceptance criteria / spec clauses **+** quotable notes - written sentences you can quote verbatim (ticket body, comments); never derived inferences **+** any requirement stated inline in the prompt but never written into the spec.
34
34
 
35
- One exception to "spec is canonical" and to the "this could be cleaner" guard below: a spec clause that is (1) obviously outside the stated problem, (2) required by no human input you hold - the verbatim prompt, the ticket, or a human decision the spec records (e.g. "user chose X") - and (3) not necessary to deliver the feature correctly (necessity beats leanness: a clause another requirement needs is not excess, even if unrequested) is **not** an `Rn`. Report it once, as an `UNAUTHORIZED` row - never as `DELIVERED`, never also as origin drift. Leg 2 uncertain -> it stays an `Rn`. The test is that three-leg predicate, not taste.
35
+ Exception - a spec clause is **not** an `Rn` when all three are true:
36
+
37
+ 1. It is clearly outside the stated problem.
38
+ 2. No human input asks for it - not the prompt, not the ticket, not a decision the spec records ("user chose X").
39
+ 3. The feature ships correctly without it. If another requirement needs it, keep it.
40
+
41
+ Report such a clause once, as `UNAUTHORIZED` (not `DELIVERED`, not origin drift). Unsure on 2 -> keep it as an `Rn`. This is the only exception to "spec is canonical"; "could be cleaner" is still not a reason.
36
42
  2. **Check origin drift.** If the spec and the prompt/ticket disagree, do **not** absorb it silently. A deviation recorded in the spec → spec wins (it was review-gated). An *unrecorded* divergence → the spec silently dropped or altered a requirement = a conformance failure to report.
37
43
  3. **Map each requirement to the deliverable.** Read the diff (code **and** docs) yourself — do not trust any summary. For each requirement, find where it is satisfied and cite real `file:line` evidence. Run read-only checks (tests, grep) when they confirm a behavior; quote actual output.
38
- 4. **Flag the unrequested.** Anything shipped that no requirement in the origin asked for = `UNAUTHORIZED` (scope creep), even if it looks useful. Do not negotiate scope with yourself. `UNAUTHORIZED` covers both surface with no origin at all and spec-laundered excess per step 1; the `origin` literal stays `none (scope creep)` for both, and for the spec-laundered case `evidence:` opens with `spec "<section>" - "<clause>" (over-spec)` followed by the surface (files, specs) and the unprotected failure.
44
+ 4. **Flag the unrequested.** Anything shipped that no requirement in the origin asked for = `UNAUTHORIZED` (scope creep), even if it looks useful. Do not negotiate scope with yourself. This includes the step-1 exception clauses. `origin` is always `none (scope creep)`. For a step-1 clause, start `evidence:` with `spec "<section>" - "<clause>" (over-spec)`, then the files/specs it adds, then what fails without it.
39
45
  5. **Apply the coverage rule.** Default: one requirement source = one spec = code covering **every** requirement. Source and solution must end in sync. Multi-spec effort is allowed **only if the spec explicitly says** it covers a named subset and lists the deferred requirements; silent partial coverage is a failure.
40
46
 
41
47
  ## Output format
@@ -125,7 +131,8 @@ serial waves — identical to planned-execution wave grouping. Runtime-resource
125
131
  `recommended` is a proposal; you never decide, edit, dispatch, or re-audit.
126
132
 
127
133
  - Default `fix` for every `PARTIAL` / `MISSING` / `DRIFTED` row.
128
- - For every `UNAUTHORIZED` row: `fix` only when removal is **contained** and, for the over-spec shape, leg 2 is established. Contained = no other `Rn`'s `evidence` `file:line` lives in the code/test/helper files being deleted (the spec clause itself never un-contains). List the deletions and the unaffected `Rn` rows in `remediation`; for the over-spec shape the deletions include the spec clause/AC line. Otherwise `accept`, with a human-voice, example-driven recommendation in `remediation`: what it costs, where it came from, what breaks if cut and what already covers that, then "I'd cut it" / "I'd keep it" with the condition that flips it. A bare provenance line is not a recommendation. `accept` for the over-spec shape means keep code and clause; no spec write.
134
+ - `UNAUTHORIZED` -> `fix` only when both hold: no other `Rn` cites a `file:line` inside the code/test/helper files being deleted (the spec clause itself never blocks this), and no human input asked for it. In `remediation`, list the files to delete (for an over-spec clause, also the spec clause/AC line) and the `Rn` rows left untouched.
135
+ - `UNAUTHORIZED` otherwise -> `accept`. Write the recommendation in a human voice with a concrete example: what it costs, where it came from, what breaks without it and what already covers that, then "I'd cut it" or "I'd keep it" and the one condition that flips the call. Provenance alone is not a recommendation. `accept` = keep code and clause, no spec edit.
129
136
  - `rescope` only when the `origin` requirement is impractical to satisfy in this branch
130
137
  (`rescope` is inapplicable to `UNAUTHORIZED` — there is no requirement to defer).
131
138
 
@@ -47,15 +47,21 @@ findings:
47
47
  lean: nothing to cut | <N> over-spec findings above
48
48
  ```
49
49
 
50
- `<kind>` is one of: gap, oversimplification, ambiguity, scope, not-actionable, external-ref, other, over-spec. `scope` means under-scope or wrong problem; excess is `over-spec` only. Omit the `findings` bullets entirely if you have none - the `findings:` header stays, and `lean:` is always the line immediately after the header or its last bullet. `lean: nothing to cut` is a legitimate, expected answer for a tight spec; `<N>` is the count of `over-spec` bullets above it.
50
+ `<kind>` is one of: gap, oversimplification, ambiguity, scope, not-actionable, external-ref, other, over-spec. `scope` = too little or the wrong problem. `over-spec` = too much. No findings -> keep the `findings:` header, no bullets. `lean:` is always the last line; `<N>` = number of `over-spec` bullets. `lean: nothing to cut` is a normal answer.
51
51
 
52
- **`over-spec`.** A clause is `over-spec` only when **all three** hold: (1) it is obviously outside the stated problem; (2) no human input requires it - human input is the verbatim block the dispatch passes you (original prompt, ticket ACs, questionary answers, user chat), and verbatim human input is off-limits; (3) it is not necessary to deliver the feature correctly - LLM-discovered necessities pass this leg and are not findings. Any leg failing -> not a finding. Necessity beats leanness. When leg 2 cannot be established from the human input you hold - none was passed, or its coverage of the clause is unclear - the clause is not over-spec; with no human input at all, every clause fails leg 2 and the report closes `lean: nothing to cut`. Grammar, one line:
52
+ **`over-spec`.** Flag a clause only when all three are true:
53
+
54
+ 1. It is clearly outside the stated problem.
55
+ 2. Nothing in the `Human input` block of your task asks for it. Never flag text that appears in that block.
56
+ 3. The feature ships correctly without it. Needed-but-unasked is not a finding.
57
+
58
+ Any test fails -> not a finding. Unsure on 2 -> not a finding. `Human input` block missing or empty -> no over-spec findings, `lean: nothing to cut`. One line per finding:
53
59
 
54
60
  ```
55
61
  - [major|minor] over-spec @ "<quoted spec clause>" — no human input requires this (closest human input: "<quote>" | none); adds: <M> files / <N> tests / <K> ACs; if cut, unprotected: <failure | nothing> → cut | shrink to <replacement>
56
62
  ```
57
63
 
58
- `major` when the clause buys >= 1 new file or >= 3 tests, `minor` below; never `blocker` - an unneeded clause never makes a spec unsound. `adds:` is your estimate of the surface the clause mandates; `unprotected:` names the failure that goes uncaught if the clause is cut - `nothing` is itself the evidence. The `closest human input:` quote comes from the passed human-input block, never from the spec's own prose.
64
+ `major` = buys >= 1 new file or >= 3 tests; else `minor`; never `blocker`. `adds:` = your estimate of the surface the clause forces. `unprotected:` = the failure nobody catches once the clause is gone; `nothing` is a valid answer. `closest human input:` quotes the `Human input` block, never the spec.
59
65
 
60
66
  Finding: spec says "S6: compute a `checksum` over child names, expose `meta.checksum`, add a reconciliation job flagging mismatches"; the human input said "return the folder tree as JSON like the HTML view"; nothing else in the spec depends on S6 -> `- [major] over-spec @ "S6 ... reconciliation job" — no human input requires this (closest human input: "return the folder tree as JSON like the HTML view"); adds: 2 files / 6 tests / 1 AC; if cut, unprotected: nothing → cut`. Non-finding: spec adds `format: false` on three compliance route mounts; nobody asked, but without it `.json` suffixes 404 on those mounts, so the JSON view cannot be delivered - leg 3 fails, not over-spec.
61
67
 
@@ -17,7 +17,9 @@ You receive the problem statement, the path to the spec, and the explicit paths
17
17
  Your job has two parts:
18
18
 
19
19
  1. **Consolidate.** Merge overlapping findings, cluster them by theme, rank each cluster by the highest severity any member assigned it, and record which members raised it. Drop pure duplicates. A member may emit an empty or absent `findings` list (it judged the spec sound) — treat that as no findings from that member, not an error.
20
- 2. **Adjudicate — your most important job.** Where members disagree (one calls something a blocker, another says it is fine; or two propose conflicting edits), weigh both arguments and decide — favor a position backed by verifiable evidence (a member that checked the codebase) over unsupported assertion, and weigh the severity and likelihood of the consequence. Fold the winning position into a single suggested edit. Do not pass the disagreement to the reader as an open question. You have the final say on member-vs-member conflicts. When you overrule a member, keep a one-line note so the decision is auditable. An `over-spec` cluster loses only to a finding that **rebuts leg 3** of the over-spec predicate - shows the clause is load-bearing, i.e. cutting it causes a product or delivery failure. A spec-quality defect on the excess clause (unnamed algorithm, missing AC, ambiguity) does **not** protect it; the cut resolves that finding - record it in `resolved:`.
20
+ 2. **Adjudicate — your most important job.** Where members disagree (one calls something a blocker, another says it is fine; or two propose conflicting edits), weigh both arguments and decide — favor a position backed by verifiable evidence (a member that checked the codebase) over unsupported assertion, and weigh the severity and likelihood of the consequence. Fold the winning position into a single suggested edit. Do not pass the disagreement to the reader as an open question. You have the final say on member-vs-member conflicts. When you overrule a member, keep a one-line note so the decision is auditable.
21
+
22
+ An `over-spec` finding loses only to a member showing the clause is needed (cutting it breaks the product or the delivery). A quality complaint about the same clause (unnamed algorithm, missing AC, ambiguity) does not save it - the cut resolves that complaint; note it in `resolved:`.
21
23
 
22
24
  You do not decide what gets applied to the spec — that is the author's and the user's call. You produce one consolidated, conflict-free report.
23
25
 
@@ -37,8 +39,15 @@ Every cluster must be pre-resolved — never emit a raw "members disagree" item.
37
39
 
38
40
  When any member raises an `external-ref` finding (load-bearing external context the spec does not inline), surface it as its own cluster with the theme prefixed `external-ref:`, e.g. `- [major] external-ref: ticket AC #4 not inlined — raised-by: [<model>] — implementer needs the AC text the spec omits → inline AC #4 into the spec`. The cluster line has no `<kind>` field, so without this prefix the flag is absorbed into generic prose and the author cannot detect it for inlining.
39
41
 
40
- When any member raises an `over-spec` finding, surface it as its own cluster with the theme prefixed `over-spec:` and carry the bullet's `adds:` and `unprotected:` values verbatim in the cluster text (when members disagree, the maximum `adds:` and the most specific `unprotected:`), e.g. `- [major] over-spec: S6 checksum/reconciliation — adds: 2 files / 6 tests / 1 AC; unprotected: nothing — raised-by: [<model>] — no human input requires S6 → cut S6 and its AC`. Same reason as `external-ref:`: the cluster line has no `<kind>` field, and the author branches on the prefix to apply the cut. Normalize, do not reject: a bullet that quotes a spec clause and states cut/shrink intent is kept even if `adds:` or `unprotected:` is missing - write `unstated` for the missing value. Drop only bullets whose quoted clause is verbatim human input (checked against the human-input block in your task) or that quote no clause at all; one line each in `resolved:`. A member's `lean:` count that disagrees with its bullet count is noted in `resolved:` and the bullets are used.
42
+ `over-spec` findings get their own cluster, theme prefixed `over-spec:` (the author branches on that prefix, as with `external-ref:`). Rules:
43
+
44
+ - Copy `adds:` and `unprotected:` into the cluster line. Members disagree -> largest `adds:`, most specific `unprotected:`.
45
+ - Missing `adds:` or `unprotected:` -> keep the finding, write `unstated`.
46
+ - Drop a finding only if its quoted clause appears in the `Human input` block, or it quotes no clause. One line in `resolved:` per drop.
47
+ - A member's `lean:` count disagrees with its bullets -> trust the bullets, note it in `resolved:`.
48
+
49
+ Example: `- [major] over-spec: S6 checksum/reconciliation — adds: 2 files / 6 tests / 1 AC; unprotected: nothing — raised-by: [<model>] — no human input requires S6 → cut S6 and its AC`
41
50
 
42
- The `lean:` line is mandatory: `k` = members whose report says `lean: nothing to cut`, `n` = members you received.
51
+ `lean:` is mandatory: `k` = members that wrote `lean: nothing to cut`, `n` = members you received.
43
52
 
44
53
  Attribute each cluster's `raised-by` using the model slug in each member's filename (e.g. `member-0-<slug>.md` → `<slug>`). If every member returned empty findings, emit `clusters:` with no bullets and set `consensus:` to `sound — no findings`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "5.3.3",
3
+ "version": "5.3.5",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "author": "Jacek Juraszek",
6
6
  "type": "module",
@@ -108,6 +108,7 @@ treated as absent.
108
108
  | Labels, teams, users, cycles | `linearis labels list`, `linearis teams list`, `linearis users list`, `linearis cycles list` | Use to resolve names to IDs; see id-cache convention. |
109
109
  | Attachments | `linearis attachments create [<issue>] --url <url>` | Positional is optional (`--issue <issue>` alias); link-only, no inline render - see gotcha (d). |
110
110
  | Upload | `linearis files upload <file>` | Returns an `assetUrl` for inline embedding - see gotcha (d). |
111
+ | Download | `linearis files download <url> --output <path>` | `<url>` is an attachment/asset URL from `issues read --with-attachments`; asset URLs are short-lived (gotcha d). A 401 here while `issues read` works is not an auth problem - see section 8. |
111
112
 
112
113
  Workspace values above (`<default team>`, `<who>`, etc.) are placeholders bound to
113
114
  the override keys in section 2 - never a real urlKey, team prefix, or email.
@@ -190,7 +191,8 @@ Safety rules, in addition to the write gate above:
190
191
 
191
192
  | Symptom | Cause | Fix |
192
193
  |---|---|---|
193
- | 401 | Not authenticated / expired token | `linearis auth status`; re-auth. |
194
+ | 401 | Not authenticated / expired token | `linearis auth status`; re-auth - unless the download row below applies. |
195
+ | 401 on `files download` while `issues read` works | linearis 2026.7.0 and 2026.8.0 prepend `Bearer ` to personal API keys on file downloads ([linearis-oss/linearis#300](https://github.com/linearis-oss/linearis/issues/300)) | Not an auth problem - do not re-auth. Fetch the URL with the bare key, or use a version without the bug once one ships. |
194
196
  | Issue not found | Wrong workspace, or issue archived | Confirm workspace; check archived state. |
195
197
  | Status not found | Status name doesn't match the team's workflow states | List the team's states before setting one. |
196
198
  | Missing `--team` error on create | `--team` is required | Supply `--team <default team>`. |