sentinelayer-cli 0.46.5 → 0.48.0
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/README.md +47 -3
- package/package.json +12 -7
- package/skills/omar-gate-setup/SKILL.md +103 -0
- package/skills/senti-agent-identity/SKILL.md +80 -0
- package/skills/senti-judge/SKILL.md +139 -0
- package/skills/senti-room-notifications/SKILL.md +73 -0
- package/skills/senti-room-notifications/listen-wrapper.cjs +150 -0
- package/skills/senti-room-notifications/package.json +1 -0
- package/skills/senti-room-notifications/test-classifier.js +109 -0
- package/skills/senti-room-notifications/test-receipt.js +54 -0
- package/skills/sentinelayer-cli/SKILL.md +222 -0
- package/src/agents/devtestbot/runner.js +22 -11
- package/src/agents/devtestbot/tool.js +24 -11
- package/src/agents/jules/fix-cycle.js +7 -1
- package/src/agents/jules/tools/runtime-audit.js +17 -12
- package/src/agents/shared-tools/dispatch-core.js +10 -5
- package/src/ai/aidenid.js +4 -2
- package/src/ai/domain-target-store.js +11 -5
- package/src/ai/identity-store.js +11 -5
- package/src/ai/site-store.js +8 -4
- package/src/audit/orchestrator.js +21 -14
- package/src/audit/package.js +6 -4
- package/src/audit/persona-loop.js +7 -0
- package/src/audit/replay.js +4 -2
- package/src/auth/gate.js +32 -1
- package/src/auth/session-store.js +37 -0
- package/src/board/evidence-resolvers.js +3 -4
- package/src/cli.js +23 -3
- package/src/commands/ai/identity-lifecycle.js +30 -26
- package/src/commands/ai/provision-governance.js +32 -24
- package/src/commands/ai/shared.js +6 -4
- package/src/commands/audit.js +14 -12
- package/src/commands/board.js +2 -2
- package/src/commands/chat.js +8 -6
- package/src/commands/judge.js +125 -0
- package/src/commands/legacy-args.js +1 -0
- package/src/commands/mcp.js +45 -52
- package/src/commands/omargate.js +2 -1
- package/src/commands/plugin.js +11 -3
- package/src/commands/review.js +9 -4
- package/src/commands/scan.js +7 -7
- package/src/commands/session.js +516 -30
- package/src/commands/skills.js +45 -0
- package/src/commands/watch.js +9 -7
- package/src/config/output-filesystem.js +156 -0
- package/src/config/schema.js +4 -2
- package/src/config/service.js +40 -4
- package/src/cost/history.js +15 -9
- package/src/daemon/artifact-lineage.js +15 -12
- package/src/daemon/assignment-ledger.js +31 -25
- package/src/daemon/ast-drift.js +7 -3
- package/src/daemon/budget-governor.js +26 -20
- package/src/daemon/error-worker.js +28 -22
- package/src/daemon/fix-cycle.js +5 -4
- package/src/daemon/hybrid-mapper.js +19 -16
- package/src/daemon/ingest-refresh.js +4 -0
- package/src/daemon/jira-lifecycle.js +21 -17
- package/src/daemon/operator-control.js +18 -15
- package/src/daemon/reliability-lane.js +18 -15
- package/src/daemon/scope-engine.js +12 -8
- package/src/daemon/watchdog.js +15 -12
- package/src/engram/build-state.js +24 -3
- package/src/engram/capability-index.js +367 -0
- package/src/engram/compile-graph.js +1063 -0
- package/src/engram/contracts/action-receipt.js +82 -0
- package/src/engram/contracts/capability-index.js +259 -0
- package/src/engram/contracts/capability.js +377 -0
- package/src/engram/contracts/content-hash.js +8 -0
- package/src/engram/contracts/evidence.js +258 -0
- package/src/engram/contracts/graph.js +594 -0
- package/src/engram/contracts/identity.js +8 -0
- package/src/engram/contracts/index.js +149 -0
- package/src/engram/contracts/media-asset.js +85 -0
- package/src/engram/contracts/money.js +249 -0
- package/src/engram/contracts/source-snapshot.js +57 -0
- package/src/engram/contracts/task-context-pack.js +114 -0
- package/src/engram/contracts/temporal-segment.js +72 -0
- package/src/engram/contracts/versions.js +96 -0
- package/src/engram/extract-html.js +692 -0
- package/src/engram/graph-store.js +877 -0
- package/src/engram/index.js +98 -14
- package/src/engram/ingest-site.js +132 -0
- package/src/engram/live-state.js +1180 -0
- package/src/engram/namespace.js +34 -1
- package/src/engram/retrieve-site.js +753 -0
- package/src/engram/safe-reader.js +597 -0
- package/src/engram/source-intake.js +251 -0
- package/src/engram/store.js +227 -9
- package/src/ingest/engine.js +21 -28
- package/src/judge/verdict.js +305 -0
- package/src/legacy-cli.js +96 -19
- package/src/mcp/bridge-inputs.js +25 -4
- package/src/mcp/cli-command-tools.js +70 -0
- package/src/mcp/registry.js +17 -13
- package/src/mcp/session-stdio-server.js +297 -19
- package/src/memory/blackboard.js +5 -4
- package/src/net/gh-api-path.js +35 -9
- package/src/net/test-egress-guard.js +16 -4
- package/src/plugin/manifest.js +12 -8
- package/src/review/ai-review.js +110 -10
- package/src/review/investor-dd-devtestbot.js +17 -6
- package/src/review/investor-dd-orchestrator.js +21 -13
- package/src/review/local-review.js +26 -16
- package/src/review/omargate-cache.js +5 -5
- package/src/review/omargate-orchestrator.js +89 -17
- package/src/review/replay.js +9 -4
- package/src/review/report.js +22 -13
- package/src/review/typesafe-severity.js +201 -0
- package/src/session/admission-auth.js +34 -7
- package/src/session/admission.js +110 -15
- package/src/session/attachment-summary.js +77 -0
- package/src/session/edit-summary.js +19 -0
- package/src/session/invitations.js +65 -1
- package/src/session/mentions.js +17 -9
- package/src/session/message-edits.js +5 -4
- package/src/session/preview.js +10 -2
- package/src/session/recap.js +3 -2
- package/src/session/room-files.js +519 -0
- package/src/session/route-classes.js +22 -8
- package/src/session/setup-guides.js +4 -0
- package/src/session/standup.js +192 -0
- package/src/session/sync.js +229 -10
- package/src/session/tickets.js +41 -0
- package/src/session/transcript.js +2 -1
- package/src/session/wake/resolve-target.js +7 -3
- package/src/skills/listener-runtime.cjs +92 -0
- package/src/skills/service.js +207 -0
- package/src/swarm/factory.js +5 -5
- package/src/swarm/pentest.js +9 -9
- package/src/swarm/report.js +4 -4
- package/src/swarm/runtime.js +15 -12
- package/src/swarm/scenario-dsl.js +7 -5
- package/src/telemetry/ledger.js +16 -7
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from "../../ai/domain-target-store.js";
|
|
25
25
|
import { listSites, recordTemporarySite } from "../../ai/site-store.js";
|
|
26
26
|
import { getIdentityById, recordProvisionedIdentity } from "../../ai/identity-store.js";
|
|
27
|
-
import { resolveOutputRoot } from "../../config/service.js";
|
|
27
|
+
import { resolveOutputRoot, resolveOutputContext } from "../../config/service.js";
|
|
28
28
|
import { fetchAidenIdCredentials, resolveActiveAuthSession } from "../../auth/service.js";
|
|
29
29
|
import {
|
|
30
30
|
buildCurlPreview,
|
|
@@ -76,7 +76,7 @@ async function provisionEmailAction(options, command) {
|
|
|
76
76
|
extractionTypes: options.extractionTypes,
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
const outputRoot = await
|
|
79
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
80
80
|
cwd: targetPath,
|
|
81
81
|
outputDirOverride: options.outputDir,
|
|
82
82
|
env: process.env,
|
|
@@ -90,7 +90,7 @@ async function provisionEmailAction(options, command) {
|
|
|
90
90
|
apiUrl,
|
|
91
91
|
idempotencyKey,
|
|
92
92
|
payload,
|
|
93
|
-
});
|
|
93
|
+
}, outputFs);
|
|
94
94
|
|
|
95
95
|
const session = await resolveActiveAuthSession({ cwd: process.cwd(), env: process.env, autoRotate: false }).catch(
|
|
96
96
|
() => null,
|
|
@@ -170,10 +170,11 @@ async function provisionEmailAction(options, command) {
|
|
|
170
170
|
apiUrl,
|
|
171
171
|
idempotencyKey,
|
|
172
172
|
response: execution.response,
|
|
173
|
-
});
|
|
173
|
+
}, outputFs);
|
|
174
174
|
|
|
175
175
|
const responseIdentity = execution.response || {};
|
|
176
176
|
const registryUpdate = await recordProvisionedIdentity({
|
|
177
|
+
outputFs,
|
|
177
178
|
outputRoot,
|
|
178
179
|
response: execution.response || {},
|
|
179
180
|
context: {
|
|
@@ -259,7 +260,7 @@ domain
|
|
|
259
260
|
.action(async (domainName, options, command) => {
|
|
260
261
|
const emitJson = shouldEmitJson(options, command);
|
|
261
262
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
262
|
-
const outputRoot = await
|
|
263
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
263
264
|
cwd: targetPath,
|
|
264
265
|
outputDirOverride: options.outputDir,
|
|
265
266
|
env: process.env,
|
|
@@ -287,7 +288,7 @@ domain
|
|
|
287
288
|
apiUrl,
|
|
288
289
|
idempotencyKey,
|
|
289
290
|
payload,
|
|
290
|
-
});
|
|
291
|
+
}, outputFs);
|
|
291
292
|
|
|
292
293
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
293
294
|
apiKey: options.apiKey,
|
|
@@ -355,10 +356,11 @@ domain
|
|
|
355
356
|
apiUrl,
|
|
356
357
|
idempotencyKey,
|
|
357
358
|
response: execution.response,
|
|
358
|
-
});
|
|
359
|
+
}, outputFs);
|
|
359
360
|
|
|
360
361
|
const proofResponse = execution.response || {};
|
|
361
362
|
const registryUpdate = await recordDomainProofResponse({
|
|
363
|
+
outputFs,
|
|
362
364
|
outputRoot,
|
|
363
365
|
domain: proofResponse.domain || {},
|
|
364
366
|
proof: proofResponse,
|
|
@@ -416,7 +418,7 @@ domain
|
|
|
416
418
|
.action(async (domainId, options, command) => {
|
|
417
419
|
const emitJson = shouldEmitJson(options, command);
|
|
418
420
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
419
|
-
const outputRoot = await
|
|
421
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
420
422
|
cwd: targetPath,
|
|
421
423
|
outputDirOverride: options.outputDir,
|
|
422
424
|
env: process.env,
|
|
@@ -451,7 +453,7 @@ domain
|
|
|
451
453
|
idempotencyKey,
|
|
452
454
|
domainId,
|
|
453
455
|
payload,
|
|
454
|
-
});
|
|
456
|
+
}, outputFs);
|
|
455
457
|
|
|
456
458
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
457
459
|
apiKey: options.apiKey,
|
|
@@ -511,10 +513,11 @@ domain
|
|
|
511
513
|
idempotencyKey,
|
|
512
514
|
domainId,
|
|
513
515
|
response: execution.response,
|
|
514
|
-
});
|
|
516
|
+
}, outputFs);
|
|
515
517
|
|
|
516
518
|
const proofResponse = execution.response || {};
|
|
517
519
|
const registryUpdate = await recordDomainProofResponse({
|
|
520
|
+
outputFs,
|
|
518
521
|
outputRoot,
|
|
519
522
|
domain: proofResponse.domain || {},
|
|
520
523
|
proof: proofResponse,
|
|
@@ -571,7 +574,7 @@ domain
|
|
|
571
574
|
.action(async (domainId, options, command) => {
|
|
572
575
|
const emitJson = shouldEmitJson(options, command);
|
|
573
576
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
574
|
-
const outputRoot = await
|
|
577
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
575
578
|
cwd: targetPath,
|
|
576
579
|
outputDirOverride: options.outputDir,
|
|
577
580
|
env: process.env,
|
|
@@ -593,7 +596,7 @@ domain
|
|
|
593
596
|
idempotencyKey,
|
|
594
597
|
domainId,
|
|
595
598
|
payload,
|
|
596
|
-
});
|
|
599
|
+
}, outputFs);
|
|
597
600
|
|
|
598
601
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
599
602
|
apiKey: options.apiKey,
|
|
@@ -653,9 +656,10 @@ domain
|
|
|
653
656
|
idempotencyKey,
|
|
654
657
|
domainId,
|
|
655
658
|
response: execution.response,
|
|
656
|
-
});
|
|
659
|
+
}, outputFs);
|
|
657
660
|
|
|
658
661
|
const registryUpdate = await recordDomainProofResponse({
|
|
662
|
+
outputFs,
|
|
659
663
|
outputRoot,
|
|
660
664
|
domain: execution.response || {},
|
|
661
665
|
proof: {},
|
|
@@ -712,7 +716,7 @@ target
|
|
|
712
716
|
.action(async (host, options, command) => {
|
|
713
717
|
const emitJson = shouldEmitJson(options, command);
|
|
714
718
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
715
|
-
const outputRoot = await
|
|
719
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
716
720
|
cwd: targetPath,
|
|
717
721
|
outputDirOverride: options.outputDir,
|
|
718
722
|
env: process.env,
|
|
@@ -745,7 +749,7 @@ target
|
|
|
745
749
|
apiUrl,
|
|
746
750
|
idempotencyKey,
|
|
747
751
|
payload,
|
|
748
|
-
});
|
|
752
|
+
}, outputFs);
|
|
749
753
|
|
|
750
754
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
751
755
|
apiKey: options.apiKey,
|
|
@@ -802,10 +806,11 @@ target
|
|
|
802
806
|
apiUrl,
|
|
803
807
|
idempotencyKey,
|
|
804
808
|
response: execution.response,
|
|
805
|
-
});
|
|
809
|
+
}, outputFs);
|
|
806
810
|
|
|
807
811
|
const proofResponse = execution.response || {};
|
|
808
812
|
const registryUpdate = await recordTargetProofResponse({
|
|
813
|
+
outputFs,
|
|
809
814
|
outputRoot,
|
|
810
815
|
target: proofResponse.target || {},
|
|
811
816
|
proof: proofResponse,
|
|
@@ -862,7 +867,7 @@ target
|
|
|
862
867
|
.action(async (targetId, options, command) => {
|
|
863
868
|
const emitJson = shouldEmitJson(options, command);
|
|
864
869
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
865
|
-
const outputRoot = await
|
|
870
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
866
871
|
cwd: targetPath,
|
|
867
872
|
outputDirOverride: options.outputDir,
|
|
868
873
|
env: process.env,
|
|
@@ -897,7 +902,7 @@ target
|
|
|
897
902
|
idempotencyKey,
|
|
898
903
|
targetId,
|
|
899
904
|
payload,
|
|
900
|
-
});
|
|
905
|
+
}, outputFs);
|
|
901
906
|
|
|
902
907
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
903
908
|
apiKey: options.apiKey,
|
|
@@ -957,10 +962,11 @@ target
|
|
|
957
962
|
idempotencyKey,
|
|
958
963
|
targetId,
|
|
959
964
|
response: execution.response,
|
|
960
|
-
});
|
|
965
|
+
}, outputFs);
|
|
961
966
|
|
|
962
967
|
const proofResponse = execution.response || {};
|
|
963
968
|
const registryUpdate = await recordTargetProofResponse({
|
|
969
|
+
outputFs,
|
|
964
970
|
outputRoot,
|
|
965
971
|
target: proofResponse.target || {},
|
|
966
972
|
proof: proofResponse,
|
|
@@ -1012,7 +1018,7 @@ target
|
|
|
1012
1018
|
.action(async (targetId, options, command) => {
|
|
1013
1019
|
const emitJson = shouldEmitJson(options, command);
|
|
1014
1020
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
1015
|
-
const outputRoot = await
|
|
1021
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
1016
1022
|
cwd: targetPath,
|
|
1017
1023
|
outputDirOverride: options.outputDir,
|
|
1018
1024
|
env: process.env,
|
|
@@ -1041,9 +1047,10 @@ target
|
|
|
1041
1047
|
generatedAt: new Date().toISOString(),
|
|
1042
1048
|
targetId,
|
|
1043
1049
|
response: execution.response,
|
|
1044
|
-
});
|
|
1050
|
+
}, outputFs);
|
|
1045
1051
|
|
|
1046
1052
|
const registryUpdate = await recordTargetProofResponse({
|
|
1053
|
+
outputFs,
|
|
1047
1054
|
outputRoot,
|
|
1048
1055
|
target: execution.response || {},
|
|
1049
1056
|
proof: {},
|
|
@@ -1098,7 +1105,7 @@ site
|
|
|
1098
1105
|
.action(async (identityId, options, command) => {
|
|
1099
1106
|
const emitJson = shouldEmitJson(options, command);
|
|
1100
1107
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
1101
|
-
const outputRoot = await
|
|
1108
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
1102
1109
|
cwd: targetPath,
|
|
1103
1110
|
outputDirOverride: options.outputDir,
|
|
1104
1111
|
env: process.env,
|
|
@@ -1132,7 +1139,7 @@ site
|
|
|
1132
1139
|
apiUrl,
|
|
1133
1140
|
idempotencyKey,
|
|
1134
1141
|
payload,
|
|
1135
|
-
});
|
|
1142
|
+
}, outputFs);
|
|
1136
1143
|
|
|
1137
1144
|
const resolvedCredentials = await resolveAidenIdCredentials({
|
|
1138
1145
|
apiKey: options.apiKey,
|
|
@@ -1190,9 +1197,10 @@ site
|
|
|
1190
1197
|
apiUrl,
|
|
1191
1198
|
idempotencyKey,
|
|
1192
1199
|
response: execution.response,
|
|
1193
|
-
});
|
|
1200
|
+
}, outputFs);
|
|
1194
1201
|
|
|
1195
1202
|
const registryUpdate = await recordTemporarySite({
|
|
1203
|
+
outputFs,
|
|
1196
1204
|
outputRoot,
|
|
1197
1205
|
site: execution.response || {},
|
|
1198
1206
|
context: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { requireOutputFileSystem } from "../../config/output-filesystem.js";
|
|
4
5
|
|
|
5
6
|
// Shared helper utilities for ai command modules.
|
|
6
7
|
|
|
@@ -128,9 +129,10 @@ export function renderLineageRows(lineage = {}) {
|
|
|
128
129
|
});
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
export async function writeArtifact(filePath, payload) {
|
|
132
|
-
|
|
133
|
-
await
|
|
132
|
+
export async function writeArtifact(filePath, payload, outputFs) {
|
|
133
|
+
requireOutputFileSystem(outputFs);
|
|
134
|
+
await outputFs.mkdir(path.dirname(filePath), { recursive: true });
|
|
135
|
+
await outputFs.writeFile(filePath, `${JSON.stringify(payload, null, 2)}\n`, "utf-8");
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
export function buildCurlPreview({ apiUrl, idempotencyKey, requestPath }) {
|
package/src/commands/audit.js
CHANGED
|
@@ -7,7 +7,7 @@ import { runAuditOrchestrator } from "../audit/orchestrator.js";
|
|
|
7
7
|
import { loadAuditRunReport, resolveAuditRunDirectory, writeDdPackage } from "../audit/package.js";
|
|
8
8
|
import { writeAuditComparisonArtifact } from "../audit/replay.js";
|
|
9
9
|
import { loadAuditRegistry, selectAuditAgents } from "../audit/registry.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveOutputContext } from "../config/service.js";
|
|
11
11
|
import { createAgentEvent } from "../events/schema.js";
|
|
12
12
|
import { createAuditSessionReporter, resolveAuditSessionId } from "../session/audit-reporter.js";
|
|
13
13
|
import { resolveActionOptions } from "./action-options.js";
|
|
@@ -217,7 +217,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
217
217
|
const actionOptions = resolveActionOptions(options, command);
|
|
218
218
|
const emitJson = shouldEmitJson(actionOptions, command);
|
|
219
219
|
const targetPath = path.resolve(process.cwd(), String(actionOptions.path || "."));
|
|
220
|
-
const outputRoot = await
|
|
220
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
221
221
|
cwd: targetPath,
|
|
222
222
|
outputDirOverride: actionOptions.outputDir,
|
|
223
223
|
env: process.env,
|
|
@@ -228,6 +228,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
228
228
|
});
|
|
229
229
|
const { report } = await loadAuditRunReport(runDirectory);
|
|
230
230
|
const ddPackage = await writeDdPackage({
|
|
231
|
+
outputFs,
|
|
231
232
|
report,
|
|
232
233
|
runDirectory,
|
|
233
234
|
});
|
|
@@ -269,7 +270,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
269
270
|
const actionOptions = resolveActionOptions(options, command);
|
|
270
271
|
const emitJson = shouldEmitJson(actionOptions, command);
|
|
271
272
|
const initialTargetPath = path.resolve(process.cwd(), String(actionOptions.path || "."));
|
|
272
|
-
const outputRoot = await
|
|
273
|
+
const { outputRoot } = await resolveOutputContext({
|
|
273
274
|
cwd: initialTargetPath,
|
|
274
275
|
outputDirOverride: actionOptions.outputDir,
|
|
275
276
|
env: process.env,
|
|
@@ -306,6 +307,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
306
307
|
baseReport,
|
|
307
308
|
candidateReport: replayResult,
|
|
308
309
|
outputDirectory: replayResult.runDirectory,
|
|
310
|
+
outputFs: replayResult.outputFs,
|
|
309
311
|
});
|
|
310
312
|
|
|
311
313
|
const payload = {
|
|
@@ -347,7 +349,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
347
349
|
const actionOptions = resolveActionOptions(options, command);
|
|
348
350
|
const emitJson = shouldEmitJson(actionOptions, command);
|
|
349
351
|
const targetPath = path.resolve(process.cwd(), String(actionOptions.path || "."));
|
|
350
|
-
const outputRoot = await
|
|
352
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
351
353
|
cwd: targetPath,
|
|
352
354
|
outputDirOverride: actionOptions.outputDir,
|
|
353
355
|
env: process.env,
|
|
@@ -366,6 +368,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
366
368
|
baseReport,
|
|
367
369
|
candidateReport,
|
|
368
370
|
outputDirectory: candidateRunDirectory,
|
|
371
|
+
outputFs,
|
|
369
372
|
});
|
|
370
373
|
|
|
371
374
|
const payload = {
|
|
@@ -869,14 +872,12 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
869
872
|
const { julesAuditLoop } = await import("../agents/jules/loop.js");
|
|
870
873
|
const { JULES_DEFINITION } = await import("../agents/jules/config/definition.js");
|
|
871
874
|
const { collectCodebaseIngest, generateCodebaseIngest } = await import("../ingest/engine.js");
|
|
872
|
-
const { resolveOutputRoot: resolveOut } = await import("../config/service.js");
|
|
873
875
|
const { createBlackboard } = await import("../memory/blackboard.js");
|
|
874
876
|
const { runDeterministicReviewPipeline } = await import("../review/local-review.js");
|
|
875
|
-
const fsp = await import("node:fs/promises");
|
|
876
877
|
|
|
877
|
-
const outputRoot = await
|
|
878
|
+
const { outputRoot, outputFs } = await resolveOutputContext({ cwd: targetPath, outputDirOverride: actionOptions.outputDir });
|
|
878
879
|
const artifactDir = path.join(outputRoot, "reports", "jules-" + Date.now());
|
|
879
|
-
await
|
|
880
|
+
await outputFs.mkdir(artifactDir, { recursive: true });
|
|
880
881
|
|
|
881
882
|
// Build event handler
|
|
882
883
|
const onEvent = buildEventHandler(emitStream, emitJson, JULES_DEFINITION);
|
|
@@ -888,7 +889,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
888
889
|
let ingest;
|
|
889
890
|
try {
|
|
890
891
|
ingest = await generateCodebaseIngest({
|
|
891
|
-
rootPath: targetPath, outputDir:
|
|
892
|
+
rootPath: targetPath, outputDir: actionOptions.outputDir,
|
|
892
893
|
refresh: Boolean(actionOptions.refresh),
|
|
893
894
|
});
|
|
894
895
|
} catch {
|
|
@@ -907,6 +908,7 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
907
908
|
targetPath,
|
|
908
909
|
mode: "full",
|
|
909
910
|
outputDir: artifactDir,
|
|
911
|
+
outputFs,
|
|
910
912
|
});
|
|
911
913
|
emitProgress(onEvent, JULES_DEFINITION,
|
|
912
914
|
"Baseline complete: P0=" + (omarBaseline?.summary?.P0 || 0) +
|
|
@@ -1085,21 +1087,21 @@ export function registerAuditCommand(program, invokeLegacy) {
|
|
|
1085
1087
|
signature: JULES_DEFINITION.signature,
|
|
1086
1088
|
};
|
|
1087
1089
|
|
|
1088
|
-
await
|
|
1090
|
+
await outputFs.writeFile(
|
|
1089
1091
|
path.join(artifactDir, "JULES_AUDIT.json"),
|
|
1090
1092
|
JSON.stringify(reportPayload, null, 2),
|
|
1091
1093
|
);
|
|
1092
1094
|
|
|
1093
1095
|
// Write baseline artifact if it exists
|
|
1094
1096
|
if (omarBaseline) {
|
|
1095
|
-
await
|
|
1097
|
+
await outputFs.writeFile(
|
|
1096
1098
|
path.join(artifactDir, "OMAR_BASELINE.json"),
|
|
1097
1099
|
JSON.stringify(omarBaseline, null, 2),
|
|
1098
1100
|
);
|
|
1099
1101
|
}
|
|
1100
1102
|
|
|
1101
1103
|
// Write reconciliation artifact
|
|
1102
|
-
await
|
|
1104
|
+
await outputFs.writeFile(
|
|
1103
1105
|
path.join(artifactDir, "RECONCILIATION.json"),
|
|
1104
1106
|
JSON.stringify(reconciliation, null, 2),
|
|
1105
1107
|
);
|
package/src/commands/board.js
CHANGED
|
@@ -104,10 +104,10 @@ export function registerBoardCommand(program) {
|
|
|
104
104
|
.description("Check whether a ticket's evidence holds (done | not-done | cannot-verify)")
|
|
105
105
|
.requiredOption("--file <path>", "Ticket JSON file with an `evidence` array")
|
|
106
106
|
.option("--json", "Emit machine-readable output")
|
|
107
|
-
.action(async (options) => {
|
|
107
|
+
.action(async (options, command) => {
|
|
108
108
|
const code = await runBoardCheck({
|
|
109
109
|
file: path.resolve(process.cwd(), String(options.file)),
|
|
110
|
-
emitJson: Boolean(options.json),
|
|
110
|
+
emitJson: Boolean(options.json || command.optsWithGlobals().json),
|
|
111
111
|
});
|
|
112
112
|
process.exitCode = code;
|
|
113
113
|
});
|
package/src/commands/chat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { requireOutputFileSystem } from "../config/output-filesystem.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolveProvider,
|
|
11
11
|
} from "../ai/client.js";
|
|
12
12
|
import { recordCliLlmSessionUsage, usageNumber } from "../billing/llm-session-usage.js";
|
|
13
|
-
import {
|
|
13
|
+
import { resolveOutputContext } from "../config/service.js";
|
|
14
14
|
import { estimateModelCost } from "../cost/tracker.js";
|
|
15
15
|
import { estimateTokens } from "../cost/tokenizer.js";
|
|
16
16
|
import { normalizeSessionId } from "../session/paths.js";
|
|
@@ -43,10 +43,11 @@ async function readPromptFromStdin() {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
async function appendTranscriptEntries({ transcriptPath, entries } = {}) {
|
|
47
|
-
|
|
46
|
+
async function appendTranscriptEntries({ transcriptPath, entries, outputFs } = {}) {
|
|
47
|
+
requireOutputFileSystem(outputFs);
|
|
48
|
+
await outputFs.mkdir(path.dirname(transcriptPath), { recursive: true });
|
|
48
49
|
const rows = entries.map((entry) => JSON.stringify(entry)).join("\n");
|
|
49
|
-
await
|
|
50
|
+
await outputFs.appendFile(transcriptPath, `${rows}\n`, "utf-8");
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export function registerChatCommand(program) {
|
|
@@ -77,7 +78,7 @@ export function registerChatCommand(program) {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
80
|
-
const outputRoot = await
|
|
81
|
+
const { outputRoot, outputFs } = await resolveOutputContext({
|
|
81
82
|
cwd: targetPath,
|
|
82
83
|
outputDirOverride: options.outputDir,
|
|
83
84
|
env: process.env,
|
|
@@ -159,6 +160,7 @@ export function registerChatCommand(program) {
|
|
|
159
160
|
});
|
|
160
161
|
|
|
161
162
|
await appendTranscriptEntries({
|
|
163
|
+
outputFs,
|
|
162
164
|
transcriptPath,
|
|
163
165
|
entries: [
|
|
164
166
|
{
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
import { formatJudgeVerdictErrors, renderJudgeVerdictMessage, validateJudgeVerdict } from "../judge/verdict.js";
|
|
6
|
+
|
|
7
|
+
function shouldEmitJson(options, command) {
|
|
8
|
+
if (options && options.json) return true;
|
|
9
|
+
return typeof command?.optsWithGlobals === "function" ? Boolean(command.optsWithGlobals().json) : false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function readStdinText() {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
15
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function readVerdictDocument(options) {
|
|
19
|
+
if (options.file && options.stdin) throw new Error("Use --file or --stdin, not both.");
|
|
20
|
+
if (!options.file && !options.stdin) throw new Error("Give the verdict with --file <path> or --stdin.");
|
|
21
|
+
const raw = options.stdin
|
|
22
|
+
? await readStdinText()
|
|
23
|
+
: await fsp.readFile(path.resolve(process.cwd(), String(options.file)), "utf8");
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
throw new Error(`The verdict is not valid JSON: ${error.message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function report(emitJson, payload, text) {
|
|
32
|
+
if (emitJson) {
|
|
33
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
34
|
+
} else {
|
|
35
|
+
process.stdout.write(`${text}\n`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function fail(emitJson, command, error) {
|
|
40
|
+
const message = error && error.message ? error.message : String(error);
|
|
41
|
+
if (emitJson) {
|
|
42
|
+
process.stdout.write(`${JSON.stringify({ command, ok: false, reason: message }, null, 2)}\n`);
|
|
43
|
+
} else {
|
|
44
|
+
process.stderr.write(`${command} failed: ${message}\n`);
|
|
45
|
+
}
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function registerJudgeCommand(program) {
|
|
50
|
+
const judge = program
|
|
51
|
+
.command("judge")
|
|
52
|
+
.description("Judge a coding agent's work and send the verdict back (LLM-as-a-judge loop)");
|
|
53
|
+
|
|
54
|
+
judge
|
|
55
|
+
.command("check")
|
|
56
|
+
.description("Validate a judge-verdict offline and print the message the coder will receive")
|
|
57
|
+
.option("--file <path>", "Verdict JSON file")
|
|
58
|
+
.option("--stdin", "Read the verdict JSON from stdin")
|
|
59
|
+
.option("--escalate-to <handle...>", "Human handle(s) to mention when the verdict escalates")
|
|
60
|
+
.option("--json", "Emit machine-readable output")
|
|
61
|
+
.action(async (options, command) => {
|
|
62
|
+
const emitJson = shouldEmitJson(options, command);
|
|
63
|
+
try {
|
|
64
|
+
const checked = validateJudgeVerdict(await readVerdictDocument(options));
|
|
65
|
+
if (!checked.ok) {
|
|
66
|
+
report(emitJson, { command: "judge check", ok: false, errors: checked.errors },
|
|
67
|
+
`Invalid verdict: ${formatJudgeVerdictErrors(checked.errors)}`);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const message = renderJudgeVerdictMessage(checked.verdict, { escalateTo: options.escalateTo || [] });
|
|
72
|
+
report(emitJson, { command: "judge check", ok: true, verdict: checked.verdict, message }, message);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
fail(emitJson, "judge check", error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
judge
|
|
79
|
+
.command("verdict <sessionId>")
|
|
80
|
+
.description("Send a judge-verdict to the room: the coder is mentioned and woken, and the verdict is recorded")
|
|
81
|
+
.option("--agent <id>", "Your judge agent id (default: SENTINELAYER_AGENT_ID)")
|
|
82
|
+
.option("--file <path>", "Verdict JSON file")
|
|
83
|
+
.option("--stdin", "Read the verdict JSON from stdin")
|
|
84
|
+
.option("--via <transport>", "auto (the API route when the server has it, else a room message), api, or room", "auto")
|
|
85
|
+
.option("--escalate-to <handle...>", "Human handle(s) to mention when the verdict escalates")
|
|
86
|
+
.option("--path <path>", "Workspace path for the session", ".")
|
|
87
|
+
.option("--dry-run", "Validate and print the message without sending it")
|
|
88
|
+
.option("--json", "Emit machine-readable output")
|
|
89
|
+
.action(async (sessionId, options, command) => {
|
|
90
|
+
const emitJson = shouldEmitJson(options, command);
|
|
91
|
+
try {
|
|
92
|
+
const verdict = await readVerdictDocument(options);
|
|
93
|
+
const agentId = String(options.agent || process.env.SENTINELAYER_AGENT_ID || "").trim();
|
|
94
|
+
if (!agentId) throw new Error("Name your judge agent with --agent <id> or SENTINELAYER_AGENT_ID.");
|
|
95
|
+
const targetPath = path.resolve(process.cwd(), String(options.path || "."));
|
|
96
|
+
// One implementation for the CLI and MCP: the native judge_verdict tool, which already runs
|
|
97
|
+
// under the admission policy every local session tool uses.
|
|
98
|
+
const { createSessionMcpToolHandlers } = await import("../mcp/session-stdio-server.js");
|
|
99
|
+
const handlers = createSessionMcpToolHandlers({ targetPath });
|
|
100
|
+
const result = await handlers.judge_verdict({
|
|
101
|
+
sessionId,
|
|
102
|
+
agentId,
|
|
103
|
+
verdict,
|
|
104
|
+
via: options.via,
|
|
105
|
+
escalateTo: options.escalateTo || [],
|
|
106
|
+
dryRun: Boolean(options.dryRun),
|
|
107
|
+
});
|
|
108
|
+
const payload = { command: "judge verdict", ...result };
|
|
109
|
+
if (!result.ok) {
|
|
110
|
+
const why = result.errors ? formatJudgeVerdictErrors(result.errors) : result.reason;
|
|
111
|
+
report(emitJson, payload, `Verdict not sent: ${why}`);
|
|
112
|
+
process.exitCode = 1;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (result.dryRun) {
|
|
116
|
+
report(emitJson, payload, result.message);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
report(emitJson, payload,
|
|
120
|
+
`Verdict ${result.verdict.verdict} (round ${result.verdict.round}) sent to @${result.verdict.coder} via ${result.transport}.`);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
fail(emitJson, "judge verdict", error);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
@@ -57,6 +57,7 @@ export function buildLegacyArgs(baseArgs, { commandOptions = {}, command } = {})
|
|
|
57
57
|
appendPassthroughFlag(args, "--max-runtime-minutes", commandOptions.maxRuntimeMinutes);
|
|
58
58
|
appendPassthroughFlag(args, "--model", commandOptions.model);
|
|
59
59
|
appendPassthroughFlag(args, "--provider", commandOptions.provider);
|
|
60
|
+
if (commandOptions.severityClassifier && commandOptions.severityClassifier !== "off") appendPassthroughFlag(args, "--severity-classifier", commandOptions.severityClassifier);
|
|
60
61
|
appendPassthroughFlag(args, "--reuse-omargate", commandOptions.reuseOmargate);
|
|
61
62
|
appendPassthroughFlag(args, "--scope-mode", commandOptions.scopeMode);
|
|
62
63
|
appendBooleanFlag(args, "--diff", commandOptions.diff);
|