hub-proposal-rubric.mjs
63 lines 2.1 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 2 days ago
1 /**
2 * Load proposal evaluation rubric: data_dir/hub_proposal_rubric.json overrides hub/proposal-rubric-default.json.
3 */
4
5 import fs from 'fs';
6 import path from 'path';
7 import { fileURLToPath } from 'url';
8
9 // Netlify gateway bundle: import.meta.url may be missing at load time — never throw here.
10 function libDirname() {
11 try {
12 const u = typeof import.meta !== 'undefined' ? import.meta.url : '';
13 if (u) return path.dirname(fileURLToPath(u));
14 } catch (_) {}
15 return path.join(process.cwd(), 'lib');
16 }
17
18 const __dirname = libDirname();
19 const PACKAGED_DEFAULT = path.join(__dirname, '..', 'hub', 'proposal-rubric-default.json');
20
21 /**
22 * @returns {{ items: { id: string, label: string }[] }}
23 */
24 export function loadProposalRubric(dataDir) {
25 const overridePath = path.join(dataDir, 'hub_proposal_rubric.json');
26 let raw;
27 if (fs.existsSync(overridePath)) {
28 try {
29 raw = JSON.parse(fs.readFileSync(overridePath, 'utf8'));
30 } catch {
31 raw = null;
32 }
33 }
34 if (!raw || !Array.isArray(raw.items)) {
35 try {
36 raw = JSON.parse(fs.readFileSync(PACKAGED_DEFAULT, 'utf8'));
37 } catch {
38 raw = { items: [] };
39 }
40 }
41 const items = (raw.items || [])
42 .map((x) => ({
43 id: typeof x.id === 'string' ? x.id.trim().slice(0, 64) : '',
44 label: typeof x.label === 'string' ? x.label.trim().slice(0, 500) : '',
45 }))
46 .filter((x) => x.id && x.label);
47 return { items: items.length ? items : fallbackItems() };
48 }
49
50 /**
51 * Used when override + packaged default file are unreadable (e.g. Netlify bundles the gateway
52 * without `hub/proposal-rubric-default.json` next to the resolved `__dirname`). Keep in sync
53 * with `hub/proposal-rubric-default.json`.
54 */
55 function fallbackItems() {
56 return [
57 { id: 'accurate', label: 'Content appears accurate and appropriate for this vault' },
58 { id: 'no_secrets', label: 'No obvious secrets, API keys, or credentials in the body' },
59 { id: 'matches_intent', label: 'Change matches the stated intent (if any)' },
60 { id: 'pii', label: 'No unnecessary personal data (PII) unless the note is meant to store it' },
61 { id: 'tone', label: 'Tone and structure fit the rest of the vault' },
62 ];
63 }
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 2 days ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 3 days ago