@ai-dossier/cli 0.53.0 → 0.54.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/README.md +35 -4
- package/dist/commands/classify.d.ts.map +1 -1
- package/dist/commands/classify.js +8 -2
- package/dist/commands/classify.js.map +1 -1
- package/dist/prescreen.d.ts +48 -5
- package/dist/prescreen.d.ts.map +1 -1
- package/dist/prescreen.js +195 -6
- package/dist/prescreen.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1016,9 +1016,11 @@ Prints a single JSON verdict — no model call anywhere, exits 0 for either verd
|
|
|
1016
1016
|
|
|
1017
1017
|
```json
|
|
1018
1018
|
{
|
|
1019
|
+
"schema": "prescreen:v2",
|
|
1019
1020
|
"issue": 538,
|
|
1020
1021
|
"state": "OPEN",
|
|
1021
|
-
"verdict": "
|
|
1022
|
+
"verdict": "candidate",
|
|
1023
|
+
"review": "full",
|
|
1022
1024
|
"reasons": [
|
|
1023
1025
|
{ "check": "text-floor", "message": "Title/body/labels match 'rule1-risk-floor-area' (keyword: 'terraform')." }
|
|
1024
1026
|
],
|
|
@@ -1040,9 +1042,11 @@ verdict still reflects whatever DID complete rather than blocking on the gap:
|
|
|
1040
1042
|
|
|
1041
1043
|
```json
|
|
1042
1044
|
{
|
|
1045
|
+
"schema": "prescreen:v2",
|
|
1043
1046
|
"issue": 538,
|
|
1044
1047
|
"state": null,
|
|
1045
1048
|
"verdict": "candidate",
|
|
1049
|
+
"review": "full",
|
|
1046
1050
|
"reasons": [],
|
|
1047
1051
|
"plan_artifact": null,
|
|
1048
1052
|
"degraded": true,
|
|
@@ -1051,18 +1055,45 @@ verdict still reflects whatever DID complete rather than blocking on the gap:
|
|
|
1051
1055
|
}
|
|
1052
1056
|
```
|
|
1053
1057
|
|
|
1054
|
-
`verdict: "full"` means an
|
|
1055
|
-
|
|
1058
|
+
`verdict: "full"` means an **excluding** floor hit was found — a hard-block label, an open
|
|
1059
|
+
dependency outside the submitted set, or (with a plan:v1 artifact) the path-based risk
|
|
1060
|
+
floor or more than 8 predicted files. The classifier should skip straight to posting
|
|
1061
|
+
`mode=full` with the recorded reason, no repo exploration needed.
|
|
1056
1062
|
`verdict: "candidate"` means proceed to the bounded mechanical-tier classify pass (issue
|
|
1057
1063
|
text + `reasons`/`warnings` as context, still no repo exploration unless that pass's
|
|
1058
1064
|
`confidence` lands below 0.6, which triggers the dossier's single mid-tier escalation).
|
|
1059
1065
|
|
|
1066
|
+
`review` is the review depth the issue needs, in the scheduler's per-member vocabulary
|
|
1067
|
+
(`light` | `full`, #771): `full` whenever any check found anything — and also when the
|
|
1068
|
+
issue itself could not be read (the fail-open path above stays `candidate`, but an unscanned
|
|
1069
|
+
issue is never reported `light`). A **text-floor** hit
|
|
1070
|
+
(risk keyword in the issue text) is `verdict: "candidate"` + `review: "full"` — the issue
|
|
1071
|
+
may join a batch, but as a full-review member (#770 Option A), not be excluded from it.
|
|
1072
|
+
|
|
1073
|
+
**Contract change — `prescreen:v1` → `prescreen:v2` (#772, CLI 0.54.0).** v1 (no
|
|
1074
|
+
`schema` key) returned `verdict: "full"` for a text-floor hit too; v2 returns
|
|
1075
|
+
`candidate` + `review: "full"` for it and adds the `schema` and `review` keys. A consumer
|
|
1076
|
+
that reads only `verdict` must also read `review` to keep routing risk-keyword issues to
|
|
1077
|
+
full-depth review. The text floor is also section-aware in v2: it scans the title, labels,
|
|
1078
|
+
and the body **minus** reference material — sections headed Related / References / See
|
|
1079
|
+
also / Links / Context / Background / Provenance / Origin; reference lines ("Related: #…",
|
|
1080
|
+
"Parent: #…", "Refs: …", "See also …"); provenance clauses that open a sentence ("Found by
|
|
1081
|
+
the #4103 security review.", "Discovered during…", "Follow-up to #…", "Split from #…" —
|
|
1082
|
+
stripped to the end of the clause, the rest of the line is kept); and link-only lines (a
|
|
1083
|
+
markdown link's text is kept, only its target is dropped) — in addition to the quoted spans
|
|
1084
|
+
#627 already blanked. A heading is ignored only when its whole text is one of those names
|
|
1085
|
+
("## Background jobs" is scope); `#` lines inside fenced code blocks are never headings.
|
|
1086
|
+
Mid-sentence the same words are prose ("the token leak is found during checkout") and are
|
|
1087
|
+
scanned. Other sections (Problem, Scope, Fix, …) are scanned; a sub-heading nested inside an
|
|
1088
|
+
ignored section stays ignored. `scripts/prescreen-backlog-measure.mjs --repo owner/name`
|
|
1089
|
+
measures v1 vs v2 over a repo's open backlog (read-only; prints no issue text).
|
|
1090
|
+
|
|
1060
1091
|
Coverage is deliberately partial — it catches the OBVIOUS floor hits, not all of them:
|
|
1061
1092
|
|
|
1062
1093
|
| Check | What it catches | Source |
|
|
1063
1094
|
|---|---|---|
|
|
1064
1095
|
| `hard-block-label` | `decision-pending`, `needs-clarification`, `epic`, `decomposed` | same policy as the `sched enqueue` pre-screen (#507) and the engine's per-tick re-check (#544), shared via `@ai-dossier/sched`'s `labels.ts` (re-exported by `cli/src/hard-block-labels.ts`) |
|
|
1065
|
-
| `text-floor` | A text-keyword approximation of RFC-0001 E.2 rules 1/3/4 (risk-floor area, new package/workspace, deploy pipeline) scanned over title + body + labels | `prescreen.ts`'s `TEXT_FLOOR_PATTERNS`; the matched keyword is named in the reason message |
|
|
1096
|
+
| `text-floor` | A text-keyword approximation of RFC-0001 E.2 rules 1/3/4 (risk-floor area, new package/workspace, deploy pipeline) scanned over title + reference-stripped body + labels — sets `review: full`, does **not** exclude | `prescreen.ts`'s `TEXT_FLOOR_PATTERNS` / `floorScanText`; the matched keyword is named in the reason message |
|
|
1066
1097
|
| `path-floor` | Rule 1's path-based risk floor, reusing `plan validate`'s `scanRiskFloor` (capped at 8 reasons — a plan:v1 artifact is comment-sourced, untrusted input) | requires a `plan:v1` artifact already on the issue |
|
|
1067
1098
|
| `file-count` | Rule 5, "Predicted files > 8" | requires a `plan:v1` artifact already on the issue |
|
|
1068
1099
|
| `open-dependency` | Rule 9, an open `Depends on #N` outside `--submitted-set` (capped at 8 reasons; refs themselves capped at 32 per issue — an issue body is untrusted input) | resolved via `gh issue view <N> --json state` |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkMzC,0EAA0E;AAC1E,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAM9D"}
|
|
@@ -59,15 +59,17 @@ function fetchPredictedFiles(issue, repo) {
|
|
|
59
59
|
return { status: 'absent' };
|
|
60
60
|
return { status: 'present', files: latest.artifact.predictedFiles };
|
|
61
61
|
}
|
|
62
|
-
/** The one JSON shape every path emits — success and failure alike carry the same
|
|
62
|
+
/** The one JSON shape every path emits (`schema: prescreen:v2`, #772) — success and failure alike carry the same keys, plus `degraded`/`warnings` when something didn't run cleanly. */
|
|
63
63
|
function emitVerdict(fields) {
|
|
64
|
-
const { issue, state, verdict, reasons, planArtifact, warnings } = fields;
|
|
64
|
+
const { issue, state, verdict, review, reasons, planArtifact, warnings } = fields;
|
|
65
65
|
for (const w of warnings)
|
|
66
66
|
console.error(`⚠ ${w}`);
|
|
67
67
|
console.log(JSON.stringify({
|
|
68
|
+
schema: prescreen_1.PRESCREEN_SCHEMA,
|
|
68
69
|
issue,
|
|
69
70
|
state,
|
|
70
71
|
verdict,
|
|
72
|
+
review,
|
|
71
73
|
reasons,
|
|
72
74
|
plan_artifact: planArtifact,
|
|
73
75
|
degraded: warnings.length > 0,
|
|
@@ -93,6 +95,9 @@ function registerPrescreenSubcommand(cmd) {
|
|
|
93
95
|
issue: Number(options.issue),
|
|
94
96
|
state: null,
|
|
95
97
|
verdict: 'candidate',
|
|
98
|
+
// Nothing was scanned — never claim "light". Fail open on exclusion (candidate) but
|
|
99
|
+
// fail safe on depth: an unread issue gets full review.
|
|
100
|
+
review: 'full',
|
|
96
101
|
reasons: [],
|
|
97
102
|
planArtifact: null,
|
|
98
103
|
warnings: [meta.error],
|
|
@@ -120,6 +125,7 @@ function registerPrescreenSubcommand(cmd) {
|
|
|
120
125
|
issue: Number(options.issue),
|
|
121
126
|
state: meta.state,
|
|
122
127
|
verdict: result.verdict,
|
|
128
|
+
review: result.review,
|
|
123
129
|
reasons: result.reasons,
|
|
124
130
|
planArtifact: predicted.status,
|
|
125
131
|
warnings,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"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"}
|
package/dist/prescreen.d.ts
CHANGED
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
* a plan artifact, rule 10 confidence) falls through to the classifier's own bounded
|
|
13
13
|
* mechanical-tier pass, which is the intended safety net — not a gap this module needs to close.
|
|
14
14
|
*
|
|
15
|
+
* v2 (#772, `PRESCREEN_SCHEMA`): two outputs. `verdict: full` only for the EXCLUDING checks
|
|
16
|
+
* (hard-block label, open dependency, plan:v1 path floor, >8 predicted files); any finding —
|
|
17
|
+
* a text-floor keyword hit included — sets `review: full`. A text-floor hit alone is a batchable
|
|
18
|
+
* `candidate` reviewed at full depth (#770 Option A), and the text floor scans the change
|
|
19
|
+
* surface only (`floorScanText`: reference sections/lines and provenance clauses removed).
|
|
20
|
+
*
|
|
15
21
|
* Pure and dependency-free (no `gh`, network, or fs), same discipline as `plan-artifact.ts` and
|
|
16
22
|
* `runstate.ts` — unit-testable directly. Subprocess access (fetching the issue, resolving
|
|
17
23
|
* dependency state, filtering by submitted set) lives in the command layer (`commands/classify.ts`).
|
|
@@ -20,7 +26,7 @@
|
|
|
20
26
|
export interface TextFloorPattern {
|
|
21
27
|
/** Reported in the reason; also the RFC-0001 E.2 rule it approximates. */
|
|
22
28
|
name: string;
|
|
23
|
-
/** Matched case-insensitively against title + body + label names
|
|
29
|
+
/** Matched case-insensitively against {@link floorScanText} (title + reference-stripped body + label names). Returns the matched keyword, or null. */
|
|
24
30
|
match: (text: string) => string | null;
|
|
25
31
|
}
|
|
26
32
|
export declare const TEXT_FLOOR_PATTERNS: readonly TextFloorPattern[];
|
|
@@ -39,7 +45,10 @@ export declare const TEXT_FLOOR_PATTERNS: readonly TextFloorPattern[];
|
|
|
39
45
|
* issues are rejected by text-floor alone, including genuine risk-floor cases
|
|
40
46
|
* (#3403 `terraform`, #3901 `authorization`). That change would have gutted the
|
|
41
47
|
* deterministic rejection rate the pre-screen exists to provide, and #538's
|
|
42
|
-
* cost saving with it.
|
|
48
|
+
* cost saving with it. (#772 later made that move deliberately — but not as
|
|
49
|
+
* "advisory": a text-floor hit still costs no model call and now carries
|
|
50
|
+
* `review: full`, so the genuine risk-floor cases are reviewed at full depth
|
|
51
|
+
* inside a batch instead of being excluded from one. See `PRESCREEN_SCHEMA`.)
|
|
43
52
|
*
|
|
44
53
|
* Stripping quoted spans, by contrast, leaves all 15 fixture verdicts
|
|
45
54
|
* unchanged — the true positives name their risk surface in prose, not in
|
|
@@ -51,6 +60,22 @@ export declare const TEXT_FLOOR_PATTERNS: readonly TextFloorPattern[];
|
|
|
51
60
|
* the same line, so a lone `"` blanks nothing.
|
|
52
61
|
*/
|
|
53
62
|
export declare function stripQuotedSpans(text: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* #772: the issue body with reference material removed — the part a text-floor keyword may
|
|
65
|
+
* legitimately fire on. Removes: sections under an {@link IGNORED_SECTION_HEADING_RE} heading
|
|
66
|
+
* (fence-aware — a `#` comment inside a code block is never a heading), reference lines
|
|
67
|
+
* ({@link REFERENCE_LINE_RE}), link-only lines, and sentence-opening provenance clauses
|
|
68
|
+
* ({@link PROVENANCE_CLAUSE_RE}). Quoted spans are handled separately by {@link stripQuotedSpans}
|
|
69
|
+
* (#627). Pure; line count is preserved (dropped lines become empty) so `stripQuotedSpans`'s
|
|
70
|
+
* same-line bound behaves exactly as before.
|
|
71
|
+
*/
|
|
72
|
+
export declare function stripReferenceMaterial(body: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* The exact text the text floor scans (#772): title + section/provenance-filtered body + label
|
|
75
|
+
* names, with quoted spans blanked (#627). Exported so measurement tooling
|
|
76
|
+
* (`scripts/prescreen-backlog-measure.mjs`) and tests see precisely what the rule sees.
|
|
77
|
+
*/
|
|
78
|
+
export declare function floorScanText(title: string, body: string, labels: readonly string[]): string;
|
|
54
79
|
/** `Depends on #N` references resolved per issue; each costs a `gh` call downstream (command layer), same rationale as `MAX_ISSUE_SELECTION` (`issue-selection.ts`). */
|
|
55
80
|
export declare const MAX_DEPENDENCY_REFS = 32;
|
|
56
81
|
/**
|
|
@@ -78,15 +103,33 @@ export interface PrescreenInput {
|
|
|
78
103
|
*/
|
|
79
104
|
openDependencies?: readonly number[];
|
|
80
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Version of the `classify prescreen` JSON contract (#772). v1 (implicit, pre-#772): any finding,
|
|
108
|
+
* text-floor included, meant `verdict: full`. v2: a text-floor hit is `verdict: candidate` +
|
|
109
|
+
* `review: full`; `verdict: full` is reserved for the checks that genuinely exclude an issue from
|
|
110
|
+
* a batch (hard-block label, open dependency, plan:v1 path floor, >8 predicted files).
|
|
111
|
+
*/
|
|
112
|
+
export declare const PRESCREEN_SCHEMA = "prescreen:v2";
|
|
81
113
|
export interface PrescreenVerdict {
|
|
82
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* `full` = an excluding floor hit (hard-block label, open dependency, plan:v1 path floor,
|
|
116
|
+
* >8 predicted files) — reject before any model call. `candidate` = proceed to the bounded
|
|
117
|
+
* mechanical-tier classify pass; read `review` for how deeply it must be reviewed.
|
|
118
|
+
*/
|
|
83
119
|
verdict: 'full' | 'candidate';
|
|
120
|
+
/**
|
|
121
|
+
* Review depth the issue needs, vocabulary shared with the scheduler's per-member `review`
|
|
122
|
+
* (#771): `full` when ANY floor finding exists — a text-floor keyword hit on a `candidate`
|
|
123
|
+
* means "batchable, but reviewed at full depth" (#770 Option A), not exclusion. `light` when
|
|
124
|
+
* no check found anything.
|
|
125
|
+
*/
|
|
126
|
+
review: 'light' | 'full';
|
|
84
127
|
/** Every check's finding, in evaluation order — not just the one that decided `verdict`. */
|
|
85
128
|
reasons: PrescreenReason[];
|
|
86
129
|
}
|
|
87
130
|
/**
|
|
88
|
-
* Run every deterministic check, in order, and record every hit —
|
|
89
|
-
*
|
|
131
|
+
* Run every deterministic check, in order, and record every hit — an excluding hit decides
|
|
132
|
+
* `verdict`, any hit decides `review`, and the caller (and the rationale a consumer posts) gets the full list, matching the existing
|
|
90
133
|
* "a verdict may hit several" precedent in `issue-cycle-classifier.ds.md`.
|
|
91
134
|
*/
|
|
92
135
|
export declare function prescreenIssue(input: PrescreenInput): PrescreenVerdict;
|
package/dist/prescreen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prescreen.d.ts","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prescreen.d.ts","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,6FAA6F;AAC7F,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,sJAAsJ;IACtJ,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACxC;AAwBD,eAAO,MAAM,mBAAmB,EAAE,SAAS,gBAAgB,EAmD1D,CAAC;AASF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAuHD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyC3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE5F;AAED,wKAAwK;AACxK,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAKtC;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAY5D;AAED,0FAA0F;AAC1F,MAAM,WAAW,eAAe;IAC9B,uGAAuG;IACvG,KAAK,EAAE,kBAAkB,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,iBAAiB,CAAC;IAC3F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,oGAAoG;IACpG,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAU/C,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B;;;;;OAKG;IACH,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,4FAA4F;IAC5F,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AA6BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,gBAAgB,CAgDtE"}
|
package/dist/prescreen.js
CHANGED
|
@@ -13,13 +13,21 @@
|
|
|
13
13
|
* a plan artifact, rule 10 confidence) falls through to the classifier's own bounded
|
|
14
14
|
* mechanical-tier pass, which is the intended safety net — not a gap this module needs to close.
|
|
15
15
|
*
|
|
16
|
+
* v2 (#772, `PRESCREEN_SCHEMA`): two outputs. `verdict: full` only for the EXCLUDING checks
|
|
17
|
+
* (hard-block label, open dependency, plan:v1 path floor, >8 predicted files); any finding —
|
|
18
|
+
* a text-floor keyword hit included — sets `review: full`. A text-floor hit alone is a batchable
|
|
19
|
+
* `candidate` reviewed at full depth (#770 Option A), and the text floor scans the change
|
|
20
|
+
* surface only (`floorScanText`: reference sections/lines and provenance clauses removed).
|
|
21
|
+
*
|
|
16
22
|
* Pure and dependency-free (no `gh`, network, or fs), same discipline as `plan-artifact.ts` and
|
|
17
23
|
* `runstate.ts` — unit-testable directly. Subprocess access (fetching the issue, resolving
|
|
18
24
|
* dependency state, filtering by submitted set) lives in the command layer (`commands/classify.ts`).
|
|
19
25
|
*/
|
|
20
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.MAX_DEPENDENCY_REFS = exports.TEXT_FLOOR_PATTERNS = void 0;
|
|
27
|
+
exports.PRESCREEN_SCHEMA = exports.MAX_DEPENDENCY_REFS = exports.TEXT_FLOOR_PATTERNS = void 0;
|
|
22
28
|
exports.stripQuotedSpans = stripQuotedSpans;
|
|
29
|
+
exports.stripReferenceMaterial = stripReferenceMaterial;
|
|
30
|
+
exports.floorScanText = floorScanText;
|
|
23
31
|
exports.extractDependencyRefs = extractDependencyRefs;
|
|
24
32
|
exports.prescreenIssue = prescreenIssue;
|
|
25
33
|
const hard_block_labels_1 = require("./hard-block-labels");
|
|
@@ -115,7 +123,10 @@ const MAX_QUOTED_SPAN = 120;
|
|
|
115
123
|
* issues are rejected by text-floor alone, including genuine risk-floor cases
|
|
116
124
|
* (#3403 `terraform`, #3901 `authorization`). That change would have gutted the
|
|
117
125
|
* deterministic rejection rate the pre-screen exists to provide, and #538's
|
|
118
|
-
* cost saving with it.
|
|
126
|
+
* cost saving with it. (#772 later made that move deliberately — but not as
|
|
127
|
+
* "advisory": a text-floor hit still costs no model call and now carries
|
|
128
|
+
* `review: full`, so the genuine risk-floor cases are reviewed at full depth
|
|
129
|
+
* inside a batch instead of being excluded from one. See `PRESCREEN_SCHEMA`.)
|
|
119
130
|
*
|
|
120
131
|
* Stripping quoted spans, by contrast, leaves all 15 fixture verdicts
|
|
121
132
|
* unchanged — the true positives name their risk surface in prose, not in
|
|
@@ -131,6 +142,166 @@ function stripQuotedSpans(text) {
|
|
|
131
142
|
.replace(new RegExp(`"[^"\\n]{0,${MAX_QUOTED_SPAN}}"`, 'g'), ' ')
|
|
132
143
|
.replace(new RegExp(`\`[^\`\\n]{0,${MAX_QUOTED_SPAN}}\``, 'g'), ' ');
|
|
133
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* #772: markdown section headings whose content is reference/provenance material, not the change
|
|
147
|
+
* surface — the whole section (to the next heading of the same or higher level) is dropped before
|
|
148
|
+
* the text floor runs. `Related`/`Context`/`Background` are the sections #772 names explicitly.
|
|
149
|
+
* A denylist on purpose: real issue bodies use arbitrary headings for their scope ("Problem",
|
|
150
|
+
* "What the user sees", "Fix"), so an allowlist of scope/requirements/acceptance headings would
|
|
151
|
+
* silently drop genuine scope. Matched against the WHOLE normalised heading text — "## Background
|
|
152
|
+
* jobs" or "## Origin validation" is scope, not reference material, and stays scanned.
|
|
153
|
+
*/
|
|
154
|
+
const IGNORED_SECTION_HEADING_RE = /^(?:related(?:\s+(?:issues?|prs?|work|links?|tickets?))?|references?|see\s+also|links|context|background|provenance|origin)$/i;
|
|
155
|
+
/**
|
|
156
|
+
* ATX markdown heading: 0–3 spaces, 1–6 `#`, then (optionally) whitespace + the heading text and an
|
|
157
|
+
* optional closing `#` run preceded by whitespace (CommonMark).
|
|
158
|
+
*/
|
|
159
|
+
const HEADING_RE = /^[ \t]{0,3}(#{1,6})(?:[ \t]+([^\n]*))?$/;
|
|
160
|
+
/** A fenced code block delimiter — a `#` line inside a fence is a shell comment, not a heading. */
|
|
161
|
+
const FENCE_RE = /^\s{0,3}(?:```|~~~)/;
|
|
162
|
+
/** Characters trimmed from the end of a heading: whitespace, `:`, emphasis, and a CommonMark closing `#` run. */
|
|
163
|
+
const HEADING_TRAILING_CHARS = ' \t\r\n\f\v:*_#';
|
|
164
|
+
/** Heading text with leading emoji/emphasis/punctuation and trailing `:`/emphasis/closing `#`s removed. */
|
|
165
|
+
function normaliseHeading(text) {
|
|
166
|
+
// Trailing trim by loop, not `/[…]+$/` — that regex is quadratic on a long whitespace run
|
|
167
|
+
// (untrusted issue body; #772 security review).
|
|
168
|
+
const trimmed = text.replace(/^[^\p{L}\p{N}]+/u, '');
|
|
169
|
+
let end = trimmed.length;
|
|
170
|
+
while (end > 0 && HEADING_TRAILING_CHARS.includes(trimmed[end - 1]))
|
|
171
|
+
end--;
|
|
172
|
+
return trimmed.slice(0, end);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Line-leading markdown decoration split off before the provenance tests: whitespace, blockquote
|
|
176
|
+
* `>`, list markers (`-`, `*`, `+`, `1.`), task boxes, and emphasis (`**`, `_`). Deliberately
|
|
177
|
+
* conservative — anything it does not strip only makes a provenance line LESS likely to be
|
|
178
|
+
* recognised, which errs toward scanning (the safe direction for a risk floor).
|
|
179
|
+
*/
|
|
180
|
+
const LINE_DECORATION_RE = /^(?:\s|>|[-*+](?=\s)|\d+[.)](?=\s)|\[[ xX]\]|\*\*|__|\*|_)*/;
|
|
181
|
+
/** Compile a phrase list into one alternation (each phrase escaped, whitespace-insensitive). */
|
|
182
|
+
function alternation(phrases) {
|
|
183
|
+
return phrases.map((p) => phrase(p).replace(/-/g, '[\\s-]?')).join('|');
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* #772: a line that STARTS with one of these markers is a pure reference line — "Parent: #770",
|
|
187
|
+
* "Related: #12", "Refs: #1709 …", "See also #10" — and is dropped whole. `related` needs a colon
|
|
188
|
+
* or a ref after it: "Related billing webhooks also fail" is scope prose.
|
|
189
|
+
*/
|
|
190
|
+
const REFERENCE_LINE_LEADS = [
|
|
191
|
+
'related:',
|
|
192
|
+
'related to #',
|
|
193
|
+
'related #',
|
|
194
|
+
'parent:',
|
|
195
|
+
'refs:',
|
|
196
|
+
'ref:',
|
|
197
|
+
'see also',
|
|
198
|
+
'provenance:',
|
|
199
|
+
];
|
|
200
|
+
const REFERENCE_LINE_RE = new RegExp(`^(?:${REFERENCE_LINE_LEADS.map((l) => phrase(l).replace(/:$/, '\\s*:')).join('|')})`, 'i');
|
|
201
|
+
/**
|
|
202
|
+
* #772: provenance phrases — where the issue came from, not what it touches ("Found by the #4103
|
|
203
|
+
* security review", "Follow-up to #4314", "Split from #99"). A clause that OPENS a sentence (line
|
|
204
|
+
* start, or after `.`/`;`/`!`/`?`) with one of these is stripped to the end of its clause (`.`, `;`,
|
|
205
|
+
* `!`, `?`, `,` or a dash followed by whitespace, or end of line) — so "Found by the #4103 review.
|
|
206
|
+
* Rotate the Stripe secrets." keeps the second sentence. Mid-sentence the same words are ordinary
|
|
207
|
+
* prose ("the token leak is found during checkout") and are left alone. "found in"/"reported in"
|
|
208
|
+
* are NOT provenance — they say where the bug is.
|
|
209
|
+
*/
|
|
210
|
+
const PROVENANCE_LEADS = [
|
|
211
|
+
'found by',
|
|
212
|
+
'found during',
|
|
213
|
+
'discovered by',
|
|
214
|
+
'discovered during',
|
|
215
|
+
'discovered while',
|
|
216
|
+
'surfaced by',
|
|
217
|
+
'surfaced during',
|
|
218
|
+
'spotted by',
|
|
219
|
+
'reported by',
|
|
220
|
+
'filed while',
|
|
221
|
+
'filed from',
|
|
222
|
+
'filed during',
|
|
223
|
+
'follow-up to',
|
|
224
|
+
'follow-up of',
|
|
225
|
+
'split from',
|
|
226
|
+
'split out of',
|
|
227
|
+
'split off from',
|
|
228
|
+
'spun off from',
|
|
229
|
+
'spun out of',
|
|
230
|
+
];
|
|
231
|
+
const PROVENANCE_CLAUSE_RE = new RegExp(`(^|[.;!?]\\s+)(?:${alternation(PROVENANCE_LEADS)})\\b.*?(?=[.;!?,—–](?:\\s|$)|\\s-\\s|$)`, 'gi');
|
|
232
|
+
/**
|
|
233
|
+
* A line carrying nothing but references: URLs, bare `#N` / `owner/repo#N` refs, and separators.
|
|
234
|
+
* A markdown link keeps its TEXT ("[Migrate billing tables](…)" is scope) — only the target is
|
|
235
|
+
* erased. Checked by erasing every reference and separator and testing for an empty remainder.
|
|
236
|
+
*/
|
|
237
|
+
function isLinkOnlyLine(line) {
|
|
238
|
+
const remainder = line
|
|
239
|
+
.replace(/\[([^[\]\n]*)\]\([^()\n]*\)/g, ' $1 ')
|
|
240
|
+
.replace(/<?https?:\/\/[^\s>)]+>?/g, ' ')
|
|
241
|
+
.replace(/(?<![\w.-])[\w.-]+\/[\w.-]+#\d+\b/g, ' ')
|
|
242
|
+
.replace(/#\d+\b/g, ' ')
|
|
243
|
+
.replace(/[\s\-*+>•|,;:/()[\]&.–—]|\band\b|\bor\b/gi, '');
|
|
244
|
+
return remainder === '' && /\S/.test(line);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* #772: the issue body with reference material removed — the part a text-floor keyword may
|
|
248
|
+
* legitimately fire on. Removes: sections under an {@link IGNORED_SECTION_HEADING_RE} heading
|
|
249
|
+
* (fence-aware — a `#` comment inside a code block is never a heading), reference lines
|
|
250
|
+
* ({@link REFERENCE_LINE_RE}), link-only lines, and sentence-opening provenance clauses
|
|
251
|
+
* ({@link PROVENANCE_CLAUSE_RE}). Quoted spans are handled separately by {@link stripQuotedSpans}
|
|
252
|
+
* (#627). Pure; line count is preserved (dropped lines become empty) so `stripQuotedSpans`'s
|
|
253
|
+
* same-line bound behaves exactly as before.
|
|
254
|
+
*/
|
|
255
|
+
function stripReferenceMaterial(body) {
|
|
256
|
+
const out = [];
|
|
257
|
+
/** Heading level of the ignored section currently being skipped, or null. */
|
|
258
|
+
let skipLevel = null;
|
|
259
|
+
let inFence = false;
|
|
260
|
+
for (const line of body.split('\n')) {
|
|
261
|
+
if (FENCE_RE.test(line)) {
|
|
262
|
+
inFence = !inFence;
|
|
263
|
+
out.push(skipLevel === null ? line : '');
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const heading = inFence ? null : HEADING_RE.exec(line);
|
|
267
|
+
if (heading) {
|
|
268
|
+
const level = heading[1].length;
|
|
269
|
+
if (skipLevel !== null && level > skipLevel) {
|
|
270
|
+
out.push('');
|
|
271
|
+
continue; // a sub-heading inside an ignored section stays ignored
|
|
272
|
+
}
|
|
273
|
+
skipLevel = IGNORED_SECTION_HEADING_RE.test(normaliseHeading(heading[2] ?? ''))
|
|
274
|
+
? level
|
|
275
|
+
: null;
|
|
276
|
+
out.push(skipLevel === null ? line : '');
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (skipLevel !== null) {
|
|
280
|
+
out.push('');
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (inFence) {
|
|
284
|
+
out.push(line);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const decoration = LINE_DECORATION_RE.exec(line)?.[0] ?? '';
|
|
288
|
+
const content = line.slice(decoration.length);
|
|
289
|
+
if (REFERENCE_LINE_RE.test(content) || isLinkOnlyLine(content)) {
|
|
290
|
+
out.push('');
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
out.push(decoration + content.replace(PROVENANCE_CLAUSE_RE, '$1 '));
|
|
294
|
+
}
|
|
295
|
+
return out.join('\n');
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* The exact text the text floor scans (#772): title + section/provenance-filtered body + label
|
|
299
|
+
* names, with quoted spans blanked (#627). Exported so measurement tooling
|
|
300
|
+
* (`scripts/prescreen-backlog-measure.mjs`) and tests see precisely what the rule sees.
|
|
301
|
+
*/
|
|
302
|
+
function floorScanText(title, body, labels) {
|
|
303
|
+
return stripQuotedSpans(`${title}\n${stripReferenceMaterial(body)}\n${labels.join(' ')}`);
|
|
304
|
+
}
|
|
134
305
|
/** `Depends on #N` references resolved per issue; each costs a `gh` call downstream (command layer), same rationale as `MAX_ISSUE_SELECTION` (`issue-selection.ts`). */
|
|
135
306
|
exports.MAX_DEPENDENCY_REFS = 32;
|
|
136
307
|
/** `Depends on #N` (case-insensitive) — the same phrasing gate-issue and the classifier dossier parse. */
|
|
@@ -154,6 +325,20 @@ function extractDependencyRefs(text) {
|
|
|
154
325
|
}
|
|
155
326
|
return refs;
|
|
156
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Version of the `classify prescreen` JSON contract (#772). v1 (implicit, pre-#772): any finding,
|
|
330
|
+
* text-floor included, meant `verdict: full`. v2: a text-floor hit is `verdict: candidate` +
|
|
331
|
+
* `review: full`; `verdict: full` is reserved for the checks that genuinely exclude an issue from
|
|
332
|
+
* a batch (hard-block label, open dependency, plan:v1 path floor, >8 predicted files).
|
|
333
|
+
*/
|
|
334
|
+
exports.PRESCREEN_SCHEMA = 'prescreen:v2';
|
|
335
|
+
/** Checks whose hit excludes the issue from batching outright (`verdict: full`). */
|
|
336
|
+
const EXCLUDING_CHECKS = new Set([
|
|
337
|
+
'hard-block-label',
|
|
338
|
+
'open-dependency',
|
|
339
|
+
'path-floor',
|
|
340
|
+
'file-count',
|
|
341
|
+
]);
|
|
157
342
|
/** Predicted files count above which RFC-0001 E.2 rule 5 ("Predicted files > 8") fires. */
|
|
158
343
|
const MAX_PREDICTED_FILES = 8;
|
|
159
344
|
/**
|
|
@@ -178,8 +363,8 @@ function sanitize(value) {
|
|
|
178
363
|
: cleaned;
|
|
179
364
|
}
|
|
180
365
|
/**
|
|
181
|
-
* Run every deterministic check, in order, and record every hit —
|
|
182
|
-
*
|
|
366
|
+
* Run every deterministic check, in order, and record every hit — an excluding hit decides
|
|
367
|
+
* `verdict`, any hit decides `review`, and the caller (and the rationale a consumer posts) gets the full list, matching the existing
|
|
183
368
|
* "a verdict may hit several" precedent in `issue-cycle-classifier.ds.md`.
|
|
184
369
|
*/
|
|
185
370
|
function prescreenIssue(input) {
|
|
@@ -191,7 +376,7 @@ function prescreenIssue(input) {
|
|
|
191
376
|
message: `Carries hard-block label '${sanitize(hardBlockLabel)}'.`,
|
|
192
377
|
});
|
|
193
378
|
}
|
|
194
|
-
const text =
|
|
379
|
+
const text = floorScanText(input.title, input.body, input.labels);
|
|
195
380
|
for (const pattern of exports.TEXT_FLOOR_PATTERNS) {
|
|
196
381
|
const hit = pattern.match(text);
|
|
197
382
|
if (hit !== null) {
|
|
@@ -220,6 +405,10 @@ function prescreenIssue(input) {
|
|
|
220
405
|
message: `Depends on #${dep}, which is open and outside the submitted set (rule9-open-dependency).`,
|
|
221
406
|
});
|
|
222
407
|
}
|
|
223
|
-
return {
|
|
408
|
+
return {
|
|
409
|
+
verdict: reasons.some((r) => EXCLUDING_CHECKS.has(r.check)) ? 'full' : 'candidate',
|
|
410
|
+
review: reasons.length > 0 ? 'full' : 'light',
|
|
411
|
+
reasons,
|
|
412
|
+
};
|
|
224
413
|
}
|
|
225
414
|
//# sourceMappingURL=prescreen.js.map
|
package/dist/prescreen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-dossier/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "Create, verify, sign, publish, and run dossiers — portable, signed, versioned skills for any LLM tool. The dossier ⇄ Claude Code skill bridge (install-skill / skill-export).",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|