instar 1.3.131 → 1.3.133

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 (70) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +92 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +10 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  8. package/dist/core/PostUpdateMigrator.js +35 -2
  9. package/dist/core/PostUpdateMigrator.js.map +1 -1
  10. package/dist/core/types.d.ts +12 -0
  11. package/dist/core/types.d.ts.map +1 -1
  12. package/dist/core/types.js.map +1 -1
  13. package/dist/monitoring/AgentWorktreeReaper.d.ts +103 -0
  14. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -0
  15. package/dist/monitoring/AgentWorktreeReaper.js +159 -0
  16. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -0
  17. package/dist/monitoring/CiFailurePoller.d.ts +1 -7
  18. package/dist/monitoring/CiFailurePoller.d.ts.map +1 -1
  19. package/dist/monitoring/CiFailurePoller.js +5 -12
  20. package/dist/monitoring/CiFailurePoller.js.map +1 -1
  21. package/dist/monitoring/CorrectionAnalyzer.d.ts +65 -0
  22. package/dist/monitoring/CorrectionAnalyzer.d.ts.map +1 -0
  23. package/dist/monitoring/CorrectionAnalyzer.js +78 -0
  24. package/dist/monitoring/CorrectionAnalyzer.js.map +1 -0
  25. package/dist/monitoring/CorrectionCaptureLoop.d.ts +130 -0
  26. package/dist/monitoring/CorrectionCaptureLoop.d.ts.map +1 -0
  27. package/dist/monitoring/CorrectionCaptureLoop.js +249 -0
  28. package/dist/monitoring/CorrectionCaptureLoop.js.map +1 -0
  29. package/dist/monitoring/CorrectionLedger.d.ts +149 -0
  30. package/dist/monitoring/CorrectionLedger.d.ts.map +1 -0
  31. package/dist/monitoring/CorrectionLedger.js +386 -0
  32. package/dist/monitoring/CorrectionLedger.js.map +1 -0
  33. package/dist/monitoring/CorrectionLoopDriver.d.ts +135 -0
  34. package/dist/monitoring/CorrectionLoopDriver.d.ts.map +1 -0
  35. package/dist/monitoring/CorrectionLoopDriver.js +185 -0
  36. package/dist/monitoring/CorrectionLoopDriver.js.map +1 -0
  37. package/dist/monitoring/HumanAsDetectorLog.d.ts +31 -1
  38. package/dist/monitoring/HumanAsDetectorLog.d.ts.map +1 -1
  39. package/dist/monitoring/HumanAsDetectorLog.js +70 -0
  40. package/dist/monitoring/HumanAsDetectorLog.js.map +1 -1
  41. package/dist/monitoring/agentWorktreeGit.d.ts +43 -0
  42. package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -0
  43. package/dist/monitoring/agentWorktreeGit.js +194 -0
  44. package/dist/monitoring/agentWorktreeGit.js.map +1 -0
  45. package/dist/monitoring/scrubSecrets.d.ts +23 -0
  46. package/dist/monitoring/scrubSecrets.d.ts.map +1 -0
  47. package/dist/monitoring/scrubSecrets.js +41 -0
  48. package/dist/monitoring/scrubSecrets.js.map +1 -0
  49. package/dist/scaffold/templates.d.ts.map +1 -1
  50. package/dist/scaffold/templates.js +1 -0
  51. package/dist/scaffold/templates.js.map +1 -1
  52. package/dist/server/AgentServer.d.ts +4 -0
  53. package/dist/server/AgentServer.d.ts.map +1 -1
  54. package/dist/server/AgentServer.js +20 -0
  55. package/dist/server/AgentServer.js.map +1 -1
  56. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  57. package/dist/server/CapabilityIndex.js +8 -3
  58. package/dist/server/CapabilityIndex.js.map +1 -1
  59. package/dist/server/routes.d.ts +7 -0
  60. package/dist/server/routes.d.ts.map +1 -1
  61. package/dist/server/routes.js +213 -0
  62. package/dist/server/routes.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/data/builtin-manifest.json +63 -63
  65. package/src/scaffold/templates/jobs/instar/correction-analyzer.md +32 -0
  66. package/src/scaffold/templates.ts +1 -0
  67. package/upgrades/1.3.132.md +42 -0
  68. package/upgrades/1.3.133.md +70 -0
  69. package/upgrades/side-effects/agent-worktree-reaper.md +96 -0
  70. package/upgrades/side-effects/correction-preference-learning-sentinel-slice1b.md +79 -0
@@ -19,6 +19,8 @@ import { FailureLedger } from '../monitoring/FailureLedger.js';
19
19
  import { FailureAttributionEngine } from '../monitoring/FailureAttributionEngine.js';
20
20
  import { FailureAnalyzer } from '../monitoring/FailureAnalyzer.js';
21
21
  import { FailureLoopDriver } from '../monitoring/FailureLoopDriver.js';
22
+ import { CorrectionLedger } from '../monitoring/CorrectionLedger.js';
23
+ import { scrubSecrets as scrubCorrectionSecrets } from '../monitoring/scrubSecrets.js';
22
24
  import { HumanAsDetectorLog } from '../monitoring/HumanAsDetectorLog.js';
23
25
  import { parseVersion, compareVersions } from '../lifeline/versionHandshake.js';
24
26
  import { readLatestCodexUsage } from '../providers/adapters/openai-codex/observability/codexRateLimitReader.js';
@@ -3345,6 +3347,18 @@ export function createRoutes(ctx) {
3345
3347
  }
3346
3348
  res.json(ctx.sessionReaper.snapshot());
3347
3349
  });
3350
+ // AgentWorktreeReaper (RESPONSIBLE-RESOURCE-USAGE — OS resource hygiene). The
3351
+ // pull-surface answer to "which stale worktrees can be reclaimed, and why is
3352
+ // each kept?": every `.worktrees/` worktree's verdict (active-lock /
3353
+ // uncommitted-changes / not-stale / unmerged / reap-eligible) + the reclaimable
3354
+ // count + whether reaping is armed (enabled, dryRun). Read-only, Bearer-auth.
3355
+ router.get('/worktrees/agent-reaper', (_req, res) => {
3356
+ if (!ctx.agentWorktreeReaper) {
3357
+ res.status(503).json({ error: 'agent worktree reaper unavailable' });
3358
+ return;
3359
+ }
3360
+ res.json(ctx.agentWorktreeReaper.snapshot());
3361
+ });
3348
3362
  // Reap-log (UNIFIED-SESSION-LIFECYCLE §P4). The pull-surface answer to "why did
3349
3363
  // my session vanish?": every reap + every refused/skipped terminate, newest
3350
3364
  // last. Read-only, Bearer-auth (the router-level middleware). `?limit=N`
@@ -9847,6 +9861,205 @@ export function createRoutes(ctx) {
9847
9861
  res.status(500).json({ error: err instanceof Error ? err.message : 'Failed to read preferences' });
9848
9862
  }
9849
9863
  });
9864
+ // ── Corrections (Correction & Preference Learning Sentinel, Slice 1b) ──
9865
+ //
9866
+ // Read surface over the CorrectionLedger — distilled, scrubbed correction /
9867
+ // preference records. SIGNAL-ONLY: this loop never blocks or rewrites a
9868
+ // message; these routes are observability + the agent-diagnosed one-tap.
9869
+ //
9870
+ // GET /corrections — list deduped records (bearer; 503 when off;
9871
+ // toApiView strips raw `learning`; keyset
9872
+ // pagination via ?before / ?limit / ?kind / ?status)
9873
+ // GET /corrections/:id — one record (toApiView)
9874
+ // POST /corrections — agent-diagnosed one-tap (requires X-Instar-Request:1)
9875
+ //
9876
+ // 503 when the feature is disabled (null ledger). The /corrections API NEVER
9877
+ // serves the raw `learning` text under any condition (CorrectionLedger.toApiView).
9878
+ router.get('/corrections', (req, res) => {
9879
+ if (!ctx.correctionLedger) {
9880
+ res.status(503).json({ error: 'correction-learning disabled' });
9881
+ return;
9882
+ }
9883
+ const limit = req.query.limit ? Math.min(Math.max(1, parseInt(req.query.limit, 10) || 100), 1000) : 100;
9884
+ const before = req.query.before ? Date.parse(req.query.before) : undefined;
9885
+ const kind = typeof req.query.kind === 'string' && ['infra-gap', 'user-preference', 'noise'].includes(req.query.kind)
9886
+ ? req.query.kind
9887
+ : undefined;
9888
+ const status = typeof req.query.status === 'string' ? req.query.status : undefined;
9889
+ const records = ctx.correctionLedger.list({
9890
+ limit,
9891
+ beforeMs: before && !Number.isNaN(before) ? before : undefined,
9892
+ kind,
9893
+ status,
9894
+ });
9895
+ res.json({
9896
+ records: records.map((r) => CorrectionLedger.toApiView(r)),
9897
+ count: records.length,
9898
+ totalRecords: ctx.correctionLedger.countRecords(),
9899
+ nextBefore: records.length === limit ? records[records.length - 1].detectedAt : null,
9900
+ });
9901
+ });
9902
+ router.get('/corrections/:id', (req, res) => {
9903
+ if (!ctx.correctionLedger) {
9904
+ res.status(503).json({ error: 'correction-learning disabled' });
9905
+ return;
9906
+ }
9907
+ const rec = ctx.correctionLedger.get(req.params.id);
9908
+ if (!rec) {
9909
+ res.status(404).json({ error: 'not found' });
9910
+ return;
9911
+ }
9912
+ res.json(CorrectionLedger.toApiView(rec));
9913
+ });
9914
+ router.post('/corrections', (req, res) => {
9915
+ if (!ctx.correctionLedger) {
9916
+ res.status(503).json({ error: 'correction-learning disabled' });
9917
+ return;
9918
+ }
9919
+ // Intent marker — paired with the deterministic scrub. NOT a transport boundary.
9920
+ if (req.headers['x-instar-request'] !== '1') {
9921
+ res.status(403).json({ error: 'POST /corrections requires the X-Instar-Request: 1 intent header' });
9922
+ return;
9923
+ }
9924
+ const body = req.body ?? {};
9925
+ const learning = typeof body.learning === 'string' ? body.learning.trim() : '';
9926
+ const kindRaw = typeof body.kind === 'string' ? body.kind : '';
9927
+ if (!learning) {
9928
+ res.status(400).json({ error: 'learning is required' });
9929
+ return;
9930
+ }
9931
+ if (!['infra-gap', 'user-preference', 'noise'].includes(kindRaw)) {
9932
+ res.status(400).json({ error: 'kind must be one of infra-gap | user-preference | noise' });
9933
+ return;
9934
+ }
9935
+ const kind = kindRaw;
9936
+ const summary = typeof body.scrubbedSummary === 'string' && body.scrubbedSummary.trim()
9937
+ ? body.scrubbedSummary.trim()
9938
+ : learning;
9939
+ // POST-SCRUB at the boundary (defense in depth — the writer scrubs again).
9940
+ const rec = ctx.correctionLedger.record({
9941
+ kind,
9942
+ learning: scrubCorrectionSecrets(learning),
9943
+ scrubbedSummary: scrubCorrectionSecrets(summary),
9944
+ deterministicWeight: typeof body.deterministicWeight === 'number' ? body.deterministicWeight : 3,
9945
+ llmConfidence: typeof body.llmConfidence === 'number' ? body.llmConfidence : 0,
9946
+ topicId: typeof body.topicId === 'number' ? body.topicId : null,
9947
+ });
9948
+ if (!rec) {
9949
+ res.status(500).json({ error: 'failed to record (logged via fail-open path)' });
9950
+ return;
9951
+ }
9952
+ res.status(201).json(CorrectionLedger.toApiView(rec));
9953
+ });
9954
+ // The recurrence analyzer + closed-loop tick (Correction & Preference Learning
9955
+ // Sentinel, spec §3.5/§3.6/§3.7). Invoked by the off-by-default
9956
+ // `correction-analyzer` builtin job (Tier-1 supervised). Runs the 3-pronged
9957
+ // recurrence gate, then ROUTES each crossing record by kind:
9958
+ // user-preference (policy-clean) → recordPreference()
9959
+ // user-preference (policy-match) → Attention (human disposes)
9960
+ // infra-gap (autoFeedback OFF, default) → tracked Action + draft Initiative
9961
+ // infra-gap (autoFeedback ON) → loopback POST /feedback (real route guards)
9962
+ // …then opens a verify window. BY-CONSTRUCTION authority guard: the loop's
9963
+ // injected deps carry NO proposal-minting and NO direct memory-file write.
9964
+ router.post('/corrections/analyze', async (req, res) => {
9965
+ if (!ctx.correctionLedger) {
9966
+ res.status(503).json({ error: 'correction-learning disabled' });
9967
+ return;
9968
+ }
9969
+ try {
9970
+ const cl = ctx.config.monitoring?.correctionLearning;
9971
+ const { CorrectionAnalyzer } = await import('../monitoring/CorrectionAnalyzer.js');
9972
+ const { CorrectionLoopDriver } = await import('../monitoring/CorrectionLoopDriver.js');
9973
+ const { PreferencesManager } = await import('../core/PreferencesManager.js');
9974
+ const analyzer = new CorrectionAnalyzer(ctx.correctionLedger, {
9975
+ minSupport: cl?.minSupport ?? 4,
9976
+ minDistinctDaysInfraGap: cl?.minDistinctDaysInfraGap ?? 3,
9977
+ minDistinctDaysPreference: cl?.minDistinctDaysPreference ?? 2,
9978
+ minDistinctTopicsPreference: cl?.minDistinctTopicsPreference ?? 2,
9979
+ });
9980
+ const prefs = new PreferencesManager(ctx.config.stateDir);
9981
+ const port = ctx.config.port;
9982
+ const authToken = ctx.config.authToken;
9983
+ const evo = ctx.evolution;
9984
+ const tracker = ctx.initiativeTracker;
9985
+ // Loopback POST helpers — bearer-authed to the agent's OWN routes so they
9986
+ // traverse the real middleware (feedback anomaly/quality/length guards;
9987
+ // attention tone gate). Authorization is never logged.
9988
+ const feedbackLoopbackPost = async (payload) => {
9989
+ try {
9990
+ const resp = await fetch(`http://localhost:${port}/feedback`, {
9991
+ method: 'POST',
9992
+ headers: {
9993
+ 'Content-Type': 'application/json',
9994
+ Authorization: `Bearer ${authToken}`,
9995
+ 'X-Instar-Origin': 'correction-loop',
9996
+ },
9997
+ body: JSON.stringify(payload),
9998
+ });
9999
+ return resp.status === 201;
10000
+ }
10001
+ catch {
10002
+ return false;
10003
+ }
10004
+ };
10005
+ const attentionRoute = async (item) => {
10006
+ try {
10007
+ const resp = await fetch(`http://localhost:${port}/attention`, {
10008
+ method: 'POST',
10009
+ headers: {
10010
+ 'Content-Type': 'application/json',
10011
+ Authorization: `Bearer ${authToken}`,
10012
+ 'X-Instar-Origin': 'correction-loop',
10013
+ },
10014
+ body: JSON.stringify({ source: 'correction-loop', body: item.summary, ...item }),
10015
+ });
10016
+ return resp.status === 201;
10017
+ }
10018
+ catch {
10019
+ return false;
10020
+ }
10021
+ };
10022
+ const driver = new CorrectionLoopDriver(ctx.correctionLedger, analyzer, {
10023
+ addAction: (o) => (evo?.addAction ? evo.addAction(o) : { id: 'no-evolution' }),
10024
+ createInitiative: async (i) => {
10025
+ if (tracker?.create) {
10026
+ const created = await tracker.create(i);
10027
+ return { id: created.id };
10028
+ }
10029
+ return { id: i.id };
10030
+ },
10031
+ feedbackLoopbackPost,
10032
+ recordPreference: (p) => { prefs.recordPreference(p); },
10033
+ attentionRoute,
10034
+ autoFeedback: cl?.autoFeedback === true,
10035
+ verifyWindowDaysPreference: cl?.verifyWindowDaysPreference ?? 7,
10036
+ verifyWindowDaysInfraGap: cl?.verifyWindowDaysInfraGap ?? 14,
10037
+ maxReopens: cl?.maxReopens ?? 2,
10038
+ preferenceStillPresent: (dedupeKey) => prefs.read().preferences.some((e) => e.dedupeKey === dedupeKey),
10039
+ });
10040
+ const analysis = analyzer.analyze();
10041
+ const routed = await driver.route();
10042
+ const verified = driver.runVerification().evaluated.length;
10043
+ res.json({
10044
+ analysis: {
10045
+ considered: analysis.considered,
10046
+ crossed: analysis.crossed.length,
10047
+ belowThreshold: analysis.belowThreshold,
10048
+ },
10049
+ routed: {
10050
+ total: routed.routed.length,
10051
+ toFeedback: routed.toFeedback,
10052
+ toPreferences: routed.toPreferences,
10053
+ toAttention: routed.toAttention,
10054
+ },
10055
+ verified,
10056
+ });
10057
+ }
10058
+ catch (err) {
10059
+ // Fail-open: the analyzer never crashes the caller (job).
10060
+ res.status(200).json({ error: 'analyze failed (logged)', detail: err instanceof Error ? err.message : String(err) });
10061
+ }
10062
+ });
9850
10063
  // ORG-INTENT.md tradeoff resolution (Phase 3 of the ORG-INTENT runtime
9851
10064
  // project). Given two contending values, consults the organization's
9852
10065
  // tradeoff hierarchy and returns which wins, with the basis for the