@yourtechtribe-labs/koncept-cli 0.2.0-alpha.2 → 0.2.0-alpha.3
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/dist/commands/acks.d.ts +38 -0
- package/dist/commands/acks.d.ts.map +1 -0
- package/dist/commands/acks.js +70 -0
- package/dist/commands/acks.js.map +1 -0
- package/dist/commands/affected.d.ts +2 -0
- package/dist/commands/affected.d.ts.map +1 -1
- package/dist/commands/affected.js +0 -0
- package/dist/commands/affected.js.map +1 -1
- package/dist/commands/anthropic-client.d.ts +9 -0
- package/dist/commands/anthropic-client.d.ts.map +1 -0
- package/dist/commands/anthropic-client.js +65 -0
- package/dist/commands/anthropic-client.js.map +1 -0
- package/dist/commands/git.d.ts +14 -0
- package/dist/commands/git.d.ts.map +1 -0
- package/dist/commands/git.js +41 -0
- package/dist/commands/git.js.map +1 -0
- package/dist/commands/review.d.ts +3 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +78 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acknowledgment resolution for `koncepto affected --require-ack`.
|
|
3
|
+
*
|
|
4
|
+
* Two sources, unioned: (1) commit trailers `Koncepto-Reviewed: <c>:<i>` in the
|
|
5
|
+
* `<from>..HEAD` range (CI-friendly audit trail), (2) the `--ack` csv flag
|
|
6
|
+
* (local override). Pure parsers are exported for unit tests; `gatherAcks`
|
|
7
|
+
* wires the git invocation (the one side effect).
|
|
8
|
+
*
|
|
9
|
+
* Range note: default `--from HEAD` ⇒ empty range ⇒ no trailer acks (only
|
|
10
|
+
* `--ack` applies). `--files` override ⇒ no git range ⇒ `--ack` only.
|
|
11
|
+
*/
|
|
12
|
+
export type AckCsvResult = {
|
|
13
|
+
ok: true;
|
|
14
|
+
keys: string[];
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
bad: string;
|
|
18
|
+
};
|
|
19
|
+
/** Parses the `--ack` csv into ack keys; fails on an entry missing a colon. */
|
|
20
|
+
export declare function parseAckCsv(csv: string): AckCsvResult;
|
|
21
|
+
/** Extracts ack keys from `git log` trailer output (one value per line). */
|
|
22
|
+
export declare function parseReviewedTrailers(gitOutput: string): string[];
|
|
23
|
+
export interface GatherAcksOptions {
|
|
24
|
+
rootDir: string;
|
|
25
|
+
from: string;
|
|
26
|
+
/** When false (e.g. --files override), skip the git range entirely. */
|
|
27
|
+
useGit: boolean;
|
|
28
|
+
ackCsv: string | null;
|
|
29
|
+
}
|
|
30
|
+
export type GatherAcksResult = {
|
|
31
|
+
ok: true;
|
|
32
|
+
acks: ReadonlySet<string>;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
error: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function gatherAcks(opts: GatherAcksOptions): GatherAcksResult;
|
|
38
|
+
//# sourceMappingURL=acks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acks.d.ts","sourceRoot":"","sources":["../../src/commands/acks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9B,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CASrD;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjE;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhC,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,CAqBpE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acknowledgment resolution for `koncepto affected --require-ack`.
|
|
3
|
+
*
|
|
4
|
+
* Two sources, unioned: (1) commit trailers `Koncepto-Reviewed: <c>:<i>` in the
|
|
5
|
+
* `<from>..HEAD` range (CI-friendly audit trail), (2) the `--ack` csv flag
|
|
6
|
+
* (local override). Pure parsers are exported for unit tests; `gatherAcks`
|
|
7
|
+
* wires the git invocation (the one side effect).
|
|
8
|
+
*
|
|
9
|
+
* Range note: default `--from HEAD` ⇒ empty range ⇒ no trailer acks (only
|
|
10
|
+
* `--ack` applies). `--files` override ⇒ no git range ⇒ `--ack` only.
|
|
11
|
+
*/
|
|
12
|
+
import { spawnSync } from 'node:child_process';
|
|
13
|
+
const TRAILER_KEY = 'Koncepto-Reviewed';
|
|
14
|
+
/** Parses the `--ack` csv into ack keys; fails on an entry missing a colon. */
|
|
15
|
+
export function parseAckCsv(csv) {
|
|
16
|
+
const keys = [];
|
|
17
|
+
for (const raw of csv.split(',')) {
|
|
18
|
+
const entry = raw.trim();
|
|
19
|
+
if (entry.length === 0)
|
|
20
|
+
continue;
|
|
21
|
+
if (!entry.includes(':'))
|
|
22
|
+
return { ok: false, bad: entry };
|
|
23
|
+
keys.push(entry);
|
|
24
|
+
}
|
|
25
|
+
return { ok: true, keys };
|
|
26
|
+
}
|
|
27
|
+
/** Extracts ack keys from `git log` trailer output (one value per line). */
|
|
28
|
+
export function parseReviewedTrailers(gitOutput) {
|
|
29
|
+
return gitOutput
|
|
30
|
+
.split('\n')
|
|
31
|
+
.map((l) => l.trim())
|
|
32
|
+
.filter((l) => l.length > 0 && l.includes(':'));
|
|
33
|
+
}
|
|
34
|
+
export function gatherAcks(opts) {
|
|
35
|
+
const acks = new Set();
|
|
36
|
+
if (opts.ackCsv !== null) {
|
|
37
|
+
const parsed = parseAckCsv(opts.ackCsv);
|
|
38
|
+
if (!parsed.ok) {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
error: `invalid --ack entry: '${parsed.bad}' (want concept-id:invariant-id)`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
for (const k of parsed.keys)
|
|
45
|
+
acks.add(k);
|
|
46
|
+
}
|
|
47
|
+
if (opts.useGit) {
|
|
48
|
+
const fromTrailers = trailersFromGit(opts.rootDir, opts.from);
|
|
49
|
+
if (!fromTrailers.ok)
|
|
50
|
+
return fromTrailers;
|
|
51
|
+
for (const k of fromTrailers.keys)
|
|
52
|
+
acks.add(k);
|
|
53
|
+
}
|
|
54
|
+
return { ok: true, acks };
|
|
55
|
+
}
|
|
56
|
+
function trailersFromGit(rootDir, from) {
|
|
57
|
+
const result = spawnSync('git', ['log', `${from}..HEAD`, `--format=%(trailers:key=${TRAILER_KEY},valueonly)`], { cwd: rootDir, encoding: 'utf-8' });
|
|
58
|
+
if (result.error) {
|
|
59
|
+
return { ok: false, error: `git invocation failed: ${result.error.message}` };
|
|
60
|
+
}
|
|
61
|
+
if (result.status !== 0) {
|
|
62
|
+
const stderr = (result.stderr ?? '').trim();
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: `git log exited with status ${result.status}${stderr ? `: ${stderr}` : ''}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { ok: true, keys: parseReviewedTrailers(result.stdout ?? '') };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=acks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acks.js","sourceRoot":"","sources":["../../src/commands/acks.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,8 @@ export interface AffectedOptions {
|
|
|
4
4
|
from: string;
|
|
5
5
|
filesOverride: string[] | null;
|
|
6
6
|
json: boolean;
|
|
7
|
+
requireAck: boolean;
|
|
8
|
+
ackCsv: string | null;
|
|
7
9
|
}
|
|
8
10
|
export declare function runAffected(ctx: CommandContext): Promise<number>;
|
|
9
11
|
//# sourceMappingURL=affected.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affected.d.ts","sourceRoot":"","sources":["../../src/commands/affected.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"affected.d.ts","sourceRoot":"","sources":["../../src/commands/affected.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,OAAO,CAAA;IACb,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAyCtE"}
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affected.js","sourceRoot":"","sources":["../../src/commands/affected.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"affected.js","sourceRoot":"","sources":["../../src/commands/affected.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Messages API provider for `koncepto review` — global `fetch`, no
|
|
3
|
+
* SDK (D-004). Returns an `llm: (prompt) => Promise<string>` matching the seam
|
|
4
|
+
* koncept-core's reviewAffected injects. One retry on network/5xx; a final
|
|
5
|
+
* failure throws (reviewAffected re-tags it with concept:invariant → exit 2).
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_MODEL = "claude-sonnet-4-6";
|
|
8
|
+
export declare function makeAnthropicLlm(apiKey: string, model: string): (prompt: string) => Promise<string>;
|
|
9
|
+
//# sourceMappingURL=anthropic-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-client.d.ts","sourceRoot":"","sources":["../../src/commands/anthropic-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,aAAa,sBAAsB,CAAA;AAMhD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAUrC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Messages API provider for `koncepto review` — global `fetch`, no
|
|
3
|
+
* SDK (D-004). Returns an `llm: (prompt) => Promise<string>` matching the seam
|
|
4
|
+
* koncept-core's reviewAffected injects. One retry on network/5xx; a final
|
|
5
|
+
* failure throws (reviewAffected re-tags it with concept:invariant → exit 2).
|
|
6
|
+
*/
|
|
7
|
+
const ENDPOINT = 'https://api.anthropic.com/v1/messages';
|
|
8
|
+
const ANTHROPIC_VERSION = '2023-06-01';
|
|
9
|
+
const MAX_TOKENS = 1024;
|
|
10
|
+
export const DEFAULT_MODEL = 'claude-sonnet-4-6';
|
|
11
|
+
export function makeAnthropicLlm(apiKey, model) {
|
|
12
|
+
return async (prompt) => {
|
|
13
|
+
const res = await postWithRetry(apiKey, model, prompt);
|
|
14
|
+
const json = (await res.json());
|
|
15
|
+
const text = json.content?.find((b) => b.type === 'text')?.text;
|
|
16
|
+
if (typeof text !== 'string') {
|
|
17
|
+
throw new Error('Anthropic response had no text content block');
|
|
18
|
+
}
|
|
19
|
+
return text;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function postWithRetry(apiKey, model, prompt) {
|
|
23
|
+
let lastError = '';
|
|
24
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
25
|
+
let res;
|
|
26
|
+
try {
|
|
27
|
+
res = await post(apiKey, model, prompt);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
lastError = err instanceof Error ? err.message : String(err); // network → retry
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (res.ok)
|
|
34
|
+
return res;
|
|
35
|
+
if (res.status < 500) {
|
|
36
|
+
throw new Error(`Anthropic API ${res.status}: ${await safeBody(res)}`); // client error → no retry
|
|
37
|
+
}
|
|
38
|
+
lastError = `Anthropic API ${res.status}`; // 5xx → retry
|
|
39
|
+
}
|
|
40
|
+
throw new Error(lastError || 'Anthropic API request failed');
|
|
41
|
+
}
|
|
42
|
+
function post(apiKey, model, prompt) {
|
|
43
|
+
return fetch(ENDPOINT, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'content-type': 'application/json',
|
|
47
|
+
'x-api-key': apiKey,
|
|
48
|
+
'anthropic-version': ANTHROPIC_VERSION,
|
|
49
|
+
},
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
model,
|
|
52
|
+
max_tokens: MAX_TOKENS,
|
|
53
|
+
messages: [{ role: 'user', content: prompt }],
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function safeBody(res) {
|
|
58
|
+
try {
|
|
59
|
+
return (await res.text()).slice(0, 300);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return '(no body)';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=anthropic-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-client.js","sourceRoot":"","sources":["../../src/commands/anthropic-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,QAAQ,GAAG,uCAAuC,CAAA;AACxD,MAAM,iBAAiB,GAAG,YAAY,CAAA;AACtC,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAMhD,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,KAAa;IAEb,OAAO,KAAK,EAAE,MAAc,EAAmB,EAAE;QAC/C,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QACtD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAA;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,CAAA;QAC/D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;QACjE,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAc,EACd,KAAa,EACb,MAAc;IAEd,IAAI,SAAS,GAAG,EAAE,CAAA;IAClB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI,GAAa,CAAA;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,kBAAkB;YAC/E,SAAQ;QACV,CAAC;QACD,IAAI,GAAG,CAAC,EAAE;YAAE,OAAO,GAAG,CAAA;QACtB,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA,CAAC,0BAA0B;QACnG,CAAC;QACD,SAAS,GAAG,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAA,CAAC,cAAc;IAC1D,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,8BAA8B,CAAC,CAAA;AAC9D,CAAC;AAED,SAAS,IAAI,CAAC,MAAc,EAAE,KAAa,EAAE,MAAc;IACzD,OAAO,KAAK,CAAC,QAAQ,EAAE;QACrB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,WAAW,EAAE,MAAM;YACnB,mBAAmB,EAAE,iBAAiB;SACvC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK;YACL,UAAU,EAAE,UAAU;YACtB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAC9C,CAAC;KACH,CAAC,CAAA;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAa;IACnC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAA;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git helpers shared by `affected` and `review` — the diff resolution both
|
|
3
|
+
* commands need. `git diff --name-only -z` is NUL-terminated (so paths with
|
|
4
|
+
* spaces survive); splitting on space silently matched nothing.
|
|
5
|
+
*/
|
|
6
|
+
export interface ChangedFilesResult {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
files: string[];
|
|
9
|
+
error: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveChangedFiles(rootDir: string, from: string, filesOverride: string[] | null): ChangedFilesResult;
|
|
12
|
+
/** Unified diff for one file against `from` (sync — the injected `diff` seam). */
|
|
13
|
+
export declare function fileDiff(rootDir: string, from: string, file: string): string;
|
|
14
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,GAC7B,kBAAkB,CAsBpB;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS5E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git helpers shared by `affected` and `review` — the diff resolution both
|
|
3
|
+
* commands need. `git diff --name-only -z` is NUL-terminated (so paths with
|
|
4
|
+
* spaces survive); splitting on space silently matched nothing.
|
|
5
|
+
*/
|
|
6
|
+
import { spawnSync } from 'node:child_process';
|
|
7
|
+
export function resolveChangedFiles(rootDir, from, filesOverride) {
|
|
8
|
+
if (filesOverride !== null) {
|
|
9
|
+
return { ok: true, files: filesOverride, error: '' };
|
|
10
|
+
}
|
|
11
|
+
const result = spawnSync('git', ['diff', '--name-only', '-z', from], {
|
|
12
|
+
cwd: rootDir,
|
|
13
|
+
encoding: 'buffer',
|
|
14
|
+
});
|
|
15
|
+
if (result.error) {
|
|
16
|
+
return { ok: false, files: [], error: `git invocation failed: ${result.error.message}` };
|
|
17
|
+
}
|
|
18
|
+
if (result.status !== 0) {
|
|
19
|
+
const stderr = result.stderr ? result.stderr.toString('utf-8').trim() : '';
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
files: [],
|
|
23
|
+
error: `git diff exited with status ${result.status}${stderr ? `: ${stderr}` : ''}`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const stdout = result.stdout ? result.stdout.toString('utf-8') : '';
|
|
27
|
+
const files = stdout.split('\0').filter((s) => s.length > 0);
|
|
28
|
+
return { ok: true, files, error: '' };
|
|
29
|
+
}
|
|
30
|
+
/** Unified diff for one file against `from` (sync — the injected `diff` seam). */
|
|
31
|
+
export function fileDiff(rootDir, from, file) {
|
|
32
|
+
const result = spawnSync('git', ['diff', from, '--', file], {
|
|
33
|
+
cwd: rootDir,
|
|
34
|
+
encoding: 'utf-8',
|
|
35
|
+
});
|
|
36
|
+
if (result.error) {
|
|
37
|
+
throw new Error(`git diff failed for ${file}: ${result.error.message}`);
|
|
38
|
+
}
|
|
39
|
+
return result.stdout ?? '';
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/commands/git.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAQ9C,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,IAAY,EACZ,aAA8B;IAE9B,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACtD,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;QACnE,GAAG,EAAE,OAAO;QACZ,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAA;IACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,0BAA0B,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAA;IAC1F,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,+BAA+B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;SACpF,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACnE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC5D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;AACvC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,IAAY,EAAE,IAAY;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;QAC1D,GAAG,EAAE,OAAO;QACZ,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAA;IACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,IAAI,EAAE,CAAA;AAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAcjD,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA4CpE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { loadConcepts, reviewAffected, } from '@yourtechtribe-labs/koncept-core';
|
|
2
|
+
import { DEFAULT_MODEL, makeAnthropicLlm } from './anthropic-client.js';
|
|
3
|
+
import { fileDiff, resolveChangedFiles } from './git.js';
|
|
4
|
+
export async function runReview(ctx) {
|
|
5
|
+
const opts = parseOptions(ctx);
|
|
6
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
7
|
+
if (apiKey === undefined || apiKey.length === 0) {
|
|
8
|
+
process.stderr.write('koncepto review: ANTHROPIC_API_KEY is required\n');
|
|
9
|
+
return 2;
|
|
10
|
+
}
|
|
11
|
+
const filesResult = resolveChangedFiles(opts.rootDir, opts.from, opts.filesOverride);
|
|
12
|
+
if (!filesResult.ok) {
|
|
13
|
+
process.stderr.write(`koncepto review: ${filesResult.error}\n`);
|
|
14
|
+
return 2;
|
|
15
|
+
}
|
|
16
|
+
const loaded = await loadConcepts(opts.rootDir);
|
|
17
|
+
if (loaded.parseErrors.length > 0 && !opts.json) {
|
|
18
|
+
for (const e of loaded.parseErrors) {
|
|
19
|
+
process.stderr.write(`koncepto review: warning: parse error in ${e.filePath}: ${e.message}\n`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
let result;
|
|
23
|
+
try {
|
|
24
|
+
result = await reviewAffected(loaded.concepts, {
|
|
25
|
+
rootDir: opts.rootDir,
|
|
26
|
+
changedFiles: filesResult.files,
|
|
27
|
+
diff: (file) => fileDiff(opts.rootDir, opts.from, file),
|
|
28
|
+
minSeverity: opts.minSeverity,
|
|
29
|
+
llm: makeAnthropicLlm(apiKey, opts.model),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
34
|
+
process.stderr.write(`koncepto review: ${detail}\n`);
|
|
35
|
+
return 2;
|
|
36
|
+
}
|
|
37
|
+
if (opts.json) {
|
|
38
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
renderReview(result);
|
|
42
|
+
}
|
|
43
|
+
return exitCodeFor(result, opts.strict);
|
|
44
|
+
}
|
|
45
|
+
const SEVERITIES = ['high', 'medium', 'low'];
|
|
46
|
+
function parseOptions(ctx) {
|
|
47
|
+
const filesFlag = ctx.flags.files;
|
|
48
|
+
const filesOverride = typeof filesFlag === 'string'
|
|
49
|
+
? filesFlag.split(',').map((s) => s.trim()).filter((s) => s.length > 0)
|
|
50
|
+
: null;
|
|
51
|
+
const sevFlag = ctx.flags.severity;
|
|
52
|
+
const minSeverity = typeof sevFlag === 'string' && SEVERITIES.includes(sevFlag)
|
|
53
|
+
? sevFlag
|
|
54
|
+
: 'medium';
|
|
55
|
+
return {
|
|
56
|
+
rootDir: ctx.rootDir,
|
|
57
|
+
from: typeof ctx.flags.from === 'string' ? ctx.flags.from : 'HEAD',
|
|
58
|
+
filesOverride,
|
|
59
|
+
minSeverity,
|
|
60
|
+
strict: ctx.flags.strict === true,
|
|
61
|
+
model: typeof ctx.flags.model === 'string' ? ctx.flags.model : DEFAULT_MODEL,
|
|
62
|
+
json: ctx.flags.json === true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const VERDICT_SYMBOL = { holds: '✓', violated: '✗', uncertain: '?' };
|
|
66
|
+
function renderReview(result) {
|
|
67
|
+
process.stdout.write(`koncepto review — ${result.reviews.length} advisory invariant(s), ${result.skipped} skipped\n`);
|
|
68
|
+
for (const r of result.reviews) {
|
|
69
|
+
process.stdout.write(`\n ${r.conceptId} / ${r.invariantId} [${r.severity}]\n`);
|
|
70
|
+
process.stdout.write(` ${VERDICT_SYMBOL[r.verdict] ?? '?'} ${r.verdict} — ${r.rationale}\n`);
|
|
71
|
+
}
|
|
72
|
+
process.stdout.write(`\n Results: ${result.holds} holds · ${result.violated} violated · ${result.uncertain} uncertain · ${result.skipped} skipped\n`);
|
|
73
|
+
}
|
|
74
|
+
/** Advisory by default (exit 0). --strict gates on `violated`; uncertain never fails. */
|
|
75
|
+
function exitCodeFor(result, strict) {
|
|
76
|
+
return strict && result.violated > 0 ? 1 : 0;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAwCA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;CACxC;AAcD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBtF"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { runList } from './commands/list.js';
|
|
|
9
9
|
import { runLink } from './commands/link.js';
|
|
10
10
|
import { runAffected } from './commands/affected.js';
|
|
11
11
|
import { runCheck } from './commands/check.js';
|
|
12
|
+
import { runReview } from './commands/review.js';
|
|
12
13
|
import { VERSION } from './version.js';
|
|
13
14
|
const HELP = `koncepto ${VERSION}
|
|
14
15
|
|
|
@@ -22,9 +23,15 @@ Usage:
|
|
|
22
23
|
--role=<r> --purpose=<p>
|
|
23
24
|
koncepto affected [--from <ref>] Report concepts/invariants touched by a diff
|
|
24
25
|
[--files=a,b,c] [--json]
|
|
26
|
+
[--require-ack] (exit 3 if an advisory high invariant is unacked)
|
|
27
|
+
[--ack=c:i,c2:i2] (acknowledge invariants; supplements commit trailers)
|
|
25
28
|
koncepto check Execute invariant.check payloads (grep + command)
|
|
26
29
|
[--id <concept-id>] (filter to one concept)
|
|
27
30
|
[--json] (machine-readable output)
|
|
31
|
+
koncepto review [--from <ref>] LLM review of touched advisory invariants
|
|
32
|
+
[--files=a,b,c] [--json] (requires ANTHROPIC_API_KEY)
|
|
33
|
+
[--severity high|medium|low] (min severity to review; default medium)
|
|
34
|
+
[--strict] [--model <id>] (--strict: exit 1 on any 'violated')
|
|
28
35
|
|
|
29
36
|
Flags:
|
|
30
37
|
--help, --version
|
|
@@ -36,6 +43,7 @@ const COMMANDS = {
|
|
|
36
43
|
link: runLink,
|
|
37
44
|
affected: runAffected,
|
|
38
45
|
check: runCheck,
|
|
46
|
+
review: runReview,
|
|
39
47
|
};
|
|
40
48
|
export async function run(argv, cwd = process.cwd()) {
|
|
41
49
|
const { command, positional, flags } = parseArgs(argv);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,IAAI,GAAG,YAAY,OAAO
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yourtechtribe-labs/koncept-cli",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.3",
|
|
4
4
|
"description": "CLI for koncepto — init, verify, list, link operations on .koncept/ concept graphs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@yourtechtribe-labs/koncept-core": "^0.2.0-alpha.0",
|
|
34
34
|
"glob": "13.0.6",
|
|
35
|
-
"yaml": "2.
|
|
35
|
+
"yaml": "2.9.0"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public",
|