@xaccefy/pi-casefile 0.1.8 → 0.2.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/package.json +1 -1
- package/src/index.ts +8 -10
- package/src/ledger.ts +14 -0
- package/src/sqlite-compat/index.ts +30 -5
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -241,15 +241,15 @@ function renderCaseResult(
|
|
|
241
241
|
theme: Theme,
|
|
242
242
|
successPrefix = "✓ ",
|
|
243
243
|
failPrefix = "✗ ",
|
|
244
|
-
):
|
|
244
|
+
): string {
|
|
245
245
|
const details = result.details as { record?: CaseRecord; changed?: boolean } | undefined;
|
|
246
246
|
if (!details?.record) {
|
|
247
|
-
return
|
|
247
|
+
return theme.fg("error", "✗ Failed");
|
|
248
248
|
}
|
|
249
249
|
const success = details.changed !== false;
|
|
250
250
|
const prefix = success ? successPrefix : failPrefix;
|
|
251
251
|
const color = success ? "success" : "warning";
|
|
252
|
-
return
|
|
252
|
+
return theme.fg(color, prefix) + renderOneLine(details.record, theme);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
// ── Dashboard component ──────────────────────────────────────────────
|
|
@@ -409,7 +409,7 @@ function buildCaseContext(records: CaseRecord[]): string {
|
|
|
409
409
|
if (records.length === 0) return "";
|
|
410
410
|
|
|
411
411
|
const safe = (v?: string, max = 160) => {
|
|
412
|
-
const controlChars =
|
|
412
|
+
const controlChars = /[\r\n\t\u0000-\u001F\u007F\u2028\u2029]+/g;
|
|
413
413
|
const s = v
|
|
414
414
|
?.replace(controlChars, " ")
|
|
415
415
|
.replace(/[<>]/g, (c) => (c === "<" ? "‹" : "›"))
|
|
@@ -547,8 +547,7 @@ export default function casefileExtension(pi: ExtensionAPI) {
|
|
|
547
547
|
renderResult(result, { expanded }, theme) {
|
|
548
548
|
const details = result.details as { created?: boolean; record?: CaseRecord };
|
|
549
549
|
const created = details?.created;
|
|
550
|
-
|
|
551
|
-
let line = baseText.toString();
|
|
550
|
+
let line = renderCaseResult(result, theme, created === false ? "↻ " : "✓ ");
|
|
552
551
|
if (expanded && details?.record) {
|
|
553
552
|
line += `\n${theme.fg("dim", ` ${details.record.id} → ${details.record.nextStep ?? "no next step"}`)}`;
|
|
554
553
|
}
|
|
@@ -603,8 +602,7 @@ export default function casefileExtension(pi: ExtensionAPI) {
|
|
|
603
602
|
renderResult(result, { expanded }, theme) {
|
|
604
603
|
const details = result.details as { changed?: boolean; record?: CaseRecord; reason?: string };
|
|
605
604
|
const unchanged = details?.changed === false;
|
|
606
|
-
|
|
607
|
-
let line = baseText.toString();
|
|
605
|
+
let line = renderCaseResult(result, theme, unchanged ? "↷ " : "✓ ");
|
|
608
606
|
if (expanded && details?.record) {
|
|
609
607
|
line +=
|
|
610
608
|
"\n" +
|
|
@@ -672,7 +670,7 @@ export default function casefileExtension(pi: ExtensionAPI) {
|
|
|
672
670
|
renderResult(result, _options, theme) {
|
|
673
671
|
const details = result.details as { run?: { exitCode: number } } | undefined;
|
|
674
672
|
const success = details?.run?.exitCode === 0;
|
|
675
|
-
return renderCaseResult(result, theme, success ? "✓ " : "✗ ", "✗ ");
|
|
673
|
+
return new Text(renderCaseResult(result, theme, success ? "✓ " : "✗ ", "✗ "), 0, 0);
|
|
676
674
|
},
|
|
677
675
|
});
|
|
678
676
|
|
|
@@ -705,7 +703,7 @@ export default function casefileExtension(pi: ExtensionAPI) {
|
|
|
705
703
|
},
|
|
706
704
|
|
|
707
705
|
renderResult(result, _options, theme) {
|
|
708
|
-
return renderCaseResult(result, theme, "", "");
|
|
706
|
+
return new Text(renderCaseResult(result, theme, "", ""), 0, 0);
|
|
709
707
|
},
|
|
710
708
|
});
|
|
711
709
|
|
package/src/ledger.ts
CHANGED
|
@@ -724,10 +724,18 @@ export function promoteFindingResult(id: string, verification: PocVerification):
|
|
|
724
724
|
);
|
|
725
725
|
}
|
|
726
726
|
|
|
727
|
+
const newEvidence =
|
|
728
|
+
(current.evidence ? current.evidence + "\n\n" : "") +
|
|
729
|
+
`### PoC Execution Capture (${verification.ranAt})\n` +
|
|
730
|
+
`- **Exit Code:** ${verification.exitCode}\n` +
|
|
731
|
+
`- **Sandbox:** ${verification.sandbox ? "yes" : "no"}\n` +
|
|
732
|
+
`#### Execution Output\n\`\`\`\n${verification.output ?? ""}\n\`\`\``;
|
|
733
|
+
|
|
727
734
|
const next = buildRecord(
|
|
728
735
|
{
|
|
729
736
|
status: "confirmed",
|
|
730
737
|
pocVerified: verification,
|
|
738
|
+
evidence: newEvidence,
|
|
731
739
|
},
|
|
732
740
|
current,
|
|
733
741
|
);
|
|
@@ -958,6 +966,12 @@ export function writeCaseReport(id: string): { path: string; record: CaseRecord
|
|
|
958
966
|
mdSection("Summary", current.summary),
|
|
959
967
|
mdSection("Steps to Reproduce / Evidence", current.evidence),
|
|
960
968
|
mdSection("Proof of Concept", current.poc),
|
|
969
|
+
current.pocVerified
|
|
970
|
+
? mdSection(
|
|
971
|
+
"PoC Verification Log",
|
|
972
|
+
`### PoC Run Verification\n- **Timestamp:** ${current.pocVerified.ranAt}\n- **Path:** \`${current.pocVerified.path}\`\n- **Sandbox:** ${current.pocVerified.sandbox ? "yes" : "no"}\n- **Exit Code:** ${current.pocVerified.exitCode}\n\n#### Output\n\`\`\`\n${current.pocVerified.output ?? ""}\n\`\`\``,
|
|
973
|
+
)
|
|
974
|
+
: undefined,
|
|
961
975
|
mdSection("Impact", current.impact),
|
|
962
976
|
mdSection("Remediation", current.remediation),
|
|
963
977
|
mdSection("Assumptions and Uncertainty", assumptions),
|
|
@@ -1,5 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const _require = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
// biome-ignore lint/suspicious/noExplicitAny: Runtime module swappability requires any casting
|
|
6
|
+
let DatabaseSyncConstructor: any;
|
|
7
|
+
try {
|
|
8
|
+
// biome-ignore lint/suspicious/noExplicitAny: Runtime module swappability
|
|
9
|
+
DatabaseSyncConstructor = _require("bun:sqlite").Database as any;
|
|
10
|
+
} catch {
|
|
11
|
+
// biome-ignore lint/suspicious/noExplicitAny: Runtime module swappability
|
|
12
|
+
DatabaseSyncConstructor = (_require("node:sqlite") as any).DatabaseSync;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// biome-ignore lint/suspicious/noExplicitAny: Standard SQLite API returns any
|
|
16
|
+
export interface StatementSync {
|
|
17
|
+
run(...args: unknown[]): { lastInsertRowid: number; changes: number };
|
|
18
|
+
// biome-ignore lint/suspicious/noExplicitAny: Standard SQLite API returns any
|
|
19
|
+
get(...args: unknown[]): any;
|
|
20
|
+
// biome-ignore lint/suspicious/noExplicitAny: Standard SQLite API returns any
|
|
21
|
+
all(...args: unknown[]): any[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DatabaseSync {
|
|
25
|
+
prepare(sql: string): StatementSync;
|
|
26
|
+
exec(sql: string): void;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const DatabaseSync: new (path: string) => DatabaseSync = DatabaseSyncConstructor;
|