instar 1.3.349 → 1.3.351

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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * PrincipalGuard — cross-principal attribution detector (EXO 3.0 / "Know Your
3
+ * Principal" standard, Phase 1 brain).
4
+ *
5
+ * The "Caroline" incident (2026-06-05, topic 19437): an autonomous session
6
+ * silently adopted a real OTHER principal as its operator and credited the
7
+ * actual operator's decisions to her across three docs — and no gate watched,
8
+ * because the contamination was in the agent's OWN output, not an inbound
9
+ * message. This module is the pure-logic detector for that failure: given a
10
+ * piece of agent-authored text, it finds operator-ROLE-decision attributions
11
+ * ("X approved", "locked with X", "mandate (X)", "X dropped a token") and
12
+ * flags any whose attributed principal is NOT the topic's bound operator and
13
+ * does NOT resolve to a known user.
14
+ *
15
+ * Pure + deterministic so it is unit-testable in isolation; it performs no I/O
16
+ * and is not wired into the live request path here (that is a later increment).
17
+ * The constitution standard it enforces: "Know Your Principal — An Unverified
18
+ * Identity Is a Guess" (docs/STANDARDS-REGISTRY.md). Spec:
19
+ * docs/specs/OPERATOR-IDENTITY-BINDING-SPEC.md.
20
+ */
21
+ /** A verified operator, established ONLY from an authenticated channel — never
22
+ * from a name read in content (that is the whole point). */
23
+ export interface VerifiedOperator {
24
+ /** The platform-verified sender id (e.g. Telegram uid). */
25
+ uid: string;
26
+ /** Display name(s) the operator is known by, lowercased for matching. */
27
+ names: string[];
28
+ }
29
+ /**
30
+ * Establish a topic's operator from the AUTHENTICATED sender — never from a
31
+ * content name. The uid is the authority; names are only for matching the
32
+ * agent's prose against the verified principal. A blank uid yields no operator
33
+ * (an unbound topic), which the guard treats as "everything is unverified".
34
+ */
35
+ export declare function establishOperator(authenticatedUid: string, displayName?: string): VerifiedOperator | null;
36
+ /** The kind of operator-role decision an attribution carries — drives warn vs block. */
37
+ export type AttributionKind = 'approval' | 'mandate' | 'credential' | 'lock' | 'acting-for';
38
+ export interface Attribution {
39
+ /** The principal name the decision was attributed to (lowercased). */
40
+ principal: string;
41
+ kind: AttributionKind;
42
+ /** The matched snippet, for the audit trail. */
43
+ snippet: string;
44
+ }
45
+ /** Find every operator-role-decision attribution in agent-authored text. */
46
+ export declare function detectAttributions(text: string): Attribution[];
47
+ export type Verdict = 'ok' | 'warn' | 'block';
48
+ export interface PrincipalFinding {
49
+ attribution: Attribution;
50
+ verdict: Verdict;
51
+ reason: string;
52
+ }
53
+ /**
54
+ * Evaluate a piece of agent-authored text against the topic's verified
55
+ * operator and the known-user registry. An attribution to the bound operator
56
+ * (or any known user) is fine; an attribution to anyone else is the Caroline
57
+ * failure — warn for prose, block for authority/credential decisions.
58
+ *
59
+ * `knownUserNames` are lowercased display names from UserManager (the
60
+ * authoritative registry). Resolution against it is what the "Know Your
61
+ * Principal" standard requires before any principal is accepted.
62
+ */
63
+ export declare function evaluatePrincipalCoherence(text: string, operator: VerifiedOperator | null, knownUserNames?: string[]): PrincipalFinding[];
64
+ //# sourceMappingURL=PrincipalGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrincipalGuard.d.ts","sourceRoot":"","sources":["../../src/core/PrincipalGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;6DAC6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAKzG;AAED,wFAAwF;AACxF,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,SAAS,GACT,YAAY,GACZ,MAAM,GACN,YAAY,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,eAAe,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AA0CD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAgB9D;AAED,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,gBAAgB,GAAG,IAAI,EACjC,cAAc,GAAE,MAAM,EAAO,GAC5B,gBAAgB,EAAE,CAqBpB"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PrincipalGuard — cross-principal attribution detector (EXO 3.0 / "Know Your
3
+ * Principal" standard, Phase 1 brain).
4
+ *
5
+ * The "Caroline" incident (2026-06-05, topic 19437): an autonomous session
6
+ * silently adopted a real OTHER principal as its operator and credited the
7
+ * actual operator's decisions to her across three docs — and no gate watched,
8
+ * because the contamination was in the agent's OWN output, not an inbound
9
+ * message. This module is the pure-logic detector for that failure: given a
10
+ * piece of agent-authored text, it finds operator-ROLE-decision attributions
11
+ * ("X approved", "locked with X", "mandate (X)", "X dropped a token") and
12
+ * flags any whose attributed principal is NOT the topic's bound operator and
13
+ * does NOT resolve to a known user.
14
+ *
15
+ * Pure + deterministic so it is unit-testable in isolation; it performs no I/O
16
+ * and is not wired into the live request path here (that is a later increment).
17
+ * The constitution standard it enforces: "Know Your Principal — An Unverified
18
+ * Identity Is a Guess" (docs/STANDARDS-REGISTRY.md). Spec:
19
+ * docs/specs/OPERATOR-IDENTITY-BINDING-SPEC.md.
20
+ */
21
+ /**
22
+ * Establish a topic's operator from the AUTHENTICATED sender — never from a
23
+ * content name. The uid is the authority; names are only for matching the
24
+ * agent's prose against the verified principal. A blank uid yields no operator
25
+ * (an unbound topic), which the guard treats as "everything is unverified".
26
+ */
27
+ export function establishOperator(authenticatedUid, displayName) {
28
+ const uid = String(authenticatedUid ?? '').trim();
29
+ if (!uid)
30
+ return null;
31
+ const names = (displayName ?? '').trim() ? [displayName.trim().toLowerCase()] : [];
32
+ return { uid, names };
33
+ }
34
+ // ── Detection patterns ───────────────────────────────────────────────
35
+ // Each captures a person-like principal NAME in group 1. Kept conservative:
36
+ // a name is 1-3 capitalized-ish words (so "the team" / "prod" don't match).
37
+ // NAME requires a real capital first letter (case-SENSITIVE — no `i` flag — so
38
+ // "have"/"production" can never be captured as a principal). Only the keyword
39
+ // LEADS are made case-flexible ([Mm]andate, [Ll]ock…) so a sentence-initial
40
+ // "Mandate" matches as well as a mid-sentence "mandate".
41
+ const NAME = String.raw `([A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+){0,2})`;
42
+ // Bounded gap that lets a date/short clause sit between a keyword and the name
43
+ // ("Locked 2026-06-04 with Caroline") without swallowing a sentence.
44
+ const GAP = String.raw `[^.\n]{0,40}?`;
45
+ const PATTERNS = [
46
+ { re: new RegExp(String.raw `\b[Mm]andate\s*\(\s*${NAME}\s*\)`, 'g'), kind: 'mandate' },
47
+ { re: new RegExp(String.raw `\b${NAME}\s+[Aa]uthoriz(?:ed|es)\b`, 'g'), kind: 'mandate' },
48
+ { re: new RegExp(String.raw `\b${NAME}\s+[Aa]pprov(?:ed|es)\b`, 'g'), kind: 'approval' },
49
+ { re: new RegExp(String.raw `\b(?:[Bb]lessed|[Ss]igned[- ]off)\s+by\s+${NAME}`, 'g'), kind: 'approval' },
50
+ { re: new RegExp(String.raw `\b[Ll]ock(?:ed)?\b${GAP}\b(?:with|by)\s+${NAME}`, 'g'), kind: 'lock' },
51
+ { re: new RegExp(String.raw `\b[Ss]tanding requirement from\s+${NAME}`, 'g'), kind: 'lock' },
52
+ { re: new RegExp(String.raw `\b${NAME}\s+(?:dropped|drop)\s+(?:a|the)\s+(?:token|credential|secret|key)`, 'g'), kind: 'credential' },
53
+ { re: new RegExp(String.raw `\b${NAME}['’]s\s+(?:credential|token|git\s+cred)`, 'g'), kind: 'credential' },
54
+ { re: new RegExp(String.raw `\b[Oo]n\s+behalf\s+of\s+${NAME}`, 'g'), kind: 'acting-for' },
55
+ { re: new RegExp(String.raw `\b[Oo]n\s+${NAME}['’]s\s+(?:say-so|behalf|authority)`, 'g'), kind: 'acting-for' },
56
+ ];
57
+ // Words that look capitalized but are never principals (sentence-start nouns,
58
+ // product/role terms). Keeps the detector from flagging "Production approved".
59
+ const NON_PRINCIPALS = new Set([
60
+ 'the', 'a', 'an', 'prod', 'production', 'ci', 'team', 'board', 'ops', 'staging',
61
+ 'github', 'telegram', 'slack', 'dawn', 'echo', 'i', 'we', 'you', 'they', 'it',
62
+ 'have', 'has', 'this', 'that', 'every', 'all',
63
+ ]);
64
+ function isPersonLike(name) {
65
+ const firstWord = name.split(/\s+/)[0];
66
+ // The `i` flag lets [A-Z] match lowercase too, so require an actual capital
67
+ // first letter here — a real person name is capitalized; "production" is not.
68
+ const startsCapital = /^[A-Z]/.test(firstWord);
69
+ return startsCapital && !NON_PRINCIPALS.has(firstWord.toLowerCase());
70
+ }
71
+ /** Find every operator-role-decision attribution in agent-authored text. */
72
+ export function detectAttributions(text) {
73
+ const out = [];
74
+ const seen = new Set();
75
+ for (const { re, kind } of PATTERNS) {
76
+ re.lastIndex = 0;
77
+ let m;
78
+ while ((m = re.exec(text)) !== null) {
79
+ const principal = (m[1] ?? '').trim();
80
+ if (!principal || !isPersonLike(principal))
81
+ continue;
82
+ const key = `${kind}:${principal.toLowerCase()}:${m.index}`;
83
+ if (seen.has(key))
84
+ continue;
85
+ seen.add(key);
86
+ out.push({ principal: principal.toLowerCase(), kind, snippet: m[0] });
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ /** Credential/authority-bearing kinds BLOCK when misattributed; the rest WARN. */
92
+ const BLOCK_KINDS = new Set(['mandate', 'credential']);
93
+ /**
94
+ * Evaluate a piece of agent-authored text against the topic's verified
95
+ * operator and the known-user registry. An attribution to the bound operator
96
+ * (or any known user) is fine; an attribution to anyone else is the Caroline
97
+ * failure — warn for prose, block for authority/credential decisions.
98
+ *
99
+ * `knownUserNames` are lowercased display names from UserManager (the
100
+ * authoritative registry). Resolution against it is what the "Know Your
101
+ * Principal" standard requires before any principal is accepted.
102
+ */
103
+ export function evaluatePrincipalCoherence(text, operator, knownUserNames = []) {
104
+ const known = new Set([
105
+ ...(operator?.names ?? []),
106
+ ...knownUserNames.map((n) => n.trim().toLowerCase()).filter(Boolean),
107
+ ]);
108
+ const findings = [];
109
+ for (const attribution of detectAttributions(text)) {
110
+ if (known.has(attribution.principal))
111
+ continue; // resolves to a verified principal — fine
112
+ const verdict = BLOCK_KINDS.has(attribution.kind) ? 'block' : 'warn';
113
+ findings.push({
114
+ attribution,
115
+ verdict,
116
+ reason: `Operator-role ${attribution.kind} attributed to "${attribution.principal}", who is ` +
117
+ (operator
118
+ ? `not this topic's bound operator and does not resolve to a known user`
119
+ : `unverifiable — this topic has no bound operator`) +
120
+ `. Know Your Principal: an unrecognized party in a decision role is a question to resolve, not a fact to accept.`,
121
+ });
122
+ }
123
+ return findings;
124
+ }
125
+ //# sourceMappingURL=PrincipalGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrincipalGuard.js","sourceRoot":"","sources":["../../src/core/PrincipalGuard.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.349",
3
+ "version": "1.3.351",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-06T06:49:15.721Z",
5
- "instarVersion": "1.3.349",
4
+ "generatedAt": "2026-06-06T06:55:18.419Z",
5
+ "instarVersion": "1.3.351",
6
6
  "entryCount": 199,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -11,7 +11,7 @@
11
11
  "domain": "identity",
12
12
  "sourcePath": "src/core/PostUpdateMigrator.ts",
13
13
  "installedPath": ".instar/hooks/instar/session-start.sh",
14
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
14
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
15
15
  "since": "2025-01-01"
16
16
  },
17
17
  "hook:dangerous-command-guard": {
@@ -20,7 +20,7 @@
20
20
  "domain": "safety",
21
21
  "sourcePath": "src/core/PostUpdateMigrator.ts",
22
22
  "installedPath": ".instar/hooks/instar/dangerous-command-guard.sh",
23
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
23
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
24
24
  "since": "2025-01-01"
25
25
  },
26
26
  "hook:grounding-before-messaging": {
@@ -29,7 +29,7 @@
29
29
  "domain": "safety",
30
30
  "sourcePath": "src/core/PostUpdateMigrator.ts",
31
31
  "installedPath": ".instar/hooks/instar/grounding-before-messaging.sh",
32
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
32
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
33
33
  "since": "2025-01-01"
34
34
  },
35
35
  "hook:compaction-recovery": {
@@ -38,7 +38,7 @@
38
38
  "domain": "identity",
39
39
  "sourcePath": "src/core/PostUpdateMigrator.ts",
40
40
  "installedPath": ".instar/hooks/instar/compaction-recovery.sh",
41
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
41
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
42
42
  "since": "2025-01-01"
43
43
  },
44
44
  "hook:external-operation-gate": {
@@ -47,7 +47,7 @@
47
47
  "domain": "safety",
48
48
  "sourcePath": "src/core/PostUpdateMigrator.ts",
49
49
  "installedPath": ".instar/hooks/instar/external-operation-gate.js",
50
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
50
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
51
51
  "since": "2025-01-01"
52
52
  },
53
53
  "hook:deferral-detector": {
@@ -56,7 +56,7 @@
56
56
  "domain": "safety",
57
57
  "sourcePath": "src/core/PostUpdateMigrator.ts",
58
58
  "installedPath": ".instar/hooks/instar/deferral-detector.js",
59
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
59
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
60
60
  "since": "2025-01-01"
61
61
  },
62
62
  "hook:self-stop-guard": {
@@ -65,7 +65,7 @@
65
65
  "domain": "coherence",
66
66
  "sourcePath": "src/core/PostUpdateMigrator.ts",
67
67
  "installedPath": ".instar/hooks/instar/self-stop-guard.js",
68
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
68
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
69
69
  "since": "2025-01-01"
70
70
  },
71
71
  "hook:post-action-reflection": {
@@ -74,7 +74,7 @@
74
74
  "domain": "evolution",
75
75
  "sourcePath": "src/core/PostUpdateMigrator.ts",
76
76
  "installedPath": ".instar/hooks/instar/post-action-reflection.js",
77
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
77
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
78
78
  "since": "2025-01-01"
79
79
  },
80
80
  "hook:external-communication-guard": {
@@ -83,7 +83,7 @@
83
83
  "domain": "safety",
84
84
  "sourcePath": "src/core/PostUpdateMigrator.ts",
85
85
  "installedPath": ".instar/hooks/instar/external-communication-guard.js",
86
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
86
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
87
87
  "since": "2025-01-01"
88
88
  },
89
89
  "hook:scope-coherence-collector": {
@@ -92,7 +92,7 @@
92
92
  "domain": "coherence",
93
93
  "sourcePath": "src/core/PostUpdateMigrator.ts",
94
94
  "installedPath": ".instar/hooks/instar/scope-coherence-collector.js",
95
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
95
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
96
96
  "since": "2025-01-01"
97
97
  },
98
98
  "hook:scope-coherence-checkpoint": {
@@ -101,7 +101,7 @@
101
101
  "domain": "coherence",
102
102
  "sourcePath": "src/core/PostUpdateMigrator.ts",
103
103
  "installedPath": ".instar/hooks/instar/scope-coherence-checkpoint.js",
104
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
104
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
105
105
  "since": "2025-01-01"
106
106
  },
107
107
  "hook:free-text-guard": {
@@ -110,7 +110,7 @@
110
110
  "domain": "safety",
111
111
  "sourcePath": "src/core/PostUpdateMigrator.ts",
112
112
  "installedPath": ".instar/hooks/instar/free-text-guard.sh",
113
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
113
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
114
114
  "since": "2025-01-01"
115
115
  },
116
116
  "hook:claim-intercept": {
@@ -119,7 +119,7 @@
119
119
  "domain": "coherence",
120
120
  "sourcePath": "src/core/PostUpdateMigrator.ts",
121
121
  "installedPath": ".instar/hooks/instar/claim-intercept.js",
122
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
122
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
123
123
  "since": "2025-01-01"
124
124
  },
125
125
  "hook:claim-intercept-response": {
@@ -128,7 +128,7 @@
128
128
  "domain": "coherence",
129
129
  "sourcePath": "src/core/PostUpdateMigrator.ts",
130
130
  "installedPath": ".instar/hooks/instar/claim-intercept-response.js",
131
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
131
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
132
132
  "since": "2025-01-01"
133
133
  },
134
134
  "hook:stop-gate-router": {
@@ -137,7 +137,7 @@
137
137
  "domain": "safety",
138
138
  "sourcePath": "src/core/PostUpdateMigrator.ts",
139
139
  "installedPath": ".instar/hooks/instar/stop-gate-router.js",
140
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
140
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
141
141
  "since": "2025-01-01"
142
142
  },
143
143
  "hook:auto-approve-permissions": {
@@ -146,7 +146,7 @@
146
146
  "domain": "safety",
147
147
  "sourcePath": "src/core/PostUpdateMigrator.ts",
148
148
  "installedPath": ".instar/hooks/instar/auto-approve-permissions.js",
149
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
149
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
150
150
  "since": "2025-01-01"
151
151
  },
152
152
  "job:health-check": {
@@ -1538,7 +1538,7 @@
1538
1538
  "type": "subsystem",
1539
1539
  "domain": "updates",
1540
1540
  "sourcePath": "src/core/PostUpdateMigrator.ts",
1541
- "contentHash": "2562b5b7c37deb568e00eefebc9acc07571a5e5ccc251f6e424e7e63039ee297",
1541
+ "contentHash": "523899adda3f26a840f9559afd1b79fdc6088ebeaffe1e07d142fdb8133bc5b7",
1542
1542
  "since": "2025-01-01"
1543
1543
  },
1544
1544
  "subsystem:scheduler": {
@@ -0,0 +1,91 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Added `src/core/PrincipalGuard.ts` — the pure-logic brain of the "Know Your
9
+ Principal" cross-principal coherence guard (constitution standard ratified in
10
+ #898). It establishes a topic's operator only from the authenticated sender,
11
+ detects operator-role-decision attributions in agent-authored text ("X
12
+ approved", "Mandate (X)", "locked with X", "X dropped a token"), and flags any
13
+ credited to a principal who is neither the bound operator nor a known user —
14
+ blocking authority/credential misattributions, warning on prose. No runtime
15
+ consumers yet (the wiring is a later increment).
16
+
17
+ Fixes #866: `POST /projects/:id/advance` building→merged always failed
18
+ `GH_PR_VIEW_UNAVAILABLE` because `StageTransitionValidator` has no internal
19
+ default for `ghPrView`/`gitMergeBaseIsAncestor` and the route never injected
20
+ them — so no project item could ever reach `merged` through the live API.
21
+ The route now injects both as read-only helpers (`gh pr view` and
22
+ `merge-base --is-ancestor` via SafeGitExecutor.readSync) against the
23
+ project's target repo. A wiring-integrity test asserts the helper-absent
24
+ error can never recur.
25
+
26
+ macOS Spotlight (`mds_stores`) was a top constant CPU consumer on busy fleet
27
+ boxes because it re-indexed the Claude Code session transcripts on every turn —
28
+ ~18 GB of JSONL that grows with every message. Instar already excluded
29
+ `.worktrees/` and `node_modules/` from Spotlight; this extends the same
30
+ `.metadata_never_index` exclusion to the agent's Claude transcript directory
31
+ (`~/.claude/projects/<encoded-agent-home>`), the largest churning set.
32
+
33
+ New `ensureClaudeTranscriptSpotlightExclusion()` helper + a `PostUpdateMigrator`
34
+ backfill so existing agents get the relief on their next update.
35
+
36
+ ## What to Tell Your User
37
+
38
+ Nothing user-facing changes. This is foundation code (experimental) for the
39
+ security fix behind the Caroline identity-bleed incident — it does not alter any
40
+ current behavior.
41
+
42
+ If you drive a multi-spec initiative through the projects pipeline, its
43
+ items can now actually reach the "merged" stage — the system verifies the
44
+ work's pull request really merged (merge state, commit reachable on the
45
+ main branch, CI green) instead of always erroring out. Project status
46
+ finally tracks reality through the whole pipeline.
47
+
48
+ Nothing required — this is silent OS-level resource hygiene. If they've noticed
49
+ the Mac running hot, part of the cause was Spotlight endlessly re-indexing
50
+ session transcripts; this stops that going forward.
51
+
52
+ ## Summary of New Capabilities
53
+
54
+ - `PrincipalGuard` (experimental, no runtime consumers yet): `establishOperator`,
55
+ `detectAttributions`, `evaluatePrincipalCoherence`.
56
+
57
+ - `POST /projects/:id/advance` with `targetStage: "merged"` now works end to
58
+ end (was structurally impossible): it verifies the PR via `gh pr view` and
59
+ confirms the merge commit is reachable on `origin/main` before recording
60
+ the item as merged.
61
+
62
+ - `ensureClaudeTranscriptSpotlightExclusion()` — drops a `.metadata_never_index`
63
+ marker at the agent's Claude transcript dir so macOS Spotlight stops
64
+ re-indexing the constantly-appended JSONL session transcripts (~18GB churn).
65
+ - `PostUpdateMigrator` backfill — existing agents get the exclusion on their next
66
+ update; new agents get it once they have transcripts. Internal OS hygiene; no
67
+ agent-facing API or config surface.
68
+
69
+ ## Evidence
70
+
71
+ Net-new capability. Verified by 13 unit tests including the incident-replay
72
+ regression test (the three real Caroline doc lines all caught with the topic
73
+ bound to the operator; the same lines crediting the operator all pass) and a
74
+ clean `tsc --noEmit`.
75
+
76
+ - tests/integration/projects-api.test.ts: building→merged now returns
77
+ GH_PR_VIEW_FAILED (not UNAVAILABLE), deterministic regardless of whether
78
+ gh is installed/authed. Full projects-api (45) + StageTransitionValidator
79
+ (26) green; tsc + destructive lint clean.
80
+
81
+ Unit + migration tests (both sides of every boundary: marker dropped when
82
+ transcripts exist, correct encoding, graceful no-op for a new agent, idempotent;
83
+ migration backfills/skips/idempotent). 15/15 green. `tsc --noEmit` clean.
84
+ Mirrors the existing node_modules/worktree exclusion pattern.
85
+
86
+ ## Scope (honest)
87
+
88
+ This prevents FUTURE re-indexing. It does not instantly drop `mds_stores` —
89
+ Spotlight releases already-indexed content on its own schedule; forcing
90
+ immediate eviction needs a one-time `sudo mdutil -E ~/.claude/projects` the
91
+ operator runs. One of several resource-efficiency fixes (2026-06-06).
@@ -0,0 +1,39 @@
1
+ # Side-effects review — PrincipalGuard (Phase 1 brain)
2
+
3
+ ## What this change is
4
+ A new pure-logic module `src/core/PrincipalGuard.ts` (operator establishment +
5
+ cross-principal attribution detector + warn/block evaluator) and its unit test.
6
+ Implements the detector half of the just-ratified "Know Your Principal" standard
7
+ (the cross-principal coherence guard from OPERATOR-IDENTITY-BINDING-SPEC.md §2).
8
+
9
+ ## Blast radius
10
+ - **Runtime impact: none.** Nothing imports `PrincipalGuard` at boot or in any
11
+ route/job/sentinel yet. Adding the file cannot change live behavior. It is the
12
+ testable brain; wiring it into the topic-operator binding, session-start
13
+ injection, and the outbound/at-rest review path are explicit later increments.
14
+ - **No I/O, no network, no new config/route/migration surface.** Pure functions
15
+ over strings + a `VerifiedOperator` value object.
16
+ - **Establishment is uid-only by construction:** `establishOperator` takes the
17
+ authenticated sender uid; there is NO code path that accepts a name from
18
+ content as the operator (the Caroline failure mode is impossible by type).
19
+
20
+ ## Security review
21
+ - The detector is conservative: a name must be capitalized (case-sensitive,
22
+ not the `i` flag) and not in a non-principal stop-set, so "Production
23
+ approved" / "The Board approved" do not flag. False positives warn (prose) or
24
+ block (authority/credential) — they never silently pass a misattribution.
25
+ - No payload/secret handling; operates only on already-authored text.
26
+
27
+ ## Framework generality
28
+ Pure logic, no session-launch/inject/message-delivery surface — framework-agnostic.
29
+
30
+ ## Test coverage
31
+ 13 unit tests covering both sides of every boundary: uid-only establishment
32
+ (incl. blank → null), each detection shape, non-principal rejection,
33
+ bound-operator pass, known-user pass, unknown-principal flag with block-vs-warn
34
+ tiering, no-operator case, and the **incident-replay regression test** — the
35
+ three real Caroline doc lines all caught (block for mandate/credential), and the
36
+ same lines crediting the bound operator all pass. `tsc --noEmit` clean.
37
+
38
+ ## Rollback
39
+ Delete the module + test; zero runtime consequence (no consumers).
@@ -0,0 +1,45 @@
1
+ # Side-Effects Review - Spotlight resource hygiene (Claude transcript exclusion)
2
+
3
+ **Version / slug:** `spotlight-resource-hygiene`
4
+ **Date:** `2026-06-06`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `not required (Tier 1)`
7
+
8
+ ## Summary of the change
9
+
10
+ Extends Instar's existing macOS Spotlight exclusion (currently covers `.worktrees/` + `node_modules/`) to the agent's Claude Code transcript directory (`~/.claude/projects/<encoded-agent-home>`). The JSONL session transcripts grow on every turn and a busy fleet box accumulates ~18 GB of them — measured as the single largest `mds_stores` (Spotlight) CPU consumer (60-90% of a core, constantly), because Spotlight re-indexes each file on every append. Adds `ensureClaudeTranscriptSpotlightExclusion()` (reuses the generic marker-dropper) + a `PostUpdateMigrator` backfill.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `ensureClaudeTranscriptSpotlightExclusion(agentHome, claudeHome?)` (new, exported) — pure-ish: computes the encoded transcript dir, drops `.metadata_never_index` if the dir exists. Reuses `ensureWorktreeSpotlightExclusion` (the dir-agnostic dropper).
15
+ - `PostUpdateMigrator.migrateClaudeTranscriptSpotlightExclusion` (new, private) — runs the helper on every update, pushes an `upgraded`/`errors` entry.
16
+ - Wired into the migrate() sequence right after `migrateNodeModulesSpotlightExclusion`.
17
+
18
+ ## 1. Behavior change / gating
19
+
20
+ NONE that affects message flow, sessions, or any gate. The only effect is writing one empty marker file into the agent's Claude transcript dir, which tells macOS Spotlight to stop indexing that subtree. No runtime behavior of the agent changes; instar's own transcript reads (TokenLedger) are unaffected (Spotlight indexing is orthogonal to file reads).
21
+
22
+ ## 2. Over/under-signal
23
+
24
+ N/A — not a signal/gate. The only "decision" is whether the transcript dir exists (drop the marker) or not (skip). Both branches are covered.
25
+
26
+ ## 3. Blast radius
27
+
28
+ Filesystem only, additive: writes `~/.claude/projects/<encoded>/.metadata_never_index`. This reaches OUTSIDE the agent home (into `~/.claude`), which is deliberate and bounded: (a) instar already READS that exact directory (TokenLedger/CompactionSentinel), so it is not new territory; (b) the path is scoped to THIS agent's own transcript dir via the home-path encoding, never all of `~/.claude/projects`; (c) the write is a single empty marker, idempotent, reversible. No state, no migration of data, no config. On a non-macOS host the marker is inert.
29
+
30
+ ## 4. Failure modes
31
+
32
+ The underlying `ensureWorktreeSpotlightExclusion` swallows write errors (`@silent-fallback-ok`) and returns false — a failed marker write just means Spotlight keeps indexing (status quo), and can never block the migration or an update. `existsSync` guards the absent-dir case (brand-new agent, no sessions). The encoding is a pure string transform with no throw path.
33
+
34
+ ## 5. Migration parity
35
+
36
+ Covered: the `PostUpdateMigrator` backfill means existing agents get the marker on their next update (the fast release cadence drops it within minutes once transcripts exist). New agents get it on their first post-session update. No agent-installed config/hooks/skills/CLAUDE.md change — this is internal OS hygiene with no agent-facing surface (consistent with the precedent: the node_modules + worktree exclusions also have no CLAUDE.md template line, as they are not capabilities the agent surfaces to a user). No init-path call is needed because the transcript dir does not exist at init time (no sessions yet) — it would no-op; the migration is the correct single mechanism.
37
+
38
+ ## 6. Scope honesty (what this is NOT)
39
+
40
+ - This is fix 1 of 4 in the resource-efficiency initiative (Justin, 2026-06-06). It is the biggest single lever (the 18 GB transcript churn) but does NOT instantly drop `mds_stores`: the marker prevents FUTURE re-indexing; Spotlight releases already-indexed content on its own schedule, and forcing immediate eviction needs a one-time `sudo mdutil -E` the operator runs (instar cannot run sudo). The durable guarantee is that no agent keeps feeding the churn.
41
+ - `mediaanalysisd` (macOS media/photo analysis) is a separate high-CPU process NOT addressed here and likely not Instar-triggered.
42
+
43
+ ## 7. Causal autopsy
44
+
45
+ Origin: **latent** (not a prior-PR regression). The transcript-indexing cost has existed since Claude Code began writing JSONL transcripts; the recent node_modules/worktree exclusion PRs addressed the static trees but never extended to the constantly-churning transcript set, which grounding showed is the larger consumer. This PR closes that gap by reusing the same marker mechanism. No behavior was broken by a prior change; an existing cost was simply never excluded.
@@ -1,37 +0,0 @@
1
- # Upgrade Guide — vNEXT
2
-
3
- <!-- assembled-by: assemble-next-md -->
4
- <!-- bump: patch -->
5
-
6
- ## What Changed
7
-
8
- Fixes #866: `POST /projects/:id/advance` building→merged always failed
9
- `GH_PR_VIEW_UNAVAILABLE` because `StageTransitionValidator` has no internal
10
- default for `ghPrView`/`gitMergeBaseIsAncestor` and the route never injected
11
- them — so no project item could ever reach `merged` through the live API.
12
- The route now injects both as read-only helpers (`gh pr view` and
13
- `merge-base --is-ancestor` via SafeGitExecutor.readSync) against the
14
- project's target repo. A wiring-integrity test asserts the helper-absent
15
- error can never recur.
16
-
17
- ## What to Tell Your User
18
-
19
- If you drive a multi-spec initiative through the projects pipeline, its
20
- items can now actually reach the "merged" stage — the system verifies the
21
- work's pull request really merged (merge state, commit reachable on the
22
- main branch, CI green) instead of always erroring out. Project status
23
- finally tracks reality through the whole pipeline.
24
-
25
- ## Summary of New Capabilities
26
-
27
- - `POST /projects/:id/advance` with `targetStage: "merged"` now works end to
28
- end (was structurally impossible): it verifies the PR via `gh pr view` and
29
- confirms the merge commit is reachable on `origin/main` before recording
30
- the item as merged.
31
-
32
- ## Evidence
33
-
34
- - tests/integration/projects-api.test.ts: building→merged now returns
35
- GH_PR_VIEW_FAILED (not UNAVAILABLE), deterministic regardless of whether
36
- gh is installed/authed. Full projects-api (45) + StageTransitionValidator
37
- (26) green; tsc + destructive lint clean.