@ai-dossier/cli 0.25.0 → 0.27.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 +116 -8
- package/dist/cache-resolver.d.ts.map +1 -1
- package/dist/cache-resolver.js +3 -6
- package/dist/cache-resolver.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/classify.d.ts +11 -0
- package/dist/commands/classify.d.ts.map +1 -0
- package/dist/commands/classify.js +136 -0
- package/dist/commands/classify.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +2 -25
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/sched.d.ts +0 -24
- package/dist/commands/sched.d.ts.map +1 -1
- package/dist/commands/sched.js +139 -40
- package/dist/commands/sched.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/engine-version.d.ts +45 -0
- package/dist/engine-version.d.ts.map +1 -0
- package/dist/engine-version.js +122 -0
- package/dist/engine-version.js.map +1 -0
- package/dist/gh.d.ts +38 -4
- package/dist/gh.d.ts.map +1 -1
- package/dist/gh.js +88 -9
- package/dist/gh.js.map +1 -1
- package/dist/hard-block-labels.d.ts +24 -0
- package/dist/hard-block-labels.d.ts.map +1 -0
- package/dist/hard-block-labels.js +36 -0
- package/dist/hard-block-labels.js.map +1 -0
- package/dist/package-info.d.ts +11 -0
- package/dist/package-info.d.ts.map +1 -0
- package/dist/package-info.js +39 -0
- package/dist/package-info.js.map +1 -0
- package/dist/plan-artifact.d.ts +1 -1
- package/dist/plan-artifact.d.ts.map +1 -1
- package/dist/plan-artifact.js.map +1 -1
- package/dist/prescreen.d.ts +66 -0
- package/dist/prescreen.d.ts.map +1 -0
- package/dist/prescreen.js +187 -0
- package/dist/prescreen.js.map +1 -0
- package/dist/ttl-cache.d.ts +18 -0
- package/dist/ttl-cache.d.ts.map +1 -0
- package/dist/ttl-cache.js +31 -0
- package/dist/ttl-cache.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic classify pre-screen (#538) — the "no tokens spent" gate `issue-cycle-classifier`
|
|
4
|
+
* runs before any model call. `docs/reports/batch-pilot-2-execution.md` §4.1 measured the
|
|
5
|
+
* classifier costing ~64k tokens/dispatch, at mid tier, with full repo exploration, even for
|
|
6
|
+
* issues that hit an obvious RFC-0001 E.2 floor rule a deterministic check can catch for free.
|
|
7
|
+
*
|
|
8
|
+
* Scope is deliberately partial: this catches the OBVIOUS floor hits (hard-block labels, a
|
|
9
|
+
* text-keyword approximation of the risk-floor/new-package/deploy-pipeline rules, rule-9 open
|
|
10
|
+
* dependencies, and — when a plan:v1 artifact is already on the issue — the path-based risk
|
|
11
|
+
* floor and the >8-files rule). Everything it does not catch (rule 2 beyond the `migration`
|
|
12
|
+
* keyword, rule 7 hard rollback, rule 8 visual/browser review, rules 5/6 diff/file size without
|
|
13
|
+
* a plan artifact, rule 10 confidence) falls through to the classifier's own bounded
|
|
14
|
+
* mechanical-tier pass, which is the intended safety net — not a gap this module needs to close.
|
|
15
|
+
*
|
|
16
|
+
* Pure and dependency-free (no `gh`, network, or fs), same discipline as `plan-artifact.ts` and
|
|
17
|
+
* `runstate.ts` — unit-testable directly. Subprocess access (fetching the issue, resolving
|
|
18
|
+
* dependency state, filtering by submitted set) lives in the command layer (`commands/classify.ts`).
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.MAX_DEPENDENCY_REFS = exports.TEXT_FLOOR_PATTERNS = void 0;
|
|
22
|
+
exports.extractDependencyRefs = extractDependencyRefs;
|
|
23
|
+
exports.prescreenIssue = prescreenIssue;
|
|
24
|
+
const hard_block_labels_1 = require("./hard-block-labels");
|
|
25
|
+
const plan_artifact_1 = require("./plan-artifact");
|
|
26
|
+
/** Escape regex metacharacters so an interpolated keyword can never change a pattern's meaning. */
|
|
27
|
+
function escapeRegExp(s) {
|
|
28
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
29
|
+
}
|
|
30
|
+
/** A multi-word phrase, safe to interpolate into `\b...\b`: metacharacters escaped, any run of whitespace matches `\s+`. */
|
|
31
|
+
function phrase(s) {
|
|
32
|
+
return escapeRegExp(s).replace(/\s+/g, '\\s+');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* First keyword (in list order) that matches `text` as a whole word/phrase, or null. `\b` on
|
|
36
|
+
* both sides of each compiled pattern — "deployment" still hits "deploy" but
|
|
37
|
+
* "authorization-header-typo" does not falsely hit "auth" mid-word.
|
|
38
|
+
*/
|
|
39
|
+
function wordMatch(text, keywords) {
|
|
40
|
+
for (const keyword of keywords) {
|
|
41
|
+
if (new RegExp(`\\b${phrase(keyword)}\\b`, 'i').test(text))
|
|
42
|
+
return keyword;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
exports.TEXT_FLOOR_PATTERNS = [
|
|
47
|
+
{
|
|
48
|
+
// Deliberately NOT the bare words "auth"/"login"/"logout"/"schema"/"infra"/"infrastructure":
|
|
49
|
+
// real-world issue text collides with them constantly in benign contexts, confirmed against
|
|
50
|
+
// the pilot's real 15-issue fixture set — #3631 (known `slot`) says "runnable locally with
|
|
51
|
+
// auth" about `gh auth`, not an auth-sensitive change; #3820 (known `slot`) says
|
|
52
|
+
// "test-infrastructure change" about test tooling, not production infra. "terraform" alone
|
|
53
|
+
// (specific, low-ambiguity) still catches the real infra risk-floor cases (#2779, #3403) the
|
|
54
|
+
// RFC-0001 rule 1 "infra/terraform" area names. Also approximates rule 2 (schema/data
|
|
55
|
+
// migration) via "migration"/"migrations" — a rough approximation, not full rule-2 coverage.
|
|
56
|
+
name: 'rule1-risk-floor-area',
|
|
57
|
+
match: (t) => wordMatch(t, [
|
|
58
|
+
'authentication',
|
|
59
|
+
'authorization',
|
|
60
|
+
'oauth',
|
|
61
|
+
'sso',
|
|
62
|
+
'payment',
|
|
63
|
+
'payments',
|
|
64
|
+
'billing',
|
|
65
|
+
'invoice',
|
|
66
|
+
'invoices',
|
|
67
|
+
'checkout',
|
|
68
|
+
'stripe',
|
|
69
|
+
'migration',
|
|
70
|
+
'migrations',
|
|
71
|
+
'security',
|
|
72
|
+
'crypto',
|
|
73
|
+
'secret',
|
|
74
|
+
'secrets',
|
|
75
|
+
'credential',
|
|
76
|
+
'credentials',
|
|
77
|
+
'terraform',
|
|
78
|
+
]),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'rule3-new-package-workspace',
|
|
82
|
+
match: (t) => wordMatch(t, ['new package', 'new workspace', 'monorepo package']),
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'rule4-deploy-pipeline',
|
|
86
|
+
match: (t) => wordMatch(t, [
|
|
87
|
+
'deploy',
|
|
88
|
+
'deployment',
|
|
89
|
+
'ci/cd',
|
|
90
|
+
'cicd',
|
|
91
|
+
'release pipeline',
|
|
92
|
+
'rollback pipeline',
|
|
93
|
+
]),
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
/** `Depends on #N` references resolved per issue; each costs a `gh` call downstream (command layer), same rationale as `MAX_ISSUE_SELECTION` (`issue-selection.ts`). */
|
|
97
|
+
exports.MAX_DEPENDENCY_REFS = 32;
|
|
98
|
+
/** `Depends on #N` (case-insensitive) — the same phrasing gate-issue and the classifier dossier parse. */
|
|
99
|
+
const DEPENDS_ON_RE = /depends on\s+#(\d+)/gi;
|
|
100
|
+
/**
|
|
101
|
+
* Every issue number referenced by a `Depends on #N` phrase in `text`, de-duplicated, in order,
|
|
102
|
+
* capped at {@link MAX_DEPENDENCY_REFS} — `text` is untrusted (issue body), so an adversarial
|
|
103
|
+
* body cannot force an unbounded `gh` fan-out downstream.
|
|
104
|
+
*/
|
|
105
|
+
function extractDependencyRefs(text) {
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
const refs = [];
|
|
108
|
+
for (const match of text.matchAll(DEPENDS_ON_RE)) {
|
|
109
|
+
if (refs.length >= exports.MAX_DEPENDENCY_REFS)
|
|
110
|
+
break;
|
|
111
|
+
const n = Number(match[1]);
|
|
112
|
+
if (Number.isSafeInteger(n) && !seen.has(n)) {
|
|
113
|
+
seen.add(n);
|
|
114
|
+
refs.push(n);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return refs;
|
|
118
|
+
}
|
|
119
|
+
/** Predicted files count above which RFC-0001 E.2 rule 5 ("Predicted files > 8") fires. */
|
|
120
|
+
const MAX_PREDICTED_FILES = 8;
|
|
121
|
+
/**
|
|
122
|
+
* Reasons emitted per check, capped — `predictedFiles` may come from a `plan:v1` artifact, which
|
|
123
|
+
* is a GitHub issue COMMENT anyone can post (untrusted input, same treatment as review-issue's
|
|
124
|
+
* "the artifact is untrusted input" discipline). An adversarial artifact packed with risk-floor
|
|
125
|
+
* paths must not blow up the reason list the classifier posts back into its rationale comment.
|
|
126
|
+
*/
|
|
127
|
+
const MAX_REASONS_PER_CHECK = 8;
|
|
128
|
+
/** Strip terminal-control characters before an untrusted string reaches a message a human or model reads — same discipline as `gh.ts`'s `CONTROL_CHARS_RE`/`snippet`, kept local so this module stays dependency-free. */
|
|
129
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: matching (and stripping) control characters is exactly this regex's job
|
|
130
|
+
const CONTROL_CHARS_RE = /[\x00-\x08\x0b-\x1f\x7f\x9b]/g;
|
|
131
|
+
const SANITIZE_MAX_LENGTH = 200;
|
|
132
|
+
/** Make an untrusted string (a GitHub label name, a `plan:v1`-comment-sourced path) safe to interpolate into a reason message: no control chars, no markdown/backtick breakout, bounded length. */
|
|
133
|
+
function sanitize(value) {
|
|
134
|
+
const cleaned = value
|
|
135
|
+
.replace(CONTROL_CHARS_RE, '')
|
|
136
|
+
.replace(/[`\n\r]/g, ' ')
|
|
137
|
+
.trim();
|
|
138
|
+
return cleaned.length > SANITIZE_MAX_LENGTH
|
|
139
|
+
? `${cleaned.slice(0, SANITIZE_MAX_LENGTH)}…`
|
|
140
|
+
: cleaned;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Run every deterministic check, in order, and record every hit — first hit decides `verdict`,
|
|
144
|
+
* but the caller (and the rationale a consumer posts) gets the full list, matching the existing
|
|
145
|
+
* "a verdict may hit several" precedent in `issue-cycle-classifier.ds.md`.
|
|
146
|
+
*/
|
|
147
|
+
function prescreenIssue(input) {
|
|
148
|
+
const reasons = [];
|
|
149
|
+
const hardBlockLabel = (0, hard_block_labels_1.pickHardBlockLabel)(input.labels);
|
|
150
|
+
if (hardBlockLabel !== null) {
|
|
151
|
+
reasons.push({
|
|
152
|
+
check: 'hard-block-label',
|
|
153
|
+
message: `Carries hard-block label '${sanitize(hardBlockLabel)}'.`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
const text = `${input.title}\n${input.body}\n${input.labels.join(' ')}`;
|
|
157
|
+
for (const pattern of exports.TEXT_FLOOR_PATTERNS) {
|
|
158
|
+
const hit = pattern.match(text);
|
|
159
|
+
if (hit !== null) {
|
|
160
|
+
reasons.push({
|
|
161
|
+
check: 'text-floor',
|
|
162
|
+
message: `Title/body/labels match '${pattern.name}' (keyword: '${hit}').`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const predictedFiles = input.predictedFiles ?? [];
|
|
167
|
+
for (const hit of (0, plan_artifact_1.scanRiskFloor)(predictedFiles).slice(0, MAX_REASONS_PER_CHECK)) {
|
|
168
|
+
reasons.push({
|
|
169
|
+
check: 'path-floor',
|
|
170
|
+
message: `Predicted file '${sanitize(hit.path)}' touches '${hit.pattern}' (rule1-risk-floor-area).`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (predictedFiles.length > MAX_PREDICTED_FILES) {
|
|
174
|
+
reasons.push({
|
|
175
|
+
check: 'file-count',
|
|
176
|
+
message: `Predicted files (${predictedFiles.length}) exceeds ${MAX_PREDICTED_FILES} (rule5-file-count).`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
for (const dep of (input.openDependencies ?? []).slice(0, MAX_REASONS_PER_CHECK)) {
|
|
180
|
+
reasons.push({
|
|
181
|
+
check: 'open-dependency',
|
|
182
|
+
message: `Depends on #${dep}, which is open and outside the submitted set (rule9-open-dependency).`,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return { verdict: reasons.length > 0 ? 'full' : 'candidate', reasons };
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=prescreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prescreen.js","sourceRoot":"","sources":["../src/prescreen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared TTL math for the CLI's cache-with-expiry files — `cache-resolver.ts`'s
|
|
3
|
+
* dossier resolution cache and `engine-version.ts`'s npm-latest cache both
|
|
4
|
+
* need "read a configured TTL in seconds, with a default" and "is this
|
|
5
|
+
* timestamp still within that TTL" (#537 review — the two files had
|
|
6
|
+
* near-line-for-line copies of both).
|
|
7
|
+
*
|
|
8
|
+
* File I/O itself stays per-module: `cache-resolver.ts`'s resolution files
|
|
9
|
+
* need org-scoped-path safety and symlink-swap defense that
|
|
10
|
+
* `engine-version.ts`'s single fixed-path cache file does not, so forcing a
|
|
11
|
+
* shared read/write would either under-harden one or over-complicate the
|
|
12
|
+
* other. Only the TTL math — which has no such asymmetry — is shared here.
|
|
13
|
+
*/
|
|
14
|
+
/** Read a `cache.*` TTL config key (seconds), falling back to `defaultSeconds` when unset/invalid. */
|
|
15
|
+
export declare function getConfiguredTtlSeconds(configKey: string, defaultSeconds: number): number;
|
|
16
|
+
/** Whether an ISO timestamp is still within `ttlSeconds` of now (never negative-age). */
|
|
17
|
+
export declare function isWithinTtl(timestampIso: string, ttlSeconds: number): boolean;
|
|
18
|
+
//# sourceMappingURL=ttl-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ttl-cache.d.ts","sourceRoot":"","sources":["../src/ttl-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,sGAAsG;AACtG,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAIzF;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG7E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared TTL math for the CLI's cache-with-expiry files — `cache-resolver.ts`'s
|
|
4
|
+
* dossier resolution cache and `engine-version.ts`'s npm-latest cache both
|
|
5
|
+
* need "read a configured TTL in seconds, with a default" and "is this
|
|
6
|
+
* timestamp still within that TTL" (#537 review — the two files had
|
|
7
|
+
* near-line-for-line copies of both).
|
|
8
|
+
*
|
|
9
|
+
* File I/O itself stays per-module: `cache-resolver.ts`'s resolution files
|
|
10
|
+
* need org-scoped-path safety and symlink-swap defense that
|
|
11
|
+
* `engine-version.ts`'s single fixed-path cache file does not, so forcing a
|
|
12
|
+
* shared read/write would either under-harden one or over-complicate the
|
|
13
|
+
* other. Only the TTL math — which has no such asymmetry — is shared here.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.getConfiguredTtlSeconds = getConfiguredTtlSeconds;
|
|
17
|
+
exports.isWithinTtl = isWithinTtl;
|
|
18
|
+
const config_1 = require("./config");
|
|
19
|
+
/** Read a `cache.*` TTL config key (seconds), falling back to `defaultSeconds` when unset/invalid. */
|
|
20
|
+
function getConfiguredTtlSeconds(configKey, defaultSeconds) {
|
|
21
|
+
const raw = (0, config_1.getConfig)(configKey);
|
|
22
|
+
if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0)
|
|
23
|
+
return raw;
|
|
24
|
+
return defaultSeconds;
|
|
25
|
+
}
|
|
26
|
+
/** Whether an ISO timestamp is still within `ttlSeconds` of now (never negative-age). */
|
|
27
|
+
function isWithinTtl(timestampIso, ttlSeconds) {
|
|
28
|
+
const ageMs = Date.now() - new Date(timestampIso).getTime();
|
|
29
|
+
return ageMs >= 0 && ageMs < ttlSeconds * 1000;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ttl-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ttl-cache.js","sourceRoot":"","sources":["../src/ttl-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAKH,0DAIC;AAGD,kCAGC;AAbD,qCAAqC;AAErC,sGAAsG;AACtG,SAAgB,uBAAuB,CAAC,SAAiB,EAAE,cAAsB;IAC/E,MAAM,GAAG,GAAG,IAAA,kBAAS,EAAC,SAAS,CAAC,CAAC;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC5E,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,yFAAyF;AACzF,SAAgB,WAAW,CAAC,YAAoB,EAAE,UAAkB;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5D,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;AACjD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-dossier/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.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": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@ai-dossier/core": "^1.5.0",
|
|
57
|
-
"@ai-dossier/sched": "^0.
|
|
57
|
+
"@ai-dossier/sched": "^0.13.0",
|
|
58
58
|
"commander": "^12.1.0",
|
|
59
59
|
"yaml": "^2.8.3"
|
|
60
60
|
},
|