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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +92 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +10 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +35 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +12 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts +103 -0
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -0
- package/dist/monitoring/AgentWorktreeReaper.js +159 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -0
- package/dist/monitoring/CiFailurePoller.d.ts +1 -7
- package/dist/monitoring/CiFailurePoller.d.ts.map +1 -1
- package/dist/monitoring/CiFailurePoller.js +5 -12
- package/dist/monitoring/CiFailurePoller.js.map +1 -1
- package/dist/monitoring/CorrectionAnalyzer.d.ts +65 -0
- package/dist/monitoring/CorrectionAnalyzer.d.ts.map +1 -0
- package/dist/monitoring/CorrectionAnalyzer.js +78 -0
- package/dist/monitoring/CorrectionAnalyzer.js.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts +130 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.js +249 -0
- package/dist/monitoring/CorrectionCaptureLoop.js.map +1 -0
- package/dist/monitoring/CorrectionLedger.d.ts +149 -0
- package/dist/monitoring/CorrectionLedger.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLedger.js +386 -0
- package/dist/monitoring/CorrectionLedger.js.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts +135 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.js +185 -0
- package/dist/monitoring/CorrectionLoopDriver.js.map +1 -0
- package/dist/monitoring/HumanAsDetectorLog.d.ts +31 -1
- package/dist/monitoring/HumanAsDetectorLog.d.ts.map +1 -1
- package/dist/monitoring/HumanAsDetectorLog.js +70 -0
- package/dist/monitoring/HumanAsDetectorLog.js.map +1 -1
- package/dist/monitoring/agentWorktreeGit.d.ts +43 -0
- package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -0
- package/dist/monitoring/agentWorktreeGit.js +194 -0
- package/dist/monitoring/agentWorktreeGit.js.map +1 -0
- package/dist/monitoring/scrubSecrets.d.ts +23 -0
- package/dist/monitoring/scrubSecrets.d.ts.map +1 -0
- package/dist/monitoring/scrubSecrets.js +41 -0
- package/dist/monitoring/scrubSecrets.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +20 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +8 -3
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +7 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +213 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates/jobs/instar/correction-analyzer.md +32 -0
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.132.md +42 -0
- package/upgrades/1.3.133.md +70 -0
- package/upgrades/side-effects/agent-worktree-reaper.md +96 -0
- package/upgrades/side-effects/correction-preference-learning-sentinel-slice1b.md +79 -0
package/dist/server/routes.js
CHANGED
|
@@ -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
|