instar 1.3.754 → 1.3.755

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiDH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAyBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6H7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA2/CD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CAonBN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA8ylBtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuDH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAyBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6H7D,OAAO,KAAK,EAAW,oBAAoB,EAAe,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAgmDD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CAonBN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAs0lBtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -32,6 +32,7 @@ import { PrHandLease } from '../core/PrHandLease.js';
32
32
  import { ConversationRegistry } from '../core/ConversationRegistry.js';
33
33
  import { claimSuspensionExcludesPin } from '../core/TopicClaimAnnotationStore.js';
34
34
  import { parseProfileTrigger, platformMessageIdFrom } from '../core/topicProfileIngress.js';
35
+ import { classifyProfileIntent, toProfilePatch, } from '../core/ProfileIntentClassifier.js';
35
36
  import { slugifyChannelName } from '../messaging/slack/sanitize.js';
36
37
  import { TopicProfileOrchestrator, resolvedToApplied, } from '../core/TopicProfileOrchestrator.js';
37
38
  import { CodexResumeMap } from '../core/CodexResumeMap.js';
@@ -704,6 +705,20 @@ function appendTopicProfileAudit(stateDir, event) {
704
705
  }
705
706
  let _projectDir = process.cwd();
706
707
  let _sharedIntelligence = null;
708
+ // Offender #1 conversion (docs/specs/keyword-intent-conversions-1-and-3.md): the
709
+ // framework/model/thinking WRITE decision is inferred by the ProfileIntentClassifier
710
+ // (LLM + recent conversation), replacing the removed keyword regexes in
711
+ // parseProfileTrigger. Dev-gated dark (resolveDevAgentGate) + dry-run FIRST: while
712
+ // dark or dry-run the message ALWAYS passes through (never actuated); the classifier
713
+ // still runs on a dev agent and LOGS would-actuate vs would-pass to
714
+ // logs/profile-intent.jsonl for the soak. Resolved once in startServer.
715
+ let _profileIntentEnabled = false;
716
+ let _profileIntentDryRun = true;
717
+ let _profileIntentMinConfidence = 0.85;
718
+ let _profileIntentTimeoutMs = 4000;
719
+ let _profileIntentContextTurns = 6;
720
+ let _profileIntentModelTier = 'fast';
721
+ let _profileIntentStateDir = '';
707
722
  let _selfKnowledgeTree = null;
708
723
  let _slackAdapter = null;
709
724
  // WS1.1 dispatch-to-owner (Slack arm): the owner-side bridge reconstructs a Slack
@@ -1669,6 +1684,42 @@ function messageToPipeline(msg, topicName) {
1669
1684
  * a message carrying platform forward metadata falls through as normal
1670
1685
  * conversation regardless of sender.
1671
1686
  */
1687
+ /**
1688
+ * Offender #1 conversion soak log: one JSONL line per LLM-engaged
1689
+ * ProfileIntentClassifier decision (docs/specs/keyword-intent-conversions-1-and-3.md).
1690
+ * A prefilter-skip is always a would-pass and the bulk of traffic — skipping it
1691
+ * cuts volume AND the privacy surface to messages that named a profile signal and
1692
+ * actually reached the classifier. Observability only — never gates the message.
1693
+ */
1694
+ function logProfileIntent(topicId, text, result, acted) {
1695
+ try {
1696
+ if (result.source === 'prefilter-skip')
1697
+ return;
1698
+ if (!_profileIntentStateDir)
1699
+ return;
1700
+ const logDir = path.join(_profileIntentStateDir, 'logs');
1701
+ fs.mkdirSync(logDir, { recursive: true });
1702
+ const decision = result.isChange ? (acted ? 'actuate' : 'would-actuate') : 'pass';
1703
+ const line = JSON.stringify({
1704
+ ts: new Date().toISOString(),
1705
+ topicId,
1706
+ decision,
1707
+ dryRun: _profileIntentDryRun,
1708
+ source: result.source,
1709
+ intent: result.intent,
1710
+ value: result.value,
1711
+ confidence: result.confidence,
1712
+ reason: result.reason,
1713
+ // NO raw message content: the enum-bounded fields above are what the FP-rate
1714
+ // soak needs, and the resolved `value` is already a closed-enum member. We
1715
+ // record only the message LENGTH (non-content) — mirroring the codebase's
1716
+ // dev-soak convention of never persisting a raw operator quote.
1717
+ textLen: typeof text === 'string' ? text.length : 0,
1718
+ });
1719
+ fs.appendFileSync(path.join(logDir, 'profile-intent.jsonl'), line + '\n');
1720
+ }
1721
+ catch { /* @silent-fallback-ok: the soak audit is observability-only — a log write fault must never gate or throw out of the message path (the classifier decision already stands) */ }
1722
+ }
1672
1723
  async function handleTopicProfileIngress(telegram, topicId, text, telegramUserId, msg) {
1673
1724
  const surface = _topicProfileWriteSurface;
1674
1725
  const slots = _topicProfileConfirmSlots;
@@ -1683,10 +1734,65 @@ async function handleTopicProfileIngress(telegram, topicId, text, telegramUserId
1683
1734
  catch { /* @silent-fallback-ok: a trust-floor read fault fails toward NOT-a-trigger (deny-by-default) — the conversational profile parse never runs for an unauthorized turn (TOPIC-PROFILE-SPEC §10.1) */ }
1684
1735
  if (!authorized)
1685
1736
  return false;
1686
- const trigger = parseProfileTrigger(text);
1687
- if (!trigger)
1688
- return false;
1689
1737
  const forwarded = msg.metadata?.forwarded === true;
1738
+ const trigger = parseProfileTrigger(text);
1739
+ if (!trigger) {
1740
+ // Offender #1 conversion (docs/specs/keyword-intent-conversions-1-and-3.md):
1741
+ // the framework/model/thinking WRITE decision moved OUT of parseProfileTrigger
1742
+ // (keyword regexes) into the ProfileIntentClassifier — an LLM reasoning over
1743
+ // the message + recent conversation with structured-enum output, per the
1744
+ // constitutional standard "Intelligence Infers, Keywords Only Guard".
1745
+ // Dev-gated dark + dry-run FIRST; fail-OPEN on every uncertainty.
1746
+ if (forwarded)
1747
+ return false; // forwarded content is never a command
1748
+ if (!_profileIntentEnabled)
1749
+ return false; // fleet-dark → pass to the agent
1750
+ let conversationContext = [];
1751
+ try {
1752
+ // Fetch one extra turn, then drop a trailing turn equal to THIS message —
1753
+ // getTopicHistory (oldest→newest) usually already contains the just-logged
1754
+ // inbound row, so without this the model would see the message twice (once
1755
+ // as MESSAGE, once as the newest CONTEXT turn).
1756
+ const hist = telegram.getTopicHistory?.(topicId, _profileIntentContextTurns + 1) ?? [];
1757
+ conversationContext = hist.map((h) => ({ fromUser: !!h.fromUser, text: String(h.text ?? '') }));
1758
+ const trimmed = text.trim();
1759
+ while (conversationContext.length > 0
1760
+ && conversationContext[conversationContext.length - 1].fromUser
1761
+ && conversationContext[conversationContext.length - 1].text.trim() === trimmed) {
1762
+ conversationContext.pop();
1763
+ }
1764
+ conversationContext = conversationContext.slice(-_profileIntentContextTurns);
1765
+ }
1766
+ catch { /* @silent-fallback-ok — context is best-effort; classify on the message alone */ }
1767
+ const result = await classifyProfileIntent({
1768
+ text,
1769
+ conversationContext,
1770
+ intelligence: _sharedIntelligence,
1771
+ minConfidence: _profileIntentMinConfidence,
1772
+ timeoutMs: _profileIntentTimeoutMs,
1773
+ maxContextTurns: _profileIntentContextTurns,
1774
+ modelTier: _profileIntentModelTier,
1775
+ });
1776
+ const willAct = result.isChange && !_profileIntentDryRun;
1777
+ logProfileIntent(topicId, text, result, willAct);
1778
+ // Dry-run (the soak) / fail-open / pass-through: log would-actuate vs
1779
+ // would-pass, but pass the message through untouched. Real actuation needs a
1780
+ // deliberate dryRun:false, AND fail-open means uncertainty never actuates.
1781
+ if (!willAct)
1782
+ return false;
1783
+ const patch = toProfilePatch(result);
1784
+ if (!patch)
1785
+ return false;
1786
+ const applyPrincipal = { kind: 'operator', platform: 'telegram', uid: String(telegramUserId) };
1787
+ const applyResult = await surface.applyWrite({
1788
+ topicKey: String(topicId), patch, principal: applyPrincipal, origin: 'conversational', discloseInReply: true,
1789
+ });
1790
+ try {
1791
+ await telegram.sendToTopic(topicId, applyResult.reply);
1792
+ }
1793
+ catch { /* @silent-fallback-ok: best-effort disclosure send (TOPIC-PROFILE-SPEC §10.1) */ }
1794
+ return true;
1795
+ }
1690
1796
  if (forwarded)
1691
1797
  return false;
1692
1798
  const topicKey = String(topicId);
@@ -5329,6 +5435,19 @@ export async function startServer(options) {
5329
5435
  const { TopicProfileResolver } = await import('../core/TopicProfileResolver.js');
5330
5436
  const { normalizeTierEscalationConfig } = await import('../core/ModelTierEscalation.js');
5331
5437
  const topicProfilesCfg = config.topicProfiles;
5438
+ // Offender #1 conversion: resolve the ProfileIntentClassifier settings ONCE
5439
+ // (the module-level ingress handler has no config in scope). `enabled` rides
5440
+ // resolveDevAgentGate (dark on the fleet, live on a dev agent — registered in
5441
+ // DEV_GATED_FEATURES, configPath topicProfiles.intentClassifier.enabled);
5442
+ // dryRun ships true (the dry-run canary — actuates only on a deliberate flip).
5443
+ const _intentCfg = topicProfilesCfg?.intentClassifier;
5444
+ _profileIntentEnabled = resolveDevAgentGate(_intentCfg?.enabled, config);
5445
+ _profileIntentDryRun = _intentCfg?.dryRun ?? true;
5446
+ _profileIntentMinConfidence = _intentCfg?.minConfidence ?? 0.85;
5447
+ _profileIntentTimeoutMs = _intentCfg?.timeoutMs ?? 4000;
5448
+ _profileIntentContextTurns = _intentCfg?.contextWindowTurns ?? 6;
5449
+ _profileIntentModelTier = _intentCfg?.modelTier ?? 'fast';
5450
+ _profileIntentStateDir = config.stateDir;
5332
5451
  _topicProfileStore = new TopicProfileStore({
5333
5452
  stateFilePath: path.join(config.stateDir, 'state', 'topic-profiles.json'),
5334
5453
  legacyFrameworksPath: path.join(config.stateDir, 'state', 'topic-frameworks.json'),