@jmtrin/opencode-kevin 0.4.0 → 0.6.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 +580 -360
- package/dist/migrations/006_v05_glassbox.sql +118 -0
- package/dist/migrations/007_v06_pull.sql +145 -0
- package/dist/plugin/Archiver.d.ts +42 -0
- package/dist/plugin/Archiver.js +99 -0
- package/dist/plugin/Archiver.js.map +1 -0
- package/dist/plugin/ArtifactWriter.d.ts +50 -0
- package/dist/plugin/ArtifactWriter.js +240 -0
- package/dist/plugin/ArtifactWriter.js.map +1 -0
- package/dist/plugin/ContextInjector.d.ts +87 -0
- package/dist/plugin/ContextInjector.js +212 -44
- package/dist/plugin/ContextInjector.js.map +1 -1
- package/dist/plugin/Curator.d.ts +96 -0
- package/dist/plugin/Curator.js +252 -0
- package/dist/plugin/Curator.js.map +1 -0
- package/dist/plugin/Feedback.d.ts +67 -0
- package/dist/plugin/Feedback.js +138 -0
- package/dist/plugin/Feedback.js.map +1 -0
- package/dist/plugin/InjectionLedger.d.ts +9 -2
- package/dist/plugin/InjectionLedger.js +63 -9
- package/dist/plugin/InjectionLedger.js.map +1 -1
- package/dist/plugin/Materializer.d.ts +59 -0
- package/dist/plugin/Materializer.js +237 -0
- package/dist/plugin/Materializer.js.map +1 -0
- package/dist/plugin/MemoryService.d.ts +38 -0
- package/dist/plugin/MemoryService.js +265 -30
- package/dist/plugin/MemoryService.js.map +1 -1
- package/dist/plugin/Migrate.js +41 -0
- package/dist/plugin/Migrate.js.map +1 -1
- package/dist/plugin/QualityGate.d.ts +53 -0
- package/dist/plugin/QualityGate.js +50 -8
- package/dist/plugin/QualityGate.js.map +1 -1
- package/dist/plugin/Retrospective.d.ts +1 -0
- package/dist/plugin/Retrospective.js +24 -1
- package/dist/plugin/Retrospective.js.map +1 -1
- package/dist/plugin/capabilities.d.ts +15 -0
- package/dist/plugin/capabilities.js +42 -0
- package/dist/plugin/capabilities.js.map +1 -0
- package/dist/plugin/confidence.d.ts +3 -1
- package/dist/plugin/confidence.js +14 -2
- package/dist/plugin/confidence.js.map +1 -1
- package/dist/plugin/diff.d.ts +8 -0
- package/dist/plugin/diff.js +183 -0
- package/dist/plugin/diff.js.map +1 -0
- package/dist/plugin/index.d.ts +3 -1
- package/dist/plugin/index.js +371 -0
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/inferability.d.ts +32 -0
- package/dist/plugin/inferability.js +89 -0
- package/dist/plugin/inferability.js.map +1 -0
- package/dist/plugin/kevin_approve.d.ts +34 -0
- package/dist/plugin/kevin_approve.js +50 -0
- package/dist/plugin/kevin_approve.js.map +1 -0
- package/dist/plugin/kevin_audit.d.ts +95 -0
- package/dist/plugin/kevin_audit.js +233 -0
- package/dist/plugin/kevin_audit.js.map +1 -0
- package/dist/plugin/kevin_propose.d.ts +23 -0
- package/dist/plugin/kevin_propose.js +15 -0
- package/dist/plugin/kevin_propose.js.map +1 -0
- package/dist/plugin/kevin_publish.d.ts +38 -0
- package/dist/plugin/kevin_publish.js +19 -0
- package/dist/plugin/kevin_publish.js.map +1 -0
- package/dist/plugin/kevin_why.js +23 -2
- package/dist/plugin/kevin_why.js.map +1 -1
- package/dist/plugin/metrics.d.ts +32 -1
- package/dist/plugin/metrics.js +86 -2
- package/dist/plugin/metrics.js.map +1 -1
- package/dist/plugin/replay-types.d.ts +327 -0
- package/dist/plugin/replay-types.js +65 -0
- package/dist/plugin/replay-types.js.map +1 -0
- package/dist/plugin/replay.d.ts +36 -0
- package/dist/plugin/replay.js +203 -0
- package/dist/plugin/replay.js.map +1 -0
- package/migrations/006_v05_glassbox.sql +118 -0
- package/migrations/007_v06_pull.sql +145 -0
- package/package.json +3 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K6-010 — v0.6.0 pull — deterministic error-knowledge classifier (plan §5.3).
|
|
3
|
+
*
|
|
4
|
+
* Pure module: no DB, no clock, no filesystem, no RNG. Fully unit-testable in
|
|
5
|
+
* isolation, and therefore fully unit-tested.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The `Reflector` dispatch surface of §3.4, restated as data: error codes whose
|
|
9
|
+
* payload IS the knowledge — no project-specific interpretation required.
|
|
10
|
+
*/
|
|
11
|
+
export const SELF_DESCRIBING_CODES = new Set([
|
|
12
|
+
"TS2304",
|
|
13
|
+
"TS2307",
|
|
14
|
+
"TS2322",
|
|
15
|
+
"TS2339",
|
|
16
|
+
"TS2305",
|
|
17
|
+
"TS2552",
|
|
18
|
+
"TS2740",
|
|
19
|
+
"TS6133",
|
|
20
|
+
"TS18047",
|
|
21
|
+
"E0433",
|
|
22
|
+
"E0432",
|
|
23
|
+
"command_not_found",
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* Rule 4 detector — deliberately conservative. Errs toward `non_inferable`,
|
|
27
|
+
* because a false `inferable` silently withholds real knowledge from curation
|
|
28
|
+
* forever, while a false `non_inferable` costs one line a human rejects.
|
|
29
|
+
*/
|
|
30
|
+
const NPM_RUN_RE = /\b(?:npm|pnpm|yarn|bun)(?:\s+(?:run|exec))?\s+[\w@:/-]+/;
|
|
31
|
+
const RELATIVE_PATH_RE = /\.{1,2}\/[\w./@-]+/;
|
|
32
|
+
const FLAG_RE = /(?:^|\s)--[\w-]+/;
|
|
33
|
+
const FILE_EXT_RE = /\b[\w./@-]+\.[a-zA-Z][a-zA-Z0-9]{0,7}\b/;
|
|
34
|
+
function namesProjectSpecific(content) {
|
|
35
|
+
return (NPM_RUN_RE.test(content) ||
|
|
36
|
+
RELATIVE_PATH_RE.test(content) ||
|
|
37
|
+
FLAG_RE.test(content) ||
|
|
38
|
+
FILE_EXT_RE.test(content));
|
|
39
|
+
}
|
|
40
|
+
function dispatchCode(metadata) {
|
|
41
|
+
if (metadata === null || typeof metadata !== "object")
|
|
42
|
+
return null;
|
|
43
|
+
const dispatch = metadata.dispatch;
|
|
44
|
+
if (dispatch === null || typeof dispatch !== "object")
|
|
45
|
+
return null;
|
|
46
|
+
const code = dispatch.code;
|
|
47
|
+
return typeof code === "string" && code.length > 0 ? code : null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Rules from plan §5.3, evaluated in order — the ordering is the specification:
|
|
51
|
+
*
|
|
52
|
+
* 1. `type` ∈ decision / rule / solution → `non_inferable`
|
|
53
|
+
* 2. `type` = pattern → `non_inferable`
|
|
54
|
+
* 3. `type` = error and `metadata.dispatch.code` ∈ SELF_DESCRIBING_CODES → `inferable`
|
|
55
|
+
* 4. `type` = error and content names a project-specific path, script or flag → `non_inferable`
|
|
56
|
+
* 5. otherwise → `unknown`
|
|
57
|
+
*
|
|
58
|
+
* Rule 4 beats rule 3: a TS2304 is inferable, but "TS2304 on
|
|
59
|
+
* `./scripts/gen-routes.ts` because the generator must run before tsc" is not —
|
|
60
|
+
* the project-specific script name is the payload, not the code. Rule 3's
|
|
61
|
+
* condition (code membership) is evaluated first for the bare case; rule 4
|
|
62
|
+
* catches what rule 3 does not.
|
|
63
|
+
*/
|
|
64
|
+
export function classify(memory) {
|
|
65
|
+
// Rule 1 — authored knowledge is never re-derived.
|
|
66
|
+
if (memory.type === "decision" ||
|
|
67
|
+
memory.type === "rule" ||
|
|
68
|
+
memory.type === "solution") {
|
|
69
|
+
return "non_inferable";
|
|
70
|
+
}
|
|
71
|
+
// Rule 2 — a mined sequence is project-specific by construction.
|
|
72
|
+
if (memory.type === "pattern") {
|
|
73
|
+
return "non_inferable";
|
|
74
|
+
}
|
|
75
|
+
if (memory.type === "error") {
|
|
76
|
+
const code = dispatchCode(memory.metadata);
|
|
77
|
+
// Rule 4 — content naming a project-specific path, script or flag.
|
|
78
|
+
if (namesProjectSpecific(memory.content)) {
|
|
79
|
+
return "non_inferable";
|
|
80
|
+
}
|
|
81
|
+
// Rule 3 — a bare self-describing code is inferable.
|
|
82
|
+
if (code !== null && SELF_DESCRIBING_CODES.has(code)) {
|
|
83
|
+
return "inferable";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Rule 5.
|
|
87
|
+
return "unknown";
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=inferability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferability.js","sourceRoot":"","sources":["../../plugin/inferability.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IACjE,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,OAAO;IACP,OAAO;IACP,mBAAmB;CACnB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAAG,yDAAyD,CAAC;AAC7E,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AAC9C,MAAM,OAAO,GAAG,kBAAkB,CAAC;AACnC,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAE9D,SAAS,oBAAoB,CAAC,OAAe;IAC5C,OAAO,CACN,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;QACxB,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACrB,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CACzB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACtC,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,QAAQ,GAAI,QAAmC,CAAC,QAAQ,CAAC;IAC/D,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,IAAI,GAAI,QAA+B,CAAC,IAAI,CAAC;IACnD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAAC,MAIxB;IACA,mDAAmD;IACnD,IACC,MAAM,CAAC,IAAI,KAAK,UAAU;QAC1B,MAAM,CAAC,IAAI,KAAK,MAAM;QACtB,MAAM,CAAC,IAAI,KAAK,UAAU,EACzB,CAAC;QACF,OAAO,eAAe,CAAC;IACxB,CAAC;IACD,iEAAiE;IACjE,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC;IACxB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3C,mEAAmE;QACnE,IAAI,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,OAAO,eAAe,CAAC;QACxB,CAAC;QACD,qDAAqD;QACrD,IAAI,IAAI,KAAK,IAAI,IAAI,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,OAAO,WAAW,CAAC;QACpB,CAAC;IACF,CAAC;IACD,UAAU;IACV,OAAO,SAAS,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ArtifactWriter } from "./ArtifactWriter.js";
|
|
2
|
+
import type { Curator, ProposalStatus } from "./Curator.js";
|
|
3
|
+
import type { MemoryService } from "./MemoryService.js";
|
|
4
|
+
import type { Store } from "./Store.js";
|
|
5
|
+
import type { Metrics } from "./metrics.js";
|
|
6
|
+
/**
|
|
7
|
+
* K6-014 — v0.6.0 pull — `kevin_approve` tool logic.
|
|
8
|
+
*
|
|
9
|
+
* The ONLY code path in the entire plugin that may call
|
|
10
|
+
* `ArtifactWriter`'s apply method (D6-01; enforced by
|
|
11
|
+
* tests/unit/single_write_path.test.ts).
|
|
12
|
+
*
|
|
13
|
+
* There is deliberately no "trusted mode" and no flag that skips the human:
|
|
14
|
+
* the approval gate is the release's entire safety model.
|
|
15
|
+
*/
|
|
16
|
+
export interface ApproveArgs {
|
|
17
|
+
readonly proposalId: string;
|
|
18
|
+
readonly decision: "approve" | "reject";
|
|
19
|
+
}
|
|
20
|
+
export type ApproveResult = {
|
|
21
|
+
readonly proposalId: string;
|
|
22
|
+
readonly status: "rejected";
|
|
23
|
+
} | {
|
|
24
|
+
readonly proposalId: string;
|
|
25
|
+
readonly status: "applied";
|
|
26
|
+
readonly outcome: string;
|
|
27
|
+
readonly curated: number;
|
|
28
|
+
} | {
|
|
29
|
+
readonly error: "not_found" | "not_pending";
|
|
30
|
+
readonly proposalId: string;
|
|
31
|
+
readonly status?: ProposalStatus;
|
|
32
|
+
readonly message: string;
|
|
33
|
+
};
|
|
34
|
+
export declare function kevinApprove(store: Store, memoryService: MemoryService, curator: Curator, writer: ArtifactWriter, metrics: Metrics | null, args: ApproveArgs): ApproveResult;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function kevinApprove(store, memoryService, curator, writer, metrics, args) {
|
|
2
|
+
const row = store
|
|
3
|
+
.prepare(`SELECT id, kind, target_path, proposed_text, memory_id, status
|
|
4
|
+
FROM curation_proposals WHERE id = ?`)
|
|
5
|
+
.get(args.proposalId);
|
|
6
|
+
if (!row) {
|
|
7
|
+
return {
|
|
8
|
+
error: "not_found",
|
|
9
|
+
proposalId: args.proposalId,
|
|
10
|
+
message: `No proposal with id "${args.proposalId}".`,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (row.status !== "pending") {
|
|
14
|
+
return {
|
|
15
|
+
error: "not_pending",
|
|
16
|
+
proposalId: args.proposalId,
|
|
17
|
+
status: row.status,
|
|
18
|
+
message: `Proposal "${args.proposalId}" is ${row.status}, not pending.`,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (args.decision === "reject") {
|
|
22
|
+
curator.transition(args.proposalId, "reject");
|
|
23
|
+
metrics?.incr("proposals_rejected", 1);
|
|
24
|
+
return { proposalId: args.proposalId, status: "rejected" };
|
|
25
|
+
}
|
|
26
|
+
// approve → apply → applied (plan §5.5). The proposed_text is re-planned
|
|
27
|
+
// at approval time against the file as it is now; apply() is atomic and
|
|
28
|
+
// audits every outcome including noop. The disk write happens BEFORE the
|
|
29
|
+
// state transitions: if apply() throws (e.g. a filesystem error), the
|
|
30
|
+
// proposal is still 'pending' and the human can retry or reject — a
|
|
31
|
+
// row stuck in 'approved' with no file written would be a dead end,
|
|
32
|
+
// since kevin_approve only accepts pending rows.
|
|
33
|
+
const plan = writer.plan(row.target_path, row.proposed_text);
|
|
34
|
+
const outcome = writer.apply(plan, args.proposalId);
|
|
35
|
+
curator.transition(args.proposalId, "approve");
|
|
36
|
+
curator.transition(args.proposalId, "apply");
|
|
37
|
+
const memoryIds = row.memory_id.split(",").filter((s) => s.length > 0);
|
|
38
|
+
const curated = memoryService.markCurated(memoryIds, sqliteNow());
|
|
39
|
+
metrics?.incr("proposals_approved", 1);
|
|
40
|
+
return {
|
|
41
|
+
proposalId: args.proposalId,
|
|
42
|
+
status: "applied",
|
|
43
|
+
outcome,
|
|
44
|
+
curated,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function sqliteNow() {
|
|
48
|
+
return new Date().toISOString().slice(0, 19).replace("T", " ");
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=kevin_approve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kevin_approve.js","sourceRoot":"","sources":["../../plugin/kevin_approve.ts"],"names":[],"mappings":"AAiDA,MAAM,UAAU,YAAY,CAC3B,KAAY,EACZ,aAA4B,EAC5B,OAAgB,EAChB,MAAsB,EACtB,OAAuB,EACvB,IAAiB;IAEjB,MAAM,GAAG,GAAG,KAAK;SACf,OAAO,CACP;yCACsC,CACtC;SACA,GAAG,CAAC,IAAI,CAAC,UAAU,CAA4B,CAAC;IAClD,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;YACN,KAAK,EAAE,WAAW;YAClB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,wBAAwB,IAAI,CAAC,UAAU,IAAI;SACpD,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO;YACN,KAAK,EAAE,aAAa;YACpB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,OAAO,EAAE,aAAa,IAAI,CAAC,UAAU,QAAQ,GAAG,CAAC,MAAM,gBAAgB;SACvE,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC;QACvC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC5D,CAAC;IAED,yEAAyE;IACzE,wEAAwE;IACxE,yEAAyE;IACzE,sEAAsE;IACtE,oEAAoE;IACpE,oEAAoE;IACpE,iDAAiD;IACjD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC/C,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IAClE,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC;IACvC,OAAO;QACN,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,MAAM,EAAE,SAAS;QACjB,OAAO;QACP,OAAO;KACP,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IACjB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Store } from "./Store.js";
|
|
2
|
+
import type { Capabilities } from "./capabilities.js";
|
|
3
|
+
import type { Metrics } from "./metrics.js";
|
|
4
|
+
/**
|
|
5
|
+
* v0.5.0 (K5-016 / plan §5.7) — `kevin_audit`.
|
|
6
|
+
*
|
|
7
|
+
* Pure SQL over `memories`, `kevin_injections`, `kevin_metrics`,
|
|
8
|
+
* `memory_feedback`. No writes, no LLM, no filesystem access.
|
|
9
|
+
*
|
|
10
|
+
* There is deliberately **no `kevin_context_ratio`** (D5-09): Kevin cannot
|
|
11
|
+
* observe total session input tokens, so any such figure would be fabricated.
|
|
12
|
+
*
|
|
13
|
+
* Pre-006 databases degrade gracefully: any block that fails (missing column
|
|
14
|
+
* or table) falls back to its zero value and the report is flagged
|
|
15
|
+
* `"partial": true` instead of throwing.
|
|
16
|
+
*
|
|
17
|
+
* v0.6.0 (K6-023 / plan §5.8) — the `channels` and `curation` blocks are the
|
|
18
|
+
* release's own scoreboard. On a pre-007 database they are **omitted** (not
|
|
19
|
+
* zero-valued) and `"partial": true` is set: a report that cannot answer
|
|
20
|
+
* "do the pull channels beat push?" must say so rather than suggest it can.
|
|
21
|
+
*/
|
|
22
|
+
export interface AuditReport {
|
|
23
|
+
memories: {
|
|
24
|
+
total: number;
|
|
25
|
+
by_status: Record<string, number>;
|
|
26
|
+
by_origin: Record<string, number>;
|
|
27
|
+
by_type: Record<string, number>;
|
|
28
|
+
ignored: number;
|
|
29
|
+
archived: number;
|
|
30
|
+
with_feedback: number;
|
|
31
|
+
superseded_with_target: number;
|
|
32
|
+
};
|
|
33
|
+
injections: {
|
|
34
|
+
total: number;
|
|
35
|
+
effective: number;
|
|
36
|
+
ineffective: number;
|
|
37
|
+
inconclusive: number;
|
|
38
|
+
unmeasured: number;
|
|
39
|
+
precision_rate: number;
|
|
40
|
+
coverage_rate: number;
|
|
41
|
+
};
|
|
42
|
+
blocked: Record<string, number>;
|
|
43
|
+
feedback: {
|
|
44
|
+
positive: number;
|
|
45
|
+
negative: number;
|
|
46
|
+
by_verdict: Record<string, number>;
|
|
47
|
+
};
|
|
48
|
+
tokens: {
|
|
49
|
+
pre_prompt: number;
|
|
50
|
+
compacting: number;
|
|
51
|
+
};
|
|
52
|
+
settings: Record<string, string>;
|
|
53
|
+
channels?: ChannelReport;
|
|
54
|
+
curation?: CurationReport;
|
|
55
|
+
partial: boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* v0.6.0 (K6-023 / plan §5.8) — three-channel comparison on the same axes.
|
|
59
|
+
* `skill_emission` / `reference_emission` distinguish the three states a
|
|
60
|
+
* channel can be in: "unavailable" (v1 host, no domain on the plugin input),
|
|
61
|
+
* "off" (capable host, setting '0'), "on" (capable host, setting '1').
|
|
62
|
+
* Collapsing "unavailable" and "off" would make "my host is too old"
|
|
63
|
+
* indistinguishable from "I turned it off".
|
|
64
|
+
*/
|
|
65
|
+
export type EmissionState = "on" | "off" | "unavailable";
|
|
66
|
+
export interface ChannelReport {
|
|
67
|
+
push: {
|
|
68
|
+
tokens_pre_prompt: number;
|
|
69
|
+
tokens_compacting: number;
|
|
70
|
+
injections_total: number;
|
|
71
|
+
precision_rate: number;
|
|
72
|
+
coverage_rate: number;
|
|
73
|
+
budget_tokens: number;
|
|
74
|
+
};
|
|
75
|
+
pull: {
|
|
76
|
+
proposals_created: number;
|
|
77
|
+
proposals_approved: number;
|
|
78
|
+
proposals_rejected: number;
|
|
79
|
+
artifact_writes_total: number;
|
|
80
|
+
artifact_writes_noop: number;
|
|
81
|
+
references_registered: number;
|
|
82
|
+
skills_registered: number;
|
|
83
|
+
skill_emission: EmissionState;
|
|
84
|
+
reference_emission: EmissionState;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export interface CurationReport {
|
|
88
|
+
eligible: number;
|
|
89
|
+
curated: number;
|
|
90
|
+
inferable: number;
|
|
91
|
+
non_inferable: number;
|
|
92
|
+
unknown: number;
|
|
93
|
+
proposals_by_status: Record<string, number>;
|
|
94
|
+
}
|
|
95
|
+
export declare function buildAudit(store: Store, metrics: Metrics, capabilities?: Capabilities): AuditReport;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { effectivePrePromptCap } from "./ContextInjector.js";
|
|
2
|
+
const ALL_FALSE_CAPABILITIES = {
|
|
3
|
+
skills: false,
|
|
4
|
+
references: false,
|
|
5
|
+
apiVersion: null,
|
|
6
|
+
};
|
|
7
|
+
function groupCounts(store, column) {
|
|
8
|
+
const rows = store
|
|
9
|
+
.prepare(`SELECT ${column} AS k, COUNT(*) AS n FROM memories GROUP BY ${column}`)
|
|
10
|
+
.all();
|
|
11
|
+
const out = {};
|
|
12
|
+
for (const r of rows) {
|
|
13
|
+
out[r.k ?? "unknown"] = r.n;
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function scalar(store, sql) {
|
|
18
|
+
const row = store.prepare(sql).get();
|
|
19
|
+
return row.n ?? 0;
|
|
20
|
+
}
|
|
21
|
+
export function buildAudit(store, metrics, capabilities = ALL_FALSE_CAPABILITIES) {
|
|
22
|
+
let partial = false;
|
|
23
|
+
// Memories block: `total` + the three GROUP BYs are pre-006 safe; the
|
|
24
|
+
// lifecycle counters need the 006 columns and fall back separately.
|
|
25
|
+
let memories = {
|
|
26
|
+
total: 0,
|
|
27
|
+
by_status: {},
|
|
28
|
+
by_origin: {},
|
|
29
|
+
by_type: {},
|
|
30
|
+
ignored: 0,
|
|
31
|
+
archived: 0,
|
|
32
|
+
with_feedback: 0,
|
|
33
|
+
superseded_with_target: 0,
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
memories = {
|
|
37
|
+
...memories,
|
|
38
|
+
total: scalar(store, "SELECT COUNT(*) AS n FROM memories"),
|
|
39
|
+
by_status: groupCounts(store, "status"),
|
|
40
|
+
by_origin: groupCounts(store, "origin"),
|
|
41
|
+
by_type: groupCounts(store, "type"),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
partial = true;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
memories = {
|
|
49
|
+
...memories,
|
|
50
|
+
ignored: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE ignored = 1"),
|
|
51
|
+
archived: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE status = 'archived'"),
|
|
52
|
+
with_feedback: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE feedback_positive > 0 OR feedback_negative > 0"),
|
|
53
|
+
superseded_with_target: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE status = 'superseded' AND superseded_by IS NOT NULL"),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
partial = true;
|
|
58
|
+
}
|
|
59
|
+
// Injections block: grouped rollup over the ledger (same query the
|
|
60
|
+
// InjectionLedger.outcomeCounts() runs), rates from the metric cache.
|
|
61
|
+
let injections = {
|
|
62
|
+
total: 0,
|
|
63
|
+
effective: 0,
|
|
64
|
+
ineffective: 0,
|
|
65
|
+
inconclusive: 0,
|
|
66
|
+
unmeasured: 0,
|
|
67
|
+
precision_rate: 0,
|
|
68
|
+
coverage_rate: 0,
|
|
69
|
+
};
|
|
70
|
+
try {
|
|
71
|
+
const rows = store
|
|
72
|
+
.prepare("SELECT outcome, COUNT(*) AS n FROM kevin_injections GROUP BY outcome")
|
|
73
|
+
.all();
|
|
74
|
+
const counts = {
|
|
75
|
+
unmeasured: 0,
|
|
76
|
+
effective: 0,
|
|
77
|
+
ineffective: 0,
|
|
78
|
+
inconclusive: 0,
|
|
79
|
+
};
|
|
80
|
+
for (const r of rows) {
|
|
81
|
+
counts[r.outcome] = r.n;
|
|
82
|
+
}
|
|
83
|
+
injections = {
|
|
84
|
+
total: rows.reduce((acc, r) => acc + r.n, 0),
|
|
85
|
+
effective: counts.effective,
|
|
86
|
+
ineffective: counts.ineffective,
|
|
87
|
+
inconclusive: counts.inconclusive,
|
|
88
|
+
unmeasured: counts.unmeasured,
|
|
89
|
+
precision_rate: metrics.precisionRate(),
|
|
90
|
+
coverage_rate: metrics.coverageRate(),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
partial = true;
|
|
95
|
+
}
|
|
96
|
+
// Feedback block: verdict rollup from the table, totals from the cache.
|
|
97
|
+
let feedback = {
|
|
98
|
+
positive: 0,
|
|
99
|
+
negative: 0,
|
|
100
|
+
by_verdict: {},
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
const rows = store
|
|
104
|
+
.prepare("SELECT verdict, COUNT(*) AS n FROM memory_feedback GROUP BY verdict")
|
|
105
|
+
.all();
|
|
106
|
+
const byVerdict = {};
|
|
107
|
+
for (const r of rows) {
|
|
108
|
+
byVerdict[r.verdict] = r.n;
|
|
109
|
+
}
|
|
110
|
+
feedback = {
|
|
111
|
+
positive: metrics.get("feedback_positive_total"),
|
|
112
|
+
negative: metrics.get("feedback_negative_total"),
|
|
113
|
+
by_verdict: byVerdict,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
partial = true;
|
|
118
|
+
}
|
|
119
|
+
const blocked = metrics.blockedSnapshot();
|
|
120
|
+
const tokens = {
|
|
121
|
+
pre_prompt: metrics.get("tokens_injected_pre_prompt"),
|
|
122
|
+
compacting: metrics.get("tokens_injected_compacting"),
|
|
123
|
+
};
|
|
124
|
+
let settings = {};
|
|
125
|
+
try {
|
|
126
|
+
const rows = store
|
|
127
|
+
.prepare("SELECT key, value FROM kevin_settings")
|
|
128
|
+
.all();
|
|
129
|
+
settings = {};
|
|
130
|
+
for (const r of rows) {
|
|
131
|
+
settings[r.key] = r.value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
partial = true;
|
|
136
|
+
}
|
|
137
|
+
// v0.6.0 (K6-023 / plan §5.8) — channels + curation. Both blocks are
|
|
138
|
+
// gated on migration 007's schema: on a pre-007 database they are
|
|
139
|
+
// OMITTED (not zero-valued) and `partial` is set, so the release's
|
|
140
|
+
// scoreboard is never presented as computed when it cannot be.
|
|
141
|
+
let channels;
|
|
142
|
+
let curation;
|
|
143
|
+
let hasSchema007 = false;
|
|
144
|
+
try {
|
|
145
|
+
store.prepare("SELECT 1 FROM curation_proposals LIMIT 1").get();
|
|
146
|
+
hasSchema007 = true;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
hasSchema007 = false;
|
|
150
|
+
}
|
|
151
|
+
if (hasSchema007) {
|
|
152
|
+
try {
|
|
153
|
+
const emission = (capable, key) => {
|
|
154
|
+
if (!capable)
|
|
155
|
+
return "unavailable";
|
|
156
|
+
return settings[key] === "1" ? "on" : "off";
|
|
157
|
+
};
|
|
158
|
+
const registered = (key) => {
|
|
159
|
+
const row = store
|
|
160
|
+
.prepare("SELECT value FROM kevin_metrics WHERE key = ?")
|
|
161
|
+
.get(key);
|
|
162
|
+
return row?.value ?? 0;
|
|
163
|
+
};
|
|
164
|
+
channels = {
|
|
165
|
+
push: {
|
|
166
|
+
tokens_pre_prompt: metrics.get("tokens_injected_pre_prompt"),
|
|
167
|
+
tokens_compacting: metrics.get("tokens_injected_compacting"),
|
|
168
|
+
injections_total: metrics.get("injections_total"),
|
|
169
|
+
precision_rate: metrics.precisionRate(),
|
|
170
|
+
coverage_rate: metrics.coverageRate(),
|
|
171
|
+
// The EFFECTIVE cap (K6-021 clamp semantics), not the raw
|
|
172
|
+
// setting: the channel comparison must use the budget the
|
|
173
|
+
// push channel actually charges against.
|
|
174
|
+
budget_tokens: effectivePrePromptCap(settings.pre_prompt_budget_tokens),
|
|
175
|
+
},
|
|
176
|
+
pull: {
|
|
177
|
+
proposals_created: metrics.get("proposals_created"),
|
|
178
|
+
// "approved" is the human decision: approved + applied.
|
|
179
|
+
proposals_approved: metrics.get("proposals_approved"),
|
|
180
|
+
proposals_rejected: metrics.get("proposals_rejected"),
|
|
181
|
+
artifact_writes_total: metrics.get("artifact_writes_total"),
|
|
182
|
+
artifact_writes_noop: metrics.get("artifact_writes_noop"),
|
|
183
|
+
references_registered: registered("references_registered"),
|
|
184
|
+
skills_registered: registered("skills_registered"),
|
|
185
|
+
skill_emission: emission(capabilities.skills, "skill_emission_enabled"),
|
|
186
|
+
reference_emission: emission(capabilities.references, "reference_emission_enabled"),
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
partial = true;
|
|
192
|
+
channels = undefined;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const proposalRows = store
|
|
196
|
+
.prepare("SELECT status, COUNT(*) AS n FROM curation_proposals GROUP BY status")
|
|
197
|
+
.all();
|
|
198
|
+
const byStatus = {};
|
|
199
|
+
for (const r of proposalRows) {
|
|
200
|
+
byStatus[r.status] = r.n;
|
|
201
|
+
}
|
|
202
|
+
curation = {
|
|
203
|
+
// The Curator predicate is `inferable != 1` (plan §5.5): an
|
|
204
|
+
// unclassified (NULL) memory must not be silently withheld.
|
|
205
|
+
eligible: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE inferable IS NOT 1"),
|
|
206
|
+
curated: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE curated = 1"),
|
|
207
|
+
inferable: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE inferable = 1"),
|
|
208
|
+
non_inferable: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE inferable = 0"),
|
|
209
|
+
unknown: scalar(store, "SELECT COUNT(*) AS n FROM memories WHERE inferable IS NULL"),
|
|
210
|
+
proposals_by_status: byStatus,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
partial = true;
|
|
215
|
+
curation = undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
partial = true;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
memories,
|
|
223
|
+
injections,
|
|
224
|
+
blocked,
|
|
225
|
+
feedback,
|
|
226
|
+
tokens,
|
|
227
|
+
settings,
|
|
228
|
+
channels,
|
|
229
|
+
curation,
|
|
230
|
+
partial,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=kevin_audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kevin_audit.js","sourceRoot":"","sources":["../../plugin/kevin_audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ArtifactWriter } from "./ArtifactWriter.js";
|
|
2
|
+
import type { Curator, ProposalKind } from "./Curator.js";
|
|
3
|
+
/**
|
|
4
|
+
* K6-014 — v0.6.0 pull — `kevin_propose` tool logic.
|
|
5
|
+
*
|
|
6
|
+
* Strict dry run in the exact sense of v0.5 `kevin_trace` (D5-08): creates
|
|
7
|
+
* `pending` rows and returns their unified diffs. No disk write, no `curated`
|
|
8
|
+
* flag, no metric beyond `proposals_created` (which `Curator.propose()`
|
|
9
|
+
* itself increments).
|
|
10
|
+
*/
|
|
11
|
+
export interface ProposedChange {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly kind: ProposalKind;
|
|
14
|
+
readonly targetPath: string;
|
|
15
|
+
readonly memoryIds: readonly string[];
|
|
16
|
+
readonly status: "pending";
|
|
17
|
+
readonly createdAt: string;
|
|
18
|
+
readonly diff: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ProposeResult {
|
|
21
|
+
readonly proposals: readonly ProposedChange[];
|
|
22
|
+
}
|
|
23
|
+
export declare function kevinPropose(curator: Curator, writer: ArtifactWriter, kind: ProposalKind): ProposeResult;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function kevinPropose(curator, writer, kind) {
|
|
2
|
+
const proposals = curator.propose(kind, writer);
|
|
3
|
+
return {
|
|
4
|
+
proposals: proposals.map((p) => ({
|
|
5
|
+
id: p.id,
|
|
6
|
+
kind: p.kind,
|
|
7
|
+
targetPath: p.targetPath,
|
|
8
|
+
memoryIds: [...p.memoryIds],
|
|
9
|
+
status: "pending",
|
|
10
|
+
createdAt: p.createdAt,
|
|
11
|
+
diff: p.diff,
|
|
12
|
+
})),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=kevin_propose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kevin_propose.js","sourceRoot":"","sources":["../../plugin/kevin_propose.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,YAAY,CAC3B,OAAgB,EAChB,MAAsB,EACtB,IAAkB;IAElB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChD,OAAO;QACN,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;YAC3B,MAAM,EAAE,SAAkB;YAC1B,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,IAAI,EAAE,CAAC,CAAC,IAAI;SACZ,CAAC,CAAC;KACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ArtifactWriter } from "./ArtifactWriter.js";
|
|
2
|
+
import type { MaterializedBundle, Materializer } from "./Materializer.js";
|
|
3
|
+
import type { MemoryService } from "./MemoryService.js";
|
|
4
|
+
import type { Capabilities } from "./capabilities.js";
|
|
5
|
+
/**
|
|
6
|
+
* K6-020 — v0.6.0 pull — `kevin_publish` tool logic.
|
|
7
|
+
*
|
|
8
|
+
* Regenerates the pull-channel bundles on demand. Writes only through the
|
|
9
|
+
* `ArtifactWriter` and only to the Materializer's targets (D6-01, D6-07):
|
|
10
|
+
* `~/.opencode-kevin/skills/project-knowledge.md` and
|
|
11
|
+
* `~/.opencode-kevin/refs/<topic>.md`. `agents_md_path` is unreachable
|
|
12
|
+
* here by construction — the paths come from `bundleTargets()`, never from
|
|
13
|
+
* a setting — and that is asserted in the integration test even when the
|
|
14
|
+
* setting points inside `~/.opencode-kevin/`.
|
|
15
|
+
*
|
|
16
|
+
* Registration is a session-start concern (K6-018/019), not this tool's:
|
|
17
|
+
* the output reports the emission state honestly (`"unavailable"` on a v1
|
|
18
|
+
* host, `"off"` for a '0' setting, `"on"` when session start registers)
|
|
19
|
+
* instead of pretending success.
|
|
20
|
+
*/
|
|
21
|
+
export type EmissionState = "on" | "off" | "unavailable";
|
|
22
|
+
export interface PublishResult {
|
|
23
|
+
readonly bundles: readonly {
|
|
24
|
+
readonly topic: string;
|
|
25
|
+
readonly outcome: MaterializedBundle["outcome"];
|
|
26
|
+
}[];
|
|
27
|
+
readonly emission: {
|
|
28
|
+
readonly skill: EmissionState;
|
|
29
|
+
readonly reference: EmissionState;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface PublishDeps {
|
|
33
|
+
readonly materializer: Materializer;
|
|
34
|
+
readonly writer: ArtifactWriter;
|
|
35
|
+
readonly memoryService: MemoryService;
|
|
36
|
+
readonly capabilities: Capabilities;
|
|
37
|
+
}
|
|
38
|
+
export declare function kevinPublish(deps: PublishDeps): PublishResult;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function emissionState(capable, setting) {
|
|
2
|
+
if (!capable)
|
|
3
|
+
return "unavailable";
|
|
4
|
+
return setting === "1" ? "on" : "off";
|
|
5
|
+
}
|
|
6
|
+
export function kevinPublish(deps) {
|
|
7
|
+
const bundles = deps.materializer.materialize(deps.writer);
|
|
8
|
+
return {
|
|
9
|
+
bundles: bundles.map((b) => ({
|
|
10
|
+
topic: b.topic,
|
|
11
|
+
outcome: b.outcome,
|
|
12
|
+
})),
|
|
13
|
+
emission: {
|
|
14
|
+
skill: emissionState(deps.capabilities.skills, deps.memoryService.getSetting("skill_emission_enabled", "0")),
|
|
15
|
+
reference: emissionState(deps.capabilities.references, deps.memoryService.getSetting("reference_emission_enabled", "0")),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=kevin_publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kevin_publish.js","sourceRoot":"","sources":["../../plugin/kevin_publish.ts"],"names":[],"mappings":"AA0CA,SAAS,aAAa,CACrB,OAAgB,EAChB,OAA2B;IAE3B,IAAI,CAAC,OAAO;QAAE,OAAO,aAAa,CAAC;IACnC,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,OAAO;SAClB,CAAC,CAAC;QACH,QAAQ,EAAE;YACT,KAAK,EAAE,aAAa,CACnB,IAAI,CAAC,YAAY,CAAC,MAAM,EACxB,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAC5D;YACD,SAAS,EAAE,aAAa,CACvB,IAAI,CAAC,YAAY,CAAC,UAAU,EAC5B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAChE;SACD;KACD,CAAC;AACH,CAAC"}
|