hex-audit 0.5.1 → 0.5.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.
Files changed (89) hide show
  1. package/dashboard/.next/BUILD_ID +1 -1
  2. package/dashboard/.next/app-build-manifest.json +23 -22
  3. package/dashboard/.next/app-path-routes-manifest.json +1 -1
  4. package/dashboard/.next/build-manifest.json +2 -2
  5. package/dashboard/.next/next-minimal-server.js.nft.json +1 -1
  6. package/dashboard/.next/next-server.js.nft.json +1 -1
  7. package/dashboard/.next/prerender-manifest.json +1 -1
  8. package/dashboard/.next/server/app/_not-found/page.js +1 -1
  9. package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
  10. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  11. package/dashboard/.next/server/app/_not-found.html +1 -1
  12. package/dashboard/.next/server/app/_not-found.rsc +4 -4
  13. package/dashboard/.next/server/app/access/page.js +1 -1
  14. package/dashboard/.next/server/app/access/page.js.nft.json +1 -1
  15. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +1 -1
  16. package/dashboard/.next/server/app/calls/page.js +1 -1
  17. package/dashboard/.next/server/app/calls/page.js.nft.json +1 -1
  18. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +1 -1
  19. package/dashboard/.next/server/app/conformance/page.js +1 -1
  20. package/dashboard/.next/server/app/conformance/page.js.nft.json +1 -1
  21. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +1 -1
  22. package/dashboard/.next/server/app/diagram/page.js +1 -1
  23. package/dashboard/.next/server/app/diagram/page.js.nft.json +1 -1
  24. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +1 -1
  25. package/dashboard/.next/server/app/diagram.html +1 -1
  26. package/dashboard/.next/server/app/diagram.rsc +4 -4
  27. package/dashboard/.next/server/app/flows/page.js +1 -1
  28. package/dashboard/.next/server/app/flows/page.js.nft.json +1 -1
  29. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +1 -1
  30. package/dashboard/.next/server/app/flows.html +1 -1
  31. package/dashboard/.next/server/app/flows.rsc +4 -4
  32. package/dashboard/.next/server/app/functions/page.js +1 -1
  33. package/dashboard/.next/server/app/functions/page.js.nft.json +1 -1
  34. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +1 -1
  35. package/dashboard/.next/server/app/issues/page.js +28 -5
  36. package/dashboard/.next/server/app/issues/page.js.nft.json +1 -1
  37. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
  38. package/dashboard/.next/server/app/overleaf/page.js +1 -1
  39. package/dashboard/.next/server/app/overleaf/page.js.nft.json +1 -1
  40. package/dashboard/.next/server/app/overleaf/page_client-reference-manifest.js +1 -1
  41. package/dashboard/.next/server/app/page.js +2 -2
  42. package/dashboard/.next/server/app/page.js.nft.json +1 -1
  43. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  44. package/dashboard/.next/server/app/progress/page.js +1 -1
  45. package/dashboard/.next/server/app/progress/page.js.nft.json +1 -1
  46. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +1 -1
  47. package/dashboard/.next/server/app/stats/page.js +1 -1
  48. package/dashboard/.next/server/app/stats/page.js.nft.json +1 -1
  49. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +1 -1
  50. package/dashboard/.next/server/app-paths-manifest.json +9 -9
  51. package/dashboard/.next/server/chunks/494.js +1 -0
  52. package/dashboard/.next/server/chunks/{431.js → 530.js} +1 -1
  53. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  54. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  55. package/dashboard/.next/server/pages/404.html +1 -1
  56. package/dashboard/.next/server/pages/500.html +1 -1
  57. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  58. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  59. package/dashboard/.next/static/chunks/app/issues/page-abb062e4cf118340.js +1 -0
  60. package/dashboard/.next/static/chunks/app/{layout-91d2987f5030a3c4.js → layout-2c5383c11b1fbd97.js} +1 -1
  61. package/dashboard/.next/static/chunks/app/{page-a0f25953d4457935.js → page-1226422e170d8895.js} +1 -1
  62. package/dashboard/.next/static/css/691f4e9edab008c8.css +3 -0
  63. package/dashboard/app/issues/IssuesBoardClient.tsx +68 -22
  64. package/dashboard/app/layout.tsx +2 -1
  65. package/dashboard/components/DashboardLayout.tsx +11 -3
  66. package/dist/commands/note.d.ts +3 -0
  67. package/dist/commands/note.d.ts.map +1 -0
  68. package/dist/commands/note.js +145 -0
  69. package/dist/commands/note.js.map +1 -0
  70. package/dist/core/notes.d.ts +62 -0
  71. package/dist/core/notes.d.ts.map +1 -0
  72. package/dist/core/notes.js +160 -0
  73. package/dist/core/notes.js.map +1 -0
  74. package/dist/core/whisper.d.ts +24 -0
  75. package/dist/core/whisper.d.ts.map +1 -0
  76. package/dist/core/whisper.js +124 -0
  77. package/dist/core/whisper.js.map +1 -0
  78. package/dist/index.js +6 -1
  79. package/dist/index.js.map +1 -1
  80. package/dist/skills/diane.md +99 -0
  81. package/dist/skills/ingest-aa-report.md +1 -1
  82. package/dist/skills/sync-issues.md +23 -3
  83. package/dist/skills/validate-issue.md +1 -1
  84. package/dist/skills/write-finding.md +2 -1
  85. package/package.json +1 -1
  86. package/dashboard/.next/static/chunks/app/issues/page-6bfbf80884d3c9d8.js +0 -1
  87. package/dashboard/.next/static/css/9c84313d0484b74f.css +0 -3
  88. /package/dashboard/.next/static/{dm-uzRRik5AgaBPedT1iR → 8MjKGPuSZw4OIpcHY4G0W}/_buildManifest.js +0 -0
  89. /package/dashboard/.next/static/{dm-uzRRik5AgaBPedT1iR → 8MjKGPuSZw4OIpcHY4G0W}/_ssgManifest.js +0 -0
@@ -361,7 +361,13 @@ function ThemeToggle() {
361
361
  }
362
362
 
363
363
  /* ── Layout ── */
364
- export function DashboardLayout({ children }: { children: React.ReactNode }) {
364
+ export function DashboardLayout({
365
+ children,
366
+ version,
367
+ }: {
368
+ children: React.ReactNode;
369
+ version: string;
370
+ }) {
365
371
  const pathname = usePathname();
366
372
  const [sidebarOpen, setSidebarOpen] = useState(false);
367
373
 
@@ -401,7 +407,7 @@ export function DashboardLayout({ children }: { children: React.ReactNode }) {
401
407
  <div className="px-5 pb-4 pt-6">
402
408
  <div className="flex items-baseline gap-2">
403
409
  <span className="text-title font-semibold text-text-primary">Hex</span>
404
- <span className="text-caption text-text-tertiary">v0.5.1</span>
410
+ <span className="text-caption text-text-tertiary">v{version}</span>
405
411
  </div>
406
412
  </div>
407
413
 
@@ -449,7 +455,9 @@ export function DashboardLayout({ children }: { children: React.ReactNode }) {
449
455
 
450
456
  {/* Main content */}
451
457
  <main className="min-h-screen bg-surface-0 p-6 pt-16 md:ml-[220px] md:pt-6">
452
- <div className="mx-auto max-w-6xl">{children}</div>
458
+ <div className={`mx-auto ${pathname === '/issues' ? 'max-w-none' : 'max-w-6xl'}`}>
459
+ {children}
460
+ </div>
453
461
  </main>
454
462
  </div>
455
463
  );
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const noteCommand: Command;
3
+ //# sourceMappingURL=note.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"note.d.ts","sourceRoot":"","sources":["../../src/commands/note.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsJpC,eAAO,MAAM,WAAW,SAOC,CAAC"}
@@ -0,0 +1,145 @@
1
+ import { Command } from 'commander';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { logger } from '../core/logger.js';
5
+ import { loadProjectContext } from '../core/config.js';
6
+ import { reportError } from '../core/errors.js';
7
+ import { readNote, writeNote, appendNote, readNotesIndex, setActiveContract, createSession, latestUnprocessedSession, markSessionProcessed, } from '../core/notes.js';
8
+ function resolveOutputDir(opts) {
9
+ return loadProjectContext(opts.project ?? process.cwd()).outputDir;
10
+ }
11
+ function readFileTrim(p) {
12
+ return fs.readFileSync(path.resolve(p), 'utf-8').trim();
13
+ }
14
+ const readCmd = new Command('read')
15
+ .description('Print a note doc (target: "general" or a contract name)')
16
+ .argument('<target>', '"general" or a contract name')
17
+ .option('--project <dir>', 'Project directory')
18
+ .action((target, opts) => {
19
+ try {
20
+ process.stdout.write(readNote(resolveOutputDir(opts), target));
21
+ }
22
+ catch (err) {
23
+ reportError(err);
24
+ process.exit(1);
25
+ }
26
+ });
27
+ const writeCmd = new Command('write')
28
+ .description('Replace a note doc with the contents of a file')
29
+ .argument('<target>', '"general" or a contract name')
30
+ .requiredOption('--body-file <path>', 'Read the note body from this file')
31
+ .option('--project <dir>', 'Project directory')
32
+ .action((target, opts) => {
33
+ try {
34
+ writeNote(resolveOutputDir(opts), target, readFileTrim(opts.bodyFile));
35
+ logger.success(`Wrote note: ${target}`);
36
+ }
37
+ catch (err) {
38
+ reportError(err);
39
+ process.exit(1);
40
+ }
41
+ });
42
+ const appendCmd = new Command('append')
43
+ .description('Append a block to a note doc (Diane accretes notes this way)')
44
+ .argument('<target>', '"general" or a contract name')
45
+ .requiredOption('--body-file <path>', 'Read the block to append from this file')
46
+ .option('--project <dir>', 'Project directory')
47
+ .action((target, opts) => {
48
+ try {
49
+ appendNote(resolveOutputDir(opts), target, readFileTrim(opts.bodyFile));
50
+ logger.success(`Appended to note: ${target}`);
51
+ }
52
+ catch (err) {
53
+ reportError(err);
54
+ process.exit(1);
55
+ }
56
+ });
57
+ const listCmd = new Command('list')
58
+ .description('Print the notes index (active contract, contracts, sessions) as JSON')
59
+ .option('--project <dir>', 'Project directory')
60
+ .action((opts) => {
61
+ try {
62
+ console.log(JSON.stringify(readNotesIndex(resolveOutputDir(opts)), null, 2));
63
+ }
64
+ catch (err) {
65
+ reportError(err);
66
+ process.exit(1);
67
+ }
68
+ });
69
+ const activeCmd = new Command('active')
70
+ .description('Set the active contract (the one being narrated)')
71
+ .argument('<name>', 'Contract name')
72
+ .option('--project <dir>', 'Project directory')
73
+ .action((name, opts) => {
74
+ try {
75
+ setActiveContract(resolveOutputDir(opts), name);
76
+ logger.success(`Active contract → ${name}`);
77
+ }
78
+ catch (err) {
79
+ reportError(err);
80
+ process.exit(1);
81
+ }
82
+ });
83
+ // ─── session subcommands ────────────────────────────────────────────
84
+ const sessionLatestCmd = new Command('latest')
85
+ .description('Print the latest unprocessed narration session (with transcript) as JSON, for /diane')
86
+ .option('--project <dir>', 'Project directory')
87
+ .action((opts) => {
88
+ try {
89
+ const session = latestUnprocessedSession(resolveOutputDir(opts));
90
+ console.log(JSON.stringify(session, null, 2));
91
+ }
92
+ catch (err) {
93
+ reportError(err);
94
+ process.exit(1);
95
+ }
96
+ });
97
+ const sessionAddCmd = new Command('add')
98
+ .description('Register a session from an existing transcript file (no audio/whisper — useful for testing)')
99
+ .requiredOption('--transcript-file <path>', 'Transcript text file')
100
+ .requiredOption('--contract <name>', 'Contract this session covers')
101
+ .option('--ts <iso>', 'Timestamp (defaults to now)')
102
+ .option('--project <dir>', 'Project directory')
103
+ .action((opts) => {
104
+ try {
105
+ const ts = (opts.ts ?? new Date().toISOString()).replace(/[:.]/g, '-');
106
+ const session = createSession(resolveOutputDir(opts), {
107
+ ts,
108
+ contract: opts.contract,
109
+ transcript: readFileTrim(opts.transcriptFile),
110
+ });
111
+ logger.success(`Session added: ${session.file} (contract: ${session.contract})`);
112
+ }
113
+ catch (err) {
114
+ reportError(err);
115
+ process.exit(1);
116
+ }
117
+ });
118
+ const sessionMarkCmd = new Command('mark-processed')
119
+ .description('Mark a session as ingested by Diane')
120
+ .argument('<file>', 'Session file (relative path from `hex note session latest`)')
121
+ .option('--project <dir>', 'Project directory')
122
+ .action((file, opts) => {
123
+ try {
124
+ markSessionProcessed(resolveOutputDir(opts), file);
125
+ logger.success(`Session marked processed: ${file}`);
126
+ }
127
+ catch (err) {
128
+ reportError(err);
129
+ process.exit(1);
130
+ }
131
+ });
132
+ const sessionCmd = new Command('session')
133
+ .description('Manage narration sessions (latest / add / mark-processed)')
134
+ .addCommand(sessionLatestCmd)
135
+ .addCommand(sessionAddCmd)
136
+ .addCommand(sessionMarkCmd);
137
+ export const noteCommand = new Command('note')
138
+ .description('Read and write Diane audit notes (read / write / append / list / active / session)')
139
+ .addCommand(readCmd)
140
+ .addCommand(writeCmd)
141
+ .addCommand(appendCmd)
142
+ .addCommand(listCmd)
143
+ .addCommand(activeCmd)
144
+ .addCommand(sessionCmd);
145
+ //# sourceMappingURL=note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"note.js","sourceRoot":"","sources":["../../src/commands/note.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ export interface SessionEntry {
2
+ /** Path relative to the notes dir, e.g. `sessions/2026-06-04T...md`. */
3
+ file: string;
4
+ /** Contract this session was recorded against (or `general`). */
5
+ contract: string;
6
+ /** ISO timestamp the session was created. */
7
+ ts: string;
8
+ /** Whether Diane has already ingested this transcript. */
9
+ processed: boolean;
10
+ /** Path (relative to notes dir) of the raw recording, if any. */
11
+ audio?: string;
12
+ }
13
+ export interface NotesIndex {
14
+ /** Contract currently being narrated (drives the dashboard default). */
15
+ active_contract: string | null;
16
+ /** Contracts that have a note doc. */
17
+ contracts: string[];
18
+ /** Recorded narration sessions, newest last. */
19
+ sessions: SessionEntry[];
20
+ }
21
+ /** Resolve a note target (`general` or a contract name) to its `.md` path. */
22
+ export declare function notePath(outputDir: string, target: string): string;
23
+ export declare function readNotesIndex(outputDir: string): NotesIndex;
24
+ export declare function writeNotesIndex(outputDir: string, index: NotesIndex): void;
25
+ /** Read a note doc. Returns '' when it doesn't exist yet. */
26
+ export declare function readNote(outputDir: string, target: string): string;
27
+ /** Replace a note doc wholesale (used by the dashboard editor's Save). */
28
+ export declare function writeNote(outputDir: string, target: string, body: string): void;
29
+ /**
30
+ * Append a block to a note doc, separated by a blank line. This is how `/diane`
31
+ * accretes structured notes across narration sessions.
32
+ */
33
+ export declare function appendNote(outputDir: string, target: string, body: string): void;
34
+ export declare function listContracts(outputDir: string): string[];
35
+ export declare function setActiveContract(outputDir: string, name: string): void;
36
+ /**
37
+ * Register a freshly recorded narration session and make its contract active.
38
+ * `file` / `audio` are paths relative to the notes dir.
39
+ */
40
+ export declare function addSession(outputDir: string, entry: {
41
+ file: string;
42
+ contract: string;
43
+ ts: string;
44
+ audio?: string;
45
+ }): SessionEntry;
46
+ /** The most recent session Diane hasn't ingested yet, with its transcript. */
47
+ export declare function latestUnprocessedSession(outputDir: string): (SessionEntry & {
48
+ text: string;
49
+ }) | null;
50
+ export declare function markSessionProcessed(outputDir: string, file: string): void;
51
+ /**
52
+ * Write a transcript into `sessions/<ts>.md` and register it. Returns the
53
+ * session's relative file path. Used by the dashboard record route (after
54
+ * transcription) and by `hex note session add` (for testing without audio).
55
+ */
56
+ export declare function createSession(outputDir: string, opts: {
57
+ ts: string;
58
+ contract: string;
59
+ transcript: string;
60
+ audio?: string;
61
+ }): SessionEntry;
62
+ //# sourceMappingURL=notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/core/notes.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sCAAsC;IACtC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gDAAgD;IAChD,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAeD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGlE;AAsBD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAa5D;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAK1E;AAUD,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAK/E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIhF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKvE;AAID;;;GAGG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE,YAAY,CAcd;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,GAChB,CAAC,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAU1C;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM1E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,YAAY,CAKd"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Canonical notes-mutation logic for Diane — the voice-narration audit
3
+ * companion. Shared by the `hex note` CLI command, the `/diane` skill (which
4
+ * shells `hex note ...`), and the dashboard's Notes API routes.
5
+ *
6
+ * Notes live under `<output_dir>/notes/`:
7
+ * notes.json index: active contract, contract list, sessions
8
+ * general.md cross-cutting / protocol-wide notes
9
+ * contracts/<Name>.md one Obsidian-style doc per contract
10
+ * sessions/<ts>.md raw transcripts (audit trail; never auto-deleted)
11
+ * audio/<ts>.webm raw recordings (kept until transcribed)
12
+ *
13
+ * Like src/core/issues.ts, this module depends ONLY on node:fs / node:path and
14
+ * is parameterized by `outputDir`, so the dashboard can import it across the
15
+ * src/ <-> dashboard/ boundary via `experimental.externalDir` without dragging
16
+ * CLI deps (chalk/ora/zod) into the Next.js bundle. Keep it that way.
17
+ */
18
+ import fs from 'node:fs';
19
+ import path from 'node:path';
20
+ const EMPTY_INDEX = { active_contract: null, contracts: [], sessions: [] };
21
+ // ─── Paths ──────────────────────────────────────────────────────────
22
+ function notesDir(outputDir) {
23
+ return path.join(outputDir, 'notes');
24
+ }
25
+ /** Filesystem-safe doc filename from a contract display name. */
26
+ function safeName(name) {
27
+ return name.replace(/[/\\:*?"<>|]/g, '_').trim();
28
+ }
29
+ /** Resolve a note target (`general` or a contract name) to its `.md` path. */
30
+ export function notePath(outputDir, target) {
31
+ if (target === 'general')
32
+ return path.join(notesDir(outputDir), 'general.md');
33
+ return path.join(notesDir(outputDir), 'contracts', safeName(target) + '.md');
34
+ }
35
+ // ─── Low-level IO (atomic) ──────────────────────────────────────────
36
+ function readText(file) {
37
+ try {
38
+ return fs.readFileSync(file, 'utf-8');
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ function writeTextAtomic(file, content) {
45
+ const dir = path.dirname(file);
46
+ if (!fs.existsSync(dir))
47
+ fs.mkdirSync(dir, { recursive: true });
48
+ const tmp = file + '.tmp';
49
+ fs.writeFileSync(tmp, content, 'utf-8');
50
+ fs.renameSync(tmp, file);
51
+ }
52
+ // ─── Index ──────────────────────────────────────────────────────────
53
+ export function readNotesIndex(outputDir) {
54
+ const raw = readText(path.join(notesDir(outputDir), 'notes.json'));
55
+ if (!raw)
56
+ return { ...EMPTY_INDEX };
57
+ try {
58
+ const parsed = JSON.parse(raw);
59
+ return {
60
+ active_contract: parsed.active_contract ?? null,
61
+ contracts: Array.isArray(parsed.contracts) ? parsed.contracts : [],
62
+ sessions: Array.isArray(parsed.sessions) ? parsed.sessions : [],
63
+ };
64
+ }
65
+ catch {
66
+ return { ...EMPTY_INDEX };
67
+ }
68
+ }
69
+ export function writeNotesIndex(outputDir, index) {
70
+ writeTextAtomic(path.join(notesDir(outputDir), 'notes.json'), JSON.stringify(index, null, 2) + '\n');
71
+ }
72
+ /** Ensure a contract is tracked in the index (no-op for `general`). */
73
+ function trackContract(index, target) {
74
+ if (target === 'general')
75
+ return;
76
+ if (!index.contracts.includes(target))
77
+ index.contracts.push(target);
78
+ }
79
+ // ─── Notes ──────────────────────────────────────────────────────────
80
+ /** Read a note doc. Returns '' when it doesn't exist yet. */
81
+ export function readNote(outputDir, target) {
82
+ return readText(notePath(outputDir, target)) ?? '';
83
+ }
84
+ /** Replace a note doc wholesale (used by the dashboard editor's Save). */
85
+ export function writeNote(outputDir, target, body) {
86
+ writeTextAtomic(notePath(outputDir, target), body.endsWith('\n') ? body : body + '\n');
87
+ const index = readNotesIndex(outputDir);
88
+ trackContract(index, target);
89
+ writeNotesIndex(outputDir, index);
90
+ }
91
+ /**
92
+ * Append a block to a note doc, separated by a blank line. This is how `/diane`
93
+ * accretes structured notes across narration sessions.
94
+ */
95
+ export function appendNote(outputDir, target, body) {
96
+ const existing = readNote(outputDir, target);
97
+ const sep = existing.trim() === '' ? '' : (existing.endsWith('\n') ? '\n' : '\n\n');
98
+ writeNote(outputDir, target, existing + sep + body.trim() + '\n');
99
+ }
100
+ export function listContracts(outputDir) {
101
+ return readNotesIndex(outputDir).contracts;
102
+ }
103
+ export function setActiveContract(outputDir, name) {
104
+ const index = readNotesIndex(outputDir);
105
+ index.active_contract = name;
106
+ trackContract(index, name);
107
+ writeNotesIndex(outputDir, index);
108
+ }
109
+ // ─── Sessions ───────────────────────────────────────────────────────
110
+ /**
111
+ * Register a freshly recorded narration session and make its contract active.
112
+ * `file` / `audio` are paths relative to the notes dir.
113
+ */
114
+ export function addSession(outputDir, entry) {
115
+ const index = readNotesIndex(outputDir);
116
+ const session = {
117
+ file: entry.file,
118
+ contract: entry.contract,
119
+ ts: entry.ts,
120
+ processed: false,
121
+ ...(entry.audio ? { audio: entry.audio } : {}),
122
+ };
123
+ index.sessions.push(session);
124
+ index.active_contract = entry.contract;
125
+ trackContract(index, entry.contract);
126
+ writeNotesIndex(outputDir, index);
127
+ return session;
128
+ }
129
+ /** The most recent session Diane hasn't ingested yet, with its transcript. */
130
+ export function latestUnprocessedSession(outputDir) {
131
+ const index = readNotesIndex(outputDir);
132
+ for (let i = index.sessions.length - 1; i >= 0; i--) {
133
+ const s = index.sessions[i];
134
+ if (!s.processed) {
135
+ const text = readText(path.join(notesDir(outputDir), s.file)) ?? '';
136
+ return { ...s, text };
137
+ }
138
+ }
139
+ return null;
140
+ }
141
+ export function markSessionProcessed(outputDir, file) {
142
+ const index = readNotesIndex(outputDir);
143
+ const session = index.sessions.find((s) => s.file === file);
144
+ if (!session)
145
+ throw new Error(`No session with file ${file}`);
146
+ session.processed = true;
147
+ writeNotesIndex(outputDir, index);
148
+ }
149
+ /**
150
+ * Write a transcript into `sessions/<ts>.md` and register it. Returns the
151
+ * session's relative file path. Used by the dashboard record route (after
152
+ * transcription) and by `hex note session add` (for testing without audio).
153
+ */
154
+ export function createSession(outputDir, opts) {
155
+ const rel = path.join('sessions', `${opts.ts}.md`);
156
+ const header = `# Narration — ${opts.contract} — ${opts.ts}\n\n`;
157
+ writeTextAtomic(path.join(notesDir(outputDir), rel), header + opts.transcript.trim() + '\n');
158
+ return addSession(outputDir, { file: rel, contract: opts.contract, ts: opts.ts, audio: opts.audio });
159
+ }
160
+ //# sourceMappingURL=notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes.js","sourceRoot":"","sources":["../../src/core/notes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** Thrown when no local Whisper engine is installed. The caller turns this into
2
+ * a setup hint and preserves the raw audio so no narration is lost. */
3
+ export declare class WhisperMissingError extends Error {
4
+ constructor();
5
+ }
6
+ export type WhisperEngine = {
7
+ kind: 'openai';
8
+ bin: string;
9
+ } | {
10
+ kind: 'faster';
11
+ bin: string;
12
+ } | {
13
+ kind: 'cpp';
14
+ bin: string;
15
+ model: string;
16
+ };
17
+ /** Find an installed engine, or null. */
18
+ export declare function detectWhisper(): WhisperEngine | null;
19
+ /**
20
+ * Transcribe `audioPath` to plain text. Throws WhisperMissingError when no
21
+ * engine is installed; the caller keeps the raw audio and surfaces the hint.
22
+ */
23
+ export declare function transcribe(audioPath: string): string;
24
+ //# sourceMappingURL=whisper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisper.d.ts","sourceRoot":"","sources":["../../src/core/whisper.ts"],"names":[],"mappings":"AAmBA;wEACwE;AACxE,qBAAa,mBAAoB,SAAQ,KAAK;;CAU7C;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAsBhD,yCAAyC;AACzC,wBAAgB,aAAa,IAAI,aAAa,GAAG,IAAI,CAUpD;AA0BD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAoCpD"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Local speech-to-text for Diane. Records stay on the machine: we shell out to
3
+ * a locally-installed Whisper engine, never a cloud API. Audit confidentiality
4
+ * is the whole point of keeping this on-device.
5
+ *
6
+ * Engines, in detection order (all auto-download their model on first run):
7
+ * 1. openai-whisper (`whisper` CLI, `pip install openai-whisper`)
8
+ * 2. faster-whisper (python module, `pip install faster-whisper`)
9
+ * 3. whisper.cpp (`whisper-cli`/`whisper-cpp`, needs HEX_WHISPER_MODEL=<model.bin>)
10
+ *
11
+ * Like src/core/notes.ts this stays node-builtins-only (child_process / fs /
12
+ * path / os) so the dashboard's record route can import it across the
13
+ * src/ <-> dashboard/ boundary without bundling CLI-only deps.
14
+ */
15
+ import { execFileSync } from 'node:child_process';
16
+ import fs from 'node:fs';
17
+ import os from 'node:os';
18
+ import path from 'node:path';
19
+ /** Thrown when no local Whisper engine is installed. The caller turns this into
20
+ * a setup hint and preserves the raw audio so no narration is lost. */
21
+ export class WhisperMissingError extends Error {
22
+ constructor() {
23
+ super('No local Whisper engine found. Install one (audio stays on your machine):\n' +
24
+ ' • pip install openai-whisper (provides the `whisper` command)\n' +
25
+ ' • pip install faster-whisper (lighter, faster on CPU)\n' +
26
+ ' • whisper.cpp + HEX_WHISPER_MODEL=/path/to/ggml-base.en.bin');
27
+ this.name = 'WhisperMissingError';
28
+ }
29
+ }
30
+ const MODEL = process.env.HEX_WHISPER_MODEL_NAME || 'base.en';
31
+ function commandExists(bin) {
32
+ try {
33
+ execFileSync('sh', ['-c', `command -v ${bin}`], { stdio: 'ignore' });
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ function pythonHasFasterWhisper(bin) {
41
+ try {
42
+ execFileSync(bin, ['-c', 'import faster_whisper'], { stdio: 'ignore' });
43
+ return true;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ /** Find an installed engine, or null. */
50
+ export function detectWhisper() {
51
+ if (commandExists('whisper'))
52
+ return { kind: 'openai', bin: 'whisper' };
53
+ for (const py of ['python3', 'python']) {
54
+ if (commandExists(py) && pythonHasFasterWhisper(py))
55
+ return { kind: 'faster', bin: py };
56
+ }
57
+ const cppModel = process.env.HEX_WHISPER_MODEL;
58
+ for (const bin of ['whisper-cli', 'whisper-cpp']) {
59
+ if (cppModel && commandExists(bin))
60
+ return { kind: 'cpp', bin, model: cppModel };
61
+ }
62
+ return null;
63
+ }
64
+ function ensureFfmpeg() {
65
+ if (!commandExists('ffmpeg')) {
66
+ throw new Error('ffmpeg is required to convert recordings for transcription, but was not found.');
67
+ }
68
+ }
69
+ /** Convert any recording to 16 kHz mono WAV (what every engine wants). */
70
+ function toWav(audioPath) {
71
+ ensureFfmpeg();
72
+ const wav = path.join(os.tmpdir(), `hex-narration-${path.basename(audioPath)}.wav`);
73
+ execFileSync('ffmpeg', ['-y', '-i', audioPath, '-ar', '16000', '-ac', '1', '-f', 'wav', wav], {
74
+ stdio: 'ignore',
75
+ });
76
+ return wav;
77
+ }
78
+ const FASTER_SCRIPT = `
79
+ import sys
80
+ from faster_whisper import WhisperModel
81
+ model = WhisperModel(sys.argv[2], device="cpu", compute_type="int8")
82
+ segments, _ = model.transcribe(sys.argv[1], language="en")
83
+ sys.stdout.write(" ".join(s.text.strip() for s in segments).strip())
84
+ `;
85
+ /**
86
+ * Transcribe `audioPath` to plain text. Throws WhisperMissingError when no
87
+ * engine is installed; the caller keeps the raw audio and surfaces the hint.
88
+ */
89
+ export function transcribe(audioPath) {
90
+ const engine = detectWhisper();
91
+ if (!engine)
92
+ throw new WhisperMissingError();
93
+ const wav = toWav(audioPath);
94
+ try {
95
+ if (engine.kind === 'openai') {
96
+ const outDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hex-whisper-'));
97
+ execFileSync(engine.bin, [wav, '--model', MODEL, '--language', 'en', '--output_format', 'txt', '--output_dir', outDir, '--task', 'transcribe'], { stdio: 'ignore' });
98
+ const txt = path.join(outDir, path.basename(wav).replace(/\.wav$/, '') + '.txt');
99
+ return (fs.readFileSync(txt, 'utf-8')).trim();
100
+ }
101
+ if (engine.kind === 'faster') {
102
+ const fasterModel = process.env.HEX_WHISPER_MODEL_NAME || 'base';
103
+ return execFileSync(engine.bin, ['-c', FASTER_SCRIPT, wav, fasterModel], {
104
+ encoding: 'utf-8',
105
+ maxBuffer: 64 * 1024 * 1024,
106
+ }).trim();
107
+ }
108
+ // whisper.cpp
109
+ const outBase = wav.replace(/\.wav$/, '');
110
+ execFileSync(engine.bin, ['-m', engine.model, '-f', wav, '-otxt', '-of', outBase, '-l', 'en'], {
111
+ stdio: 'ignore',
112
+ });
113
+ return fs.readFileSync(outBase + '.txt', 'utf-8').trim();
114
+ }
115
+ finally {
116
+ try {
117
+ fs.unlinkSync(wav);
118
+ }
119
+ catch {
120
+ /* best-effort cleanup */
121
+ }
122
+ }
123
+ }
124
+ //# sourceMappingURL=whisper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisper.js","sourceRoot":"","sources":["../../src/core/whisper.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from 'node:fs';
2
3
  import { Command } from 'commander';
3
4
  import { initCommand } from './commands/init.js';
4
5
  import { statsCommand } from './commands/stats.js';
@@ -18,11 +19,15 @@ import { doctorCommand } from './commands/doctor.js';
18
19
  import { aiStatusCommand } from './commands/ai-status.js';
19
20
  import { updateCommand } from './commands/update.js';
20
21
  import { issueCommand } from './commands/issue.js';
22
+ // Single source of truth for the version: package.json (always shipped at the
23
+ // package root, one dir up from dist/index.js). Avoids drift between the npm
24
+ // version and what `hex --version` reports.
25
+ const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
21
26
  const program = new Command();
22
27
  program
23
28
  .name('hex')
24
29
  .description('CLI toolkit for Solidity smart contract auditors')
25
- .version('0.5.1');
30
+ .version(pkg.version);
26
31
  program.addCommand(initCommand);
27
32
  program.addCommand(statsCommand);
28
33
  program.addCommand(depsCommand);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,8EAA8E;AAC9E,6EAA6E;AAC7E,4CAA4C;AAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC3C,CAAC;AAEzB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}