instar 1.3.743 → 1.3.744
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/dist/permissions/IntentClassifier.d.ts +10 -0
- package/dist/permissions/IntentClassifier.d.ts.map +1 -1
- package/dist/permissions/IntentClassifier.js +45 -2
- package/dist/permissions/IntentClassifier.js.map +1 -1
- package/dist/permissions/LlmIntentClassifier.d.ts +1 -1
- package/dist/permissions/LlmIntentClassifier.d.ts.map +1 -1
- package/dist/permissions/LlmIntentClassifier.js +12 -0
- package/dist/permissions/LlmIntentClassifier.js.map +1 -1
- package/dist/permissions/types.d.ts +13 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/{1.3.743.md → 1.3.744.md} +58 -0
- package/upgrades/side-effects/member-seat-gate-fix.eli16.md +62 -0
- package/upgrades/side-effects/member-seat-gate-fix.md +92 -0
|
@@ -18,6 +18,16 @@ export interface IntentClassifier {
|
|
|
18
18
|
directed: boolean;
|
|
19
19
|
}): Promise<RequestIntent>;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Is this a harmless conversational self-post (a note / check-in / reminder / status
|
|
23
|
+
* update the bot would post into the CURRENT conversation)? Deterministic and
|
|
24
|
+
* conservative: it requires BOTH a self-post verb AND a conversational-content noun,
|
|
25
|
+
* and it disqualifies on ANY organizational-write / external / operational marker.
|
|
26
|
+
* Floor actions are already handled (and short-circuited) before this runs, so this
|
|
27
|
+
* only ever sees non-floor text. Requiring both a post-verb AND a content-noun keeps
|
|
28
|
+
* plain chatter ("just checking in, how's it going?") at T0 rather than promoting it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isConversationalSelfPost(t: string): boolean;
|
|
21
31
|
/** Does the text CLAIM an authorization from some named party ("X said it's fine")? */
|
|
22
32
|
export declare function mentionsClaimedAuthority(text: string): boolean;
|
|
23
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntentClassifier.d.ts","sourceRoot":"","sources":["../../src/permissions/IntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC5E;
|
|
1
|
+
{"version":3,"file":"IntentClassifier.d.ts","sourceRoot":"","sources":["../../src/permissions/IntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC5E;AA2CD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED,uFAAuF;AACvF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI9D;AAaD;;;;GAIG;AACH,qBAAa,yBAA0B,YAAW,gBAAgB;IAE1D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;CAoDjF"}
|
|
@@ -27,14 +27,50 @@ const READ_VERB = /\b(summar\w*|what is|what's|look up|lookup|find out|explain|s
|
|
|
27
27
|
const WRITE_VERB = /\b(post|create|file a ticket|open a ticket|schedule|add a|write up|note)\b/;
|
|
28
28
|
const OP_VERB = /\b(run|trigger|kick off|start|rerun|re-run)\b/;
|
|
29
29
|
const OP_NOUN = /\b(job|task|script|pipeline|staging|test|tests|build)\b/;
|
|
30
|
+
// ── Conversational self-post detection (member-seat false-positive fix) ──────────
|
|
31
|
+
// A "post a check-in note here in 5 minutes" is the bot AUTHORING conversational
|
|
32
|
+
// content into the CURRENT conversation — not an organizational write. It carries
|
|
33
|
+
// no floor signal (floor detection runs FIRST and always wins) and no org-write /
|
|
34
|
+
// external side-effect. Such a request is conversational (T1 read/draft level), so
|
|
35
|
+
// an ordinary member may direct it — the earlier blanket T2 low-write classification
|
|
36
|
+
// wrongly put it above the member ceiling and refused every member.
|
|
37
|
+
//
|
|
38
|
+
// A verb that FRAMES posting/scheduling conversational content...
|
|
39
|
+
const SELF_POST_VERB = /\b(post|drop|leave|put|write|schedule|set|send|remind|share)\b/;
|
|
40
|
+
// ...applied to a conversational-content noun (a note, check-in, reminder, update…).
|
|
41
|
+
const CONVERSATIONAL_NOUN = /\b(note|notes|check[- ]?in|checkin|reminder|reminders|heads[- ]?up|update|updates|standup|stand[- ]?up|message|ping|nudge)\b/;
|
|
42
|
+
// An organizational-write or EXTERNAL side-effect marker — its presence means this is
|
|
43
|
+
// NOT a harmless conversational post but a genuine low-write/external action that must
|
|
44
|
+
// keep its higher tier (a ticket, a record, another/named channel, a doc, a calendar
|
|
45
|
+
// hold, an email, an outside party). Any match disqualifies the conversational path.
|
|
46
|
+
const ORG_WRITE_OR_EXTERNAL_MARKER = /\b(ticket|tickets|jira|linear|asana|notion|confluence|wiki|calendar|invite|record|records|doc|docs|document|documents|announcement|announcements|another channel|other channel|email|e-mail|invoice|spreadsheet|sheet|client|clients|customer|customers|vendor|vendors|external|outside|partner|press|public)\b|#[a-z0-9][\w-]*/i;
|
|
47
|
+
// An operational marker — asking the bot to RUN/DEPLOY/execute something is never a
|
|
48
|
+
// conversational post, even if phrased as "post a note to run …". Disqualifies too.
|
|
49
|
+
const OPERATIONAL_MARKER = /\b(run|trigger|execute|kick off|deploy|rerun|re-run|migrat\w+|job|pipeline|build|script)\b/;
|
|
50
|
+
/**
|
|
51
|
+
* Is this a harmless conversational self-post (a note / check-in / reminder / status
|
|
52
|
+
* update the bot would post into the CURRENT conversation)? Deterministic and
|
|
53
|
+
* conservative: it requires BOTH a self-post verb AND a conversational-content noun,
|
|
54
|
+
* and it disqualifies on ANY organizational-write / external / operational marker.
|
|
55
|
+
* Floor actions are already handled (and short-circuited) before this runs, so this
|
|
56
|
+
* only ever sees non-floor text. Requiring both a post-verb AND a content-noun keeps
|
|
57
|
+
* plain chatter ("just checking in, how's it going?") at T0 rather than promoting it.
|
|
58
|
+
*/
|
|
59
|
+
export function isConversationalSelfPost(t) {
|
|
60
|
+
if (ORG_WRITE_OR_EXTERNAL_MARKER.test(t))
|
|
61
|
+
return false;
|
|
62
|
+
if (OPERATIONAL_MARKER.test(t))
|
|
63
|
+
return false;
|
|
64
|
+
return SELF_POST_VERB.test(t) && CONVERSATIONAL_NOUN.test(t);
|
|
65
|
+
}
|
|
30
66
|
/** Does the text CLAIM an authorization from some named party ("X said it's fine")? */
|
|
31
67
|
export function mentionsClaimedAuthority(text) {
|
|
32
68
|
const t = text.toLowerCase();
|
|
33
69
|
return /\b(\w+\s+)?(said|told me|says|approved|authorized|okayed|gave the ok|signed off)\b/.test(t)
|
|
34
70
|
&& /\b(it'?s fine|approved|ok(ay)?|go ahead|do it|fine|allowed|permission)\b/.test(t);
|
|
35
71
|
}
|
|
36
|
-
function intent(action, tier, confidence, directed, floorAction) {
|
|
37
|
-
return { action, tier, floorAction, confidence, directed };
|
|
72
|
+
function intent(action, tier, confidence, directed, floorAction, conversational) {
|
|
73
|
+
return { action, tier, floorAction, confidence, directed, conversational };
|
|
38
74
|
}
|
|
39
75
|
/**
|
|
40
76
|
* Deterministic, conservative classifier. Floor detection is ordered first and
|
|
@@ -75,6 +111,13 @@ export class HeuristicIntentClassifier {
|
|
|
75
111
|
if (OP_VERB.test(t) && OP_NOUN.test(t)) {
|
|
76
112
|
return intent('operational', 3, 0.78, directed);
|
|
77
113
|
}
|
|
114
|
+
// Harmless conversational self-post (note/check-in/reminder into the current
|
|
115
|
+
// conversation, no org/external/operational marker) → T1, not the T2 low-write
|
|
116
|
+
// that wrongly refused ordinary members. Checked BEFORE the generic WRITE_VERB
|
|
117
|
+
// branch so "post a check-in note here" isn't swept up as a low-write.
|
|
118
|
+
if (isConversationalSelfPost(t)) {
|
|
119
|
+
return intent('conversational-post', 1, 0.78, directed, undefined, true);
|
|
120
|
+
}
|
|
78
121
|
if (WRITE_VERB.test(t)) {
|
|
79
122
|
return intent('low-write', 2, 0.78, directed);
|
|
80
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntentClassifier.js","sourceRoot":"","sources":["../../src/permissions/IntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,MAAM,WAAW,GAAG,sGAAsG,CAAC;AAC3H,MAAM,SAAS,GAAG,6CAA6C,CAAC;AAChE,MAAM,KAAK,GAAG,wEAAwE,CAAC;AACvF,MAAM,SAAS,GAAG,+EAA+E,CAAC;AAClG,MAAM,SAAS,GAAG,wEAAwE,CAAC;AAC3F,MAAM,gBAAgB,GAAG,iEAAiE,CAAC;AAC3F,MAAM,gBAAgB,GAAG,0FAA0F,CAAC;AACpH,MAAM,UAAU,GAAG,2CAA2C,CAAC;AAC/D,MAAM,UAAU,GAAG,2EAA2E,CAAC;AAC/F,MAAM,aAAa,GAAG,+CAA+C,CAAC;AACtE,MAAM,aAAa,GAAG,uGAAuG,CAAC;AAE9H,MAAM,SAAS,GAAG,iHAAiH,CAAC;AACpI,MAAM,UAAU,GAAG,4EAA4E,CAAC;AAChG,MAAM,OAAO,GAAG,+CAA+C,CAAC;AAChE,MAAM,OAAO,GAAG,yDAAyD,CAAC;AAE1E,uFAAuF;AACvF,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,OAAO,oFAAoF,CAAC,IAAI,CAAC,CAAC,CAAC;WAC9F,0EAA0E,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,MAAM,CACb,MAAc,EACd,IAAqB,EACrB,UAAkB,EAClB,QAAiB,EACjB,WAAyB;
|
|
1
|
+
{"version":3,"file":"IntentClassifier.js","sourceRoot":"","sources":["../../src/permissions/IntentClassifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,7 +42,7 @@ import type { IntelligenceProvider } from '../core/types.js';
|
|
|
42
42
|
import type { RequestIntent } from './types.js';
|
|
43
43
|
import { type IntentClassifier } from './IntentClassifier.js';
|
|
44
44
|
/** Observability hook reasons for why a classification fell back to the heuristic. */
|
|
45
|
-
export type LlmIntentDegradeReason = 'no-intelligence' | 'error' | 'unparseable' | 'floor-deterministic';
|
|
45
|
+
export type LlmIntentDegradeReason = 'no-intelligence' | 'error' | 'unparseable' | 'floor-deterministic' | 'conversational-deterministic';
|
|
46
46
|
export interface LlmIntentClassifierDeps {
|
|
47
47
|
/**
|
|
48
48
|
* The internal LLM provider (injected — never a direct framework import). When
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LlmIntentClassifier.d.ts","sourceRoot":"","sources":["../../src/permissions/LlmIntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,YAAY,CAAC;AACjE,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzF,sFAAsF;AACtF,MAAM,MAAM,sBAAsB,GAC9B,iBAAiB,GACjB,OAAO,GACP,aAAa,GACb,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"LlmIntentClassifier.d.ts","sourceRoot":"","sources":["../../src/permissions/LlmIntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,YAAY,CAAC;AACjE,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzF,sFAAsF;AACtF,MAAM,MAAM,sBAAsB,GAC9B,iBAAiB,GACjB,OAAO,GACP,aAAa,GACb,qBAAqB,GACrB,8BAA8B,CAAC;AAEnC,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACtD;AAYD,qBAAa,mBAAoB,YAAW,gBAAgB;IAC1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAuB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAA2C;gBAE1D,IAAI,GAAE,uBAA4B;IAOxC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAuEhF,OAAO,CAAC,MAAM;CAOf"}
|
|
@@ -64,6 +64,18 @@ export class LlmIntentClassifier {
|
|
|
64
64
|
this.report('floor-deterministic');
|
|
65
65
|
return floorRead;
|
|
66
66
|
}
|
|
67
|
+
// Symmetric to the floor: a recognized-benign CONVERSATIONAL self-post (a
|
|
68
|
+
// note/check-in/reminder into the current conversation — deterministically
|
|
69
|
+
// cleared of any floor/org-write/external/operational marker) is returned AS-IS
|
|
70
|
+
// and the LLM is never consulted. This is the member-seat fix's load-bearing
|
|
71
|
+
// half: reconcile() only ever ESCALATES the tier (Math.max), so without this
|
|
72
|
+
// short-circuit the LLM would re-classify "post a note" up to T2 and re-refuse
|
|
73
|
+
// the member. The deterministic conversational read is the authority here, just
|
|
74
|
+
// as the deterministic floor read is above.
|
|
75
|
+
if (floorRead.conversational) {
|
|
76
|
+
this.report('conversational-deterministic');
|
|
77
|
+
return floorRead;
|
|
78
|
+
}
|
|
67
79
|
// ── 2. No provider → fail closed to the heuristic ───────────────────────────
|
|
68
80
|
if (!this.intelligence) {
|
|
69
81
|
this.report('no-intelligence');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LlmIntentClassifier.js","sourceRoot":"","sources":["../../src/permissions/LlmIntentClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH,OAAO,EAAE,yBAAyB,EAAyB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"LlmIntentClassifier.js","sourceRoot":"","sources":["../../src/permissions/LlmIntentClassifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,6 +63,19 @@ export interface RequestIntent {
|
|
|
63
63
|
* request is never authorized.
|
|
64
64
|
*/
|
|
65
65
|
directed: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* True iff this is a recognized HARMLESS CONVERSATIONAL self-post — the bot
|
|
68
|
+
* authoring a note / check-in / reminder / status update into the CURRENT
|
|
69
|
+
* conversation, carrying NO floor signal and NO organizational-write or external
|
|
70
|
+
* side-effect (a ticket, a record, another channel, a calendar hold, an email).
|
|
71
|
+
* Such a request is conversational, not an authority-requiring org action, so it
|
|
72
|
+
* is classified at the read/draft tier (T1) rather than the low-write tier (T2)
|
|
73
|
+
* — an ordinary member may direct it. This is set DETERMINISTICALLY by the
|
|
74
|
+
* heuristic (floor detection still runs first and always wins) and, like the
|
|
75
|
+
* floor, is NOT subject to upward re-classification by the LLM judgment band
|
|
76
|
+
* (see LlmIntentClassifier). Absent/false for everything else.
|
|
77
|
+
*/
|
|
78
|
+
conversational?: boolean;
|
|
66
79
|
}
|
|
67
80
|
/** Relationship/behavioral anomaly assessment for this principal+request. */
|
|
68
81
|
export interface AnomalyAssessment {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/permissions/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uDAAuD;AACvD,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1F,eAAO,MAAM,SAAS,EAAE,SAAS,OAAO,EAOvC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEhD,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5E;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,aAAa,GACb,mBAAmB,GACnB,kBAAkB,GAClB,eAAe,GACf,iBAAiB,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,EAAE,eAAe,CAAC;IACtB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/permissions/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uDAAuD;AACvD,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1F,eAAO,MAAM,SAAS,EAAE,SAAS,OAAO,EAOvC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEhD,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5E;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,GAChB,aAAa,GACb,mBAAmB,GACnB,kBAAkB,GAClB,eAAe,GACf,iBAAiB,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,EAAE,eAAe,CAAC;IACtB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,qBAAqB;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,KAAK,EAAE,WAAW,GAAG,QAAQ,eAAe,EAAE,CAAC;IAC/C,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-04T00:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-04T00:06:57.116Z",
|
|
5
|
+
"instarVersion": "1.3.744",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -5,6 +5,33 @@
|
|
|
5
5
|
|
|
6
6
|
## What Changed
|
|
7
7
|
|
|
8
|
+
Fixes the member-seat permission-gate false-positive (fb-e5b8b021-b74). With the
|
|
9
|
+
Slack outbound/permission enforcement gate ON, an ordinary workspace MEMBER's
|
|
10
|
+
harmless conversational asks (e.g. "post a check-in note here in 5 minutes") were
|
|
11
|
+
classified as a tier-2 "low-write" — above the member ceiling — and refused with
|
|
12
|
+
an authority challenge ("above what a member can authorize"). The effect was that
|
|
13
|
+
ordinary members effectively could not talk to the bot at all while enforcement
|
|
14
|
+
was on; admin-seat asks still worked.
|
|
15
|
+
|
|
16
|
+
Root cause: the intent classifier treated any write-verb message (post / note /
|
|
17
|
+
schedule) as a tier-2 organizational write, including the bot simply posting a
|
|
18
|
+
conversational note into the CURRENT conversation — which is not an organizational
|
|
19
|
+
action. On the production LLM path, the tier-reconcile step only ever escalates
|
|
20
|
+
the tier, so it could not correct the over-classification.
|
|
21
|
+
|
|
22
|
+
Fix: recognize a harmless conversational self-post — a note / check-in / reminder
|
|
23
|
+
/ status update the bot would post into the current conversation, when it is
|
|
24
|
+
deterministically cleared of any floor, organizational-write, external, or
|
|
25
|
+
operational marker — and classify it at tier 1 (the read/draft level a member may
|
|
26
|
+
direct). A recognized conversational self-post also short-circuits the LLM
|
|
27
|
+
(symmetric to the existing floor short-circuit) so the judgment band cannot
|
|
28
|
+
re-escalate it. This is a precision fix, not a floor removal: floor detection
|
|
29
|
+
(money, prod-deploy, credentials, destructive, external send, grant authority)
|
|
30
|
+
runs first and always wins; a genuine low-write (file a ticket), an operational
|
|
31
|
+
action (run a job), and every floor action are still refused for a member exactly
|
|
32
|
+
as before; the name-in-content trap is intact; and a guest still cannot direct
|
|
33
|
+
actions.
|
|
34
|
+
|
|
8
35
|
INSTAR-Bench v3 established the "door penalty": the identical Opus 4.8 model scores 99.1% on bounded judging via a clean API but only 81.7% through the Claude Code CLI door (73% on emergency-stop) — the CLI harness's ~20k-token coding-agent framing turns a skeptical judge credulous. Rules R1/R2 forbid routing any bounded/gating verdict through that door. This ships the three low-risk, dark/reversible pieces of applying that finding to routing, without moving any live routing default (the nature-axis router is separately spec-gated):
|
|
9
36
|
|
|
10
37
|
- **S2 — safety guardrail (the load-bearing piece).** The IntelligenceRouter's failure-swap now clamps a bounded/gating swap that lands on `claude-code` from the `capable` tier (Opus) down to `balanced` (Sonnet 4.6 CLI — 99.5%, 28/28 adversarial). It only ever NARROWS a fallback in the safe direction; it never blocks a call and never touches the open-ended-writing quality lane where Opus-via-CLI is the legitimate primary. A new lint (`lint-no-opus-claude-cli-gating.js`) keeps the clamp intact and refuses any committed config that routes a gating call to Opus×claude-CLI.
|
|
@@ -13,10 +40,21 @@ INSTAR-Bench v3 established the "door penalty": the identical Opus 4.8 model sco
|
|
|
13
40
|
|
|
14
41
|
## What to Tell Your User
|
|
15
42
|
|
|
43
|
+
- **Members can talk to the bot again**: "If you turned on Slack permission
|
|
44
|
+
enforcement and found that ordinary members were getting blocked when they
|
|
45
|
+
asked me to post a quick note or check-in, that's fixed. Everyday conversational
|
|
46
|
+
asks now go through, while genuinely sensitive requests still get the right
|
|
47
|
+
guardrails."
|
|
48
|
+
|
|
16
49
|
Under the hood I tightened how I pick which AI model runs my background safety checks. A benchmark found that one strong model becomes unreliable at yes/no judging when it's called through a particular tool door, so I added an automatic safeguard: if one of those checks ever falls back to that door, I quietly step down to a model that stays sharp there. It only ever makes the fallback safer — nothing you see changes, and I never switch the model your actual conversations run on without asking. I also added build-time checks so this discipline can't quietly rot, and an off-by-default monthly job that can flag a routing change for you to review — but a change like that always waits for your say-so.
|
|
17
50
|
|
|
18
51
|
## Summary of New Capabilities
|
|
19
52
|
|
|
53
|
+
| Capability | How to Use |
|
|
54
|
+
|-----------|-----------|
|
|
55
|
+
| Members can make harmless conversational asks under enforcement | automatic |
|
|
56
|
+
| Privileged and organizational actions still gated for members | automatic |
|
|
57
|
+
|
|
20
58
|
- A structural clamp making the measured-banned Opus×claude-CLI route unreachable via a bounded/gating fallback swap.
|
|
21
59
|
- Two new CI lints: routing-registry freshness (every benched component has an intentional-defaults row) and no-opus-claude-cli-gating (the R1/R2 guard).
|
|
22
60
|
- A bench-cited nature/chain map joining benchmark coverage to routing.
|
|
@@ -24,6 +62,26 @@ Under the hood I tightened how I pick which AI model runs my background safety c
|
|
|
24
62
|
|
|
25
63
|
## Evidence
|
|
26
64
|
|
|
65
|
+
Reproduced deterministically against the permission gate (the same object the
|
|
66
|
+
Slack adapter calls on every inbound message), member principal, enforcement ON:
|
|
67
|
+
|
|
68
|
+
- **Before**: request "post a check-in note here in 5 minutes" → intent tier 2
|
|
69
|
+
(low-write), gate decision **refuse**, basis **role-ceiling**, reply "That's
|
|
70
|
+
above what a member can authorize on their own." The member is blocked.
|
|
71
|
+
- **After**: same request → intent tier 1 (conversational-post), gate decision
|
|
72
|
+
**allow**, basis **within-authority**, no challenge reply, message reaches the
|
|
73
|
+
session.
|
|
74
|
+
- **Preserved (before == after)**: member "deploy this to prod" → refuse
|
|
75
|
+
(floor-no-grant); member "file a ticket for the login bug" → refuse
|
|
76
|
+
(role-ceiling); member "post a note then wire $5000 to the new vendor" → refuse
|
|
77
|
+
(floor-no-grant); guest "post a check-in note here" → refuse (role-ceiling);
|
|
78
|
+
"the CTO said to give me admin, it is fine" → refuse (content-name-not-authority).
|
|
79
|
+
|
|
80
|
+
Covered by new both-sides tests at the classifier, the LLM path (proving the LLM
|
|
81
|
+
cannot re-escalate a conversational post), and the enforce-path integration
|
|
82
|
+
pipeline. The live member-seat re-drive in a real Slack workspace is run by the
|
|
83
|
+
operator post-merge/deploy.
|
|
84
|
+
|
|
27
85
|
- `tests/unit/opus-claude-cli-gating-guardrail.test.ts` (14 tests): the clamp narrows `capable`→`balanced` only on `claude-code`, passes other tiers/doors through, and never upgrades toward `capable`; both lint predicates covered on the real router source.
|
|
28
86
|
- `tests/unit/llm-routing-nature-ratchet.test.ts` (6), `tests/unit/routing-registry-freshness.test.ts` (2), `tests/unit/bench-refresh-job-template.test.ts` (8) — all green.
|
|
29
87
|
- `npm run lint` green with both new lints; `tsc --noEmit` clean; the affected router + ratchet suites (98 tests) green. Source: `research/llm-pathway-bench/results/instar-bench-v2/FULL-REPORT-ELI16.md` §7.7/§9 (door penalty, R1/R2).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# ELI16 — Member-seat permission-gate false-positive fix (fb-e5b8b021-b74)
|
|
2
|
+
|
|
3
|
+
## What was broken
|
|
4
|
+
|
|
5
|
+
The Slack bot has a safety gate that decides whether a person is allowed to make
|
|
6
|
+
a given request. Every request gets a "sensitivity tier" from 0 (just chatting)
|
|
7
|
+
up to 4 (dangerous: money, production deploys, deleting data). Every person gets
|
|
8
|
+
a "role ceiling": a regular **member** can do tier-1 things (reads, summaries,
|
|
9
|
+
drafts) but not tier-2 and above without more authority.
|
|
10
|
+
|
|
11
|
+
The bug: when a regular member typed a totally harmless message like
|
|
12
|
+
**"post a check-in note here in 5 minutes"**, the gate labeled it a tier-2
|
|
13
|
+
"low-write" — because the word "post"/"note" tripped the write-verb detector.
|
|
14
|
+
Tier 2 is above a member's ceiling, so the gate **refused** the member with an
|
|
15
|
+
authority challenge: *"That's above what a member can authorize on their own."*
|
|
16
|
+
|
|
17
|
+
Because almost anything a member might ask the bot to say/post/schedule tripped
|
|
18
|
+
this, ordinary members effectively **could not talk to the bot at all** while
|
|
19
|
+
enforcement was on. Admins were fine; members were locked out. That was
|
|
20
|
+
demonstrated live from the member seat during today's Slack drive.
|
|
21
|
+
|
|
22
|
+
## Why it happened
|
|
23
|
+
|
|
24
|
+
Two places conspired:
|
|
25
|
+
|
|
26
|
+
1. The **heuristic classifier** treated ANY message containing a write verb
|
|
27
|
+
(`post`, `note`, `schedule`, …) as a tier-2 low-write — including the bot
|
|
28
|
+
simply posting a conversational note into the CURRENT channel, which isn't an
|
|
29
|
+
organizational action at all.
|
|
30
|
+
2. The **LLM classifier** (used in production) couldn't rescue it: its reconcile
|
|
31
|
+
step only ever RAISES the tier (`Math.max`), never lowers it. So even when the
|
|
32
|
+
LLM correctly read the message as conversational, the tier was clamped back up
|
|
33
|
+
to the heuristic's wrong tier-2.
|
|
34
|
+
|
|
35
|
+
## The fix
|
|
36
|
+
|
|
37
|
+
We taught the classifier to recognize a **harmless conversational self-post** — a
|
|
38
|
+
note / check-in / reminder / status update the bot would post into the current
|
|
39
|
+
conversation — and classify it at **tier 1** (the same level as a draft), which a
|
|
40
|
+
member IS allowed to direct. The recognition is deterministic and conservative:
|
|
41
|
+
|
|
42
|
+
- It fires only when BOTH a post-style verb AND a conversational-content noun are
|
|
43
|
+
present (so plain chatter like "just checking in" stays tier 0).
|
|
44
|
+
- It is disqualified by ANY organizational-write, external, or operational marker
|
|
45
|
+
— a ticket, a record, another named channel (`#…`), a calendar hold, an email,
|
|
46
|
+
or a "run/deploy/job". Those keep their higher tier.
|
|
47
|
+
- Floor detection (money, prod-deploy, credentials, destructive, external-send,
|
|
48
|
+
grant-authority) runs FIRST and always wins, so a privileged action hidden
|
|
49
|
+
inside a "post a note" phrasing is still caught and refused.
|
|
50
|
+
|
|
51
|
+
To make it stick on the production LLM path, a recognized conversational self-post
|
|
52
|
+
short-circuits the LLM entirely (just like a floor action does), so the judgment
|
|
53
|
+
band can't re-escalate it back to tier 2.
|
|
54
|
+
|
|
55
|
+
## What did NOT change
|
|
56
|
+
|
|
57
|
+
This is a precision fix, not a floor removal. A member asking for a genuine
|
|
58
|
+
low-write (file a ticket), an operational action (run a job), or any privileged
|
|
59
|
+
floor action is STILL refused exactly as before. The "someone said it's fine"
|
|
60
|
+
name-in-content trap still fires on floor actions. Guests still cannot direct
|
|
61
|
+
actions. Only the harmless conversational note/check-in case moved from
|
|
62
|
+
wrongly-refused to correctly-allowed.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Side-Effects Review — Member-seat permission-gate false-positive fix
|
|
2
|
+
|
|
3
|
+
**Slug:** `member-seat-gate-fix`
|
|
4
|
+
**Date:** 2026-07-03
|
|
5
|
+
**Author:** Echo (instar-dev)
|
|
6
|
+
**Defect:** fb-e5b8b021-b74 (member-seat conversational asks refused as "above what a member can authorize")
|
|
7
|
+
**Tier:** 1 (small, low-risk, reversible precision fix to an intent classifier)
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
With the Slack outbound/permission enforcement gate ON, an ordinary workspace
|
|
12
|
+
MEMBER's harmless conversational asks (e.g. "post a check-in note here in 5
|
|
13
|
+
minutes") were classified tier-2 "low-write", which exceeds the member ceiling
|
|
14
|
+
(tier 1), so the gate refused them with an authority challenge. Effect: ordinary
|
|
15
|
+
members effectively could not talk to the bot while enforcement was on.
|
|
16
|
+
|
|
17
|
+
Root cause (two-part):
|
|
18
|
+
- `HeuristicIntentClassifier` classified ANY write-verb message (`post`/`note`/
|
|
19
|
+
`schedule`/…) as tier-2 low-write — including the bot posting a conversational
|
|
20
|
+
note into the CURRENT conversation, which is not an organizational action.
|
|
21
|
+
- `LlmIntentClassifier.reconcile()` only escalates the tier (`Math.max`), never
|
|
22
|
+
lowers it, so the production LLM path could not correct the over-classification.
|
|
23
|
+
|
|
24
|
+
Fix: recognize a harmless conversational self-post (note / check-in / reminder /
|
|
25
|
+
status update into the current conversation, with no floor/org-write/external/
|
|
26
|
+
operational marker) as tier 1 (read/draft level) which a member may direct. A
|
|
27
|
+
recognized conversational self-post also short-circuits the LLM (symmetric to the
|
|
28
|
+
floor short-circuit) so the judgment band cannot re-escalate it.
|
|
29
|
+
|
|
30
|
+
**Files changed (source):**
|
|
31
|
+
- `src/permissions/types.ts` — add `conversational?: boolean` to `RequestIntent`.
|
|
32
|
+
- `src/permissions/IntentClassifier.ts` — add `isConversationalSelfPost()` +
|
|
33
|
+
regexes; new deterministic branch (ordered after floor + operational, before
|
|
34
|
+
the generic WRITE_VERB branch) returns tier 1 / `conversational: true`.
|
|
35
|
+
- `src/permissions/LlmIntentClassifier.ts` — new `conversational-deterministic`
|
|
36
|
+
degrade reason + short-circuit returning the deterministic conversational read
|
|
37
|
+
as-is (LLM never consulted, never re-escalated).
|
|
38
|
+
|
|
39
|
+
**Files changed (tests):** `tests/unit/slack-permission-gate.test.ts`,
|
|
40
|
+
`tests/unit/slack-llm-intent-classifier.test.ts`,
|
|
41
|
+
`tests/integration/slack-permission-pipeline.test.ts` — both-sides boundary
|
|
42
|
+
coverage (member conversational ask allowed; member genuine tier-2/floor still
|
|
43
|
+
refused; guest still refused; LLM cannot re-escalate; enforce-path pipeline).
|
|
44
|
+
|
|
45
|
+
## Decision-point inventory
|
|
46
|
+
|
|
47
|
+
- Harmless conversational note/check-in/reminder self-post in the current channel
|
|
48
|
+
→ **downgrade** to tier 1 (member-allowed).
|
|
49
|
+
- Any org-write/external marker (ticket, record, `#channel`, calendar, email,
|
|
50
|
+
outside party) → **keep** tier 2+ (unchanged).
|
|
51
|
+
- Any operational marker (run/deploy/job/pipeline) → **keep** operational tier
|
|
52
|
+
(unchanged).
|
|
53
|
+
- Any floor signal → **unchanged** (floor detection runs first and always wins).
|
|
54
|
+
- Plain chatter that merely mentions "checking in" (no post verb) → **unchanged**
|
|
55
|
+
(stays tier 0).
|
|
56
|
+
|
|
57
|
+
## 1–7. Analysis (behavioral / security / reversibility)
|
|
58
|
+
|
|
59
|
+
- **Behavioral:** the ONLY behavior change is that a narrow, deterministically
|
|
60
|
+
recognized class of harmless conversational self-posts moves from tier 2 to
|
|
61
|
+
tier 1 — allowing an ordinary member to direct them. Every other classification
|
|
62
|
+
is byte-identical.
|
|
63
|
+
- **Security / not weakening the gate:** the fix cannot widen access to a
|
|
64
|
+
privileged action. Floor detection (money / prod-deploy / credential-access /
|
|
65
|
+
destructive-data / external-send / grant-authority) is ordered FIRST in the
|
|
66
|
+
heuristic and short-circuits before the conversational branch, and the LLM
|
|
67
|
+
reconcile still drops any LLM-asserted floor. The conversational path is
|
|
68
|
+
additionally disqualified by any org-write, external, or operational marker.
|
|
69
|
+
The "X said it's fine" name-in-content trap (`content-name-not-authority`) is on
|
|
70
|
+
floor actions and is untouched. Guests still cannot direct actions (tier-1 needs
|
|
71
|
+
the member ceiling). Unregistered principals are still refused. This is a
|
|
72
|
+
precision fix, not a floor removal — verified by both-sides tests.
|
|
73
|
+
- **LLM injection surface:** because a recognized conversational self-post
|
|
74
|
+
short-circuits the LLM, untrusted message content can neither raise nor lower
|
|
75
|
+
the tier on that path; and on every other path the existing never-widen
|
|
76
|
+
reconcile clamp is unchanged.
|
|
77
|
+
- **Reversibility:** fully reversible by reverting the commit. No migration, no
|
|
78
|
+
config, no schema, no state format, no new dependency, no new failure mode.
|
|
79
|
+
- **Framework generality:** the change is pure classification logic in the
|
|
80
|
+
permission module; it does not touch session launch/inject and is
|
|
81
|
+
framework-agnostic (no Claude-specific assumption).
|
|
82
|
+
|
|
83
|
+
## Evidence pointers
|
|
84
|
+
|
|
85
|
+
- Typecheck: `tsc --noEmit` — 0 errors.
|
|
86
|
+
- Targeted tests: `slack-permission-gate`, `slack-llm-intent-classifier`,
|
|
87
|
+
`slack-permission-pipeline`, `slack-permission-enforce`,
|
|
88
|
+
`slack-permission-wiring`, `slack-scenario-audit-harness`,
|
|
89
|
+
`slack-relationship-anomaly`, `permissions-routes`,
|
|
90
|
+
`slack-testcast-principal-pipeline`, `intent-llm-judge*`, ambient gate — all
|
|
91
|
+
green (both-sides boundary + enforce-path pipeline).
|
|
92
|
+
- Live re-drive from the member seat is driven post-merge/deploy by the operator.
|