@neurcode-ai/cli 0.16.4 → 0.16.6
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/.telemetry-bundle/dist/index.js +0 -0
- package/LICENSE +201 -0
- package/dist/api-client.d.ts +75 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +43 -0
- package/dist/api-client.js.map +1 -1
- package/dist/commands/brain.d.ts.map +1 -1
- package/dist/commands/brain.js +151 -0
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/cursor.d.ts.map +1 -1
- package/dist/commands/cursor.js +72 -0
- package/dist/commands/cursor.js.map +1 -1
- package/dist/commands/eval.d.ts +19 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/eval.js +246 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/onboard.d.ts +29 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +247 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/runtime-doctor.d.ts.map +1 -1
- package/dist/commands/runtime-doctor.js +80 -9
- package/dist/commands/runtime-doctor.js.map +1 -1
- package/dist/commands/runtime-sync.d.ts.map +1 -1
- package/dist/commands/runtime-sync.js +22 -0
- package/dist/commands/runtime-sync.js.map +1 -1
- package/dist/commands/runtime.d.ts +18 -0
- package/dist/commands/runtime.d.ts.map +1 -1
- package/dist/commands/runtime.js +321 -1
- package/dist/commands/runtime.js.map +1 -1
- package/dist/commands/session-hook.d.ts +10 -2
- package/dist/commands/session-hook.d.ts.map +1 -1
- package/dist/commands/session-hook.js +533 -122
- package/dist/commands/session-hook.js.map +1 -1
- package/dist/commands/session.d.ts +34 -0
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +243 -2
- package/dist/commands/session.js.map +1 -1
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime-build.json +5 -5
- package/dist/utils/agent-guard-supervisor.d.ts.map +1 -1
- package/dist/utils/agent-guard-supervisor.js +0 -1
- package/dist/utils/agent-guard-supervisor.js.map +1 -1
- package/dist/utils/cursor-gate.d.ts +1 -0
- package/dist/utils/cursor-gate.d.ts.map +1 -1
- package/dist/utils/cursor-gate.js +34 -7
- package/dist/utils/cursor-gate.js.map +1 -1
- package/dist/utils/guided-eval.d.ts +251 -0
- package/dist/utils/guided-eval.d.ts.map +1 -0
- package/dist/utils/guided-eval.js +880 -0
- package/dist/utils/guided-eval.js.map +1 -0
- package/dist/utils/local-repo-brain.d.ts +158 -0
- package/dist/utils/local-repo-brain.d.ts.map +1 -0
- package/dist/utils/local-repo-brain.js +854 -0
- package/dist/utils/local-repo-brain.js.map +1 -0
- package/dist/utils/runtime-live.d.ts +25 -0
- package/dist/utils/runtime-live.d.ts.map +1 -1
- package/dist/utils/runtime-live.js +103 -4
- package/dist/utils/runtime-live.js.map +1 -1
- package/dist/utils/runtime-outbox.d.ts +2 -1
- package/dist/utils/runtime-outbox.d.ts.map +1 -1
- package/dist/utils/runtime-outbox.js +21 -16
- package/dist/utils/runtime-outbox.js.map +1 -1
- package/dist/utils/session-allowlist-rules.d.ts +12 -0
- package/dist/utils/session-allowlist-rules.d.ts.map +1 -1
- package/dist/utils/session-allowlist-rules.js +61 -1
- package/dist/utils/session-allowlist-rules.js.map +1 -1
- package/dist/utils/structural-understanding.d.ts +61 -1
- package/dist/utils/structural-understanding.d.ts.map +1 -1
- package/dist/utils/structural-understanding.js +534 -1
- package/dist/utils/structural-understanding.js.map +1 -1
- package/dist/utils/v0-governance.d.ts.map +1 -1
- package/dist/utils/v0-governance.js +10 -0
- package/dist/utils/v0-governance.js.map +1 -1
- package/package.json +7 -8
package/dist/commands/session.js
CHANGED
|
@@ -54,6 +54,8 @@ exports.waiveGovernanceObligationCommand = waiveGovernanceObligationCommand;
|
|
|
54
54
|
exports.listRuntimeSessionsCommand = listRuntimeSessionsCommand;
|
|
55
55
|
exports.showRuntimeSessionCommand = showRuntimeSessionCommand;
|
|
56
56
|
exports.aiChangeRecordCommand = aiChangeRecordCommand;
|
|
57
|
+
exports.exportAIChangeRecordForCli = exportAIChangeRecordForCli;
|
|
58
|
+
exports.verifyAIChangeRecordForCli = verifyAIChangeRecordForCli;
|
|
57
59
|
exports.structuralUnderstandingCommand = structuralUnderstandingCommand;
|
|
58
60
|
exports.listSessionsCommand = listSessionsCommand;
|
|
59
61
|
exports.endSessionCommand = endSessionCommand;
|
|
@@ -73,6 +75,7 @@ const session_continuity_1 = require("../utils/session-continuity");
|
|
|
73
75
|
const runtime_evidence_1 = require("../utils/runtime-evidence");
|
|
74
76
|
const v0_governance_1 = require("../utils/v0-governance");
|
|
75
77
|
const runtime_connection_1 = require("../utils/runtime-connection");
|
|
78
|
+
const runtime_connection_2 = require("../utils/runtime-connection");
|
|
76
79
|
const runtime_live_1 = require("../utils/runtime-live");
|
|
77
80
|
const session_allowlist_rules_1 = require("../utils/session-allowlist-rules");
|
|
78
81
|
const runtime_outbox_1 = require("../utils/runtime-outbox");
|
|
@@ -187,6 +190,15 @@ function resolveUnderstandingDiff(repoRoot, options) {
|
|
|
187
190
|
function loadLocalGovernanceSession(repoRoot, sessionId) {
|
|
188
191
|
return sessionId ? (0, governance_runtime_1.loadSession)(repoRoot, sessionId) : (0, governance_runtime_1.loadActiveSession)(repoRoot);
|
|
189
192
|
}
|
|
193
|
+
function normalizeApprovalPathForCloudMatch(repoRoot, inputPath) {
|
|
194
|
+
const normalized = inputPath.trim().replace(/\\/g, '/');
|
|
195
|
+
if (!normalized)
|
|
196
|
+
return normalized;
|
|
197
|
+
if ((0, node_path_1.isAbsolute)(normalized)) {
|
|
198
|
+
return (0, node_path_1.relative)(repoRoot, normalized).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
199
|
+
}
|
|
200
|
+
return normalized.replace(/^\.\//, '').replace(/^\//, '');
|
|
201
|
+
}
|
|
190
202
|
function latestEventTimestamp(session) {
|
|
191
203
|
return [...session.events]
|
|
192
204
|
.reverse()
|
|
@@ -635,20 +647,64 @@ async function approveGovernanceSessionCommand(options = {}) {
|
|
|
635
647
|
}
|
|
636
648
|
const repoRoot = (0, v0_governance_1.resolveRepoRoot)(options.dir || process.cwd());
|
|
637
649
|
try {
|
|
638
|
-
const
|
|
650
|
+
const sessionId = options.sessionId || (0, governance_runtime_1.loadActiveSession)(repoRoot)?.sessionId;
|
|
651
|
+
const normalizedPath = normalizeApprovalPathForCloudMatch(repoRoot, path);
|
|
652
|
+
const discoveredCloudApproval = sessionId
|
|
653
|
+
? await (0, runtime_live_1.findRuntimeLiveApprovalRequest)(repoRoot, sessionId, normalizedPath)
|
|
654
|
+
: null;
|
|
655
|
+
const explicitCloudApproval = options.requestId && sessionId
|
|
656
|
+
? {
|
|
657
|
+
id: options.requestId,
|
|
658
|
+
sessionId,
|
|
659
|
+
path: normalizedPath,
|
|
660
|
+
reason: options.reason || 'Operator approved exact path',
|
|
661
|
+
status: 'requested',
|
|
662
|
+
requestedBy: 'local_operator',
|
|
663
|
+
expiresAt: undefined,
|
|
664
|
+
}
|
|
665
|
+
: null;
|
|
666
|
+
const matchingCloudApproval = discoveredCloudApproval || explicitCloudApproval;
|
|
667
|
+
const result = (0, governance_runtime_1.approveSession)(repoRoot, path, {
|
|
668
|
+
reason: options.reason,
|
|
669
|
+
sessionId: options.sessionId,
|
|
670
|
+
source: matchingCloudApproval ? 'dashboard' : 'local_cli',
|
|
671
|
+
approvedBy: matchingCloudApproval?.requestedBy || null,
|
|
672
|
+
requestId: matchingCloudApproval?.id || null,
|
|
673
|
+
expiresAt: matchingCloudApproval?.expiresAt || undefined,
|
|
674
|
+
});
|
|
675
|
+
if (matchingCloudApproval?.id) {
|
|
676
|
+
(0, runtime_live_1.queueRuntimeLiveApprovalAppliedAck)(repoRoot, result.sessionId, matchingCloudApproval, {
|
|
677
|
+
appliedPath: result.approvedPath,
|
|
678
|
+
expiresAt: result.expiresAt,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
639
681
|
const session = (0, governance_runtime_1.loadSession)(repoRoot, result.sessionId);
|
|
640
682
|
if (session) {
|
|
641
683
|
(0, session_allowlist_rules_1.refreshSessionScopeRules)({ dir: repoRoot, sessionId: session.sessionId });
|
|
642
684
|
await (0, runtime_live_1.publishRuntimeLiveStatus)(repoRoot, session);
|
|
643
685
|
}
|
|
644
686
|
if (options.json) {
|
|
645
|
-
console.log(JSON.stringify({
|
|
687
|
+
console.log(JSON.stringify({
|
|
688
|
+
ok: true,
|
|
689
|
+
repoRoot,
|
|
690
|
+
...result,
|
|
691
|
+
runtimeApprovalRequest: matchingCloudApproval?.id
|
|
692
|
+
? {
|
|
693
|
+
id: matchingCloudApproval.id,
|
|
694
|
+
source: discoveredCloudApproval ? 'matched' : 'explicit',
|
|
695
|
+
acknowledgementQueued: true,
|
|
696
|
+
}
|
|
697
|
+
: null,
|
|
698
|
+
}, null, 2));
|
|
646
699
|
return;
|
|
647
700
|
}
|
|
648
701
|
console.log('');
|
|
649
702
|
console.log(chalk.green(`Approved: ${result.approvedPath}`));
|
|
650
703
|
console.log(chalk.dim(`Session: ${result.sessionId}`));
|
|
651
704
|
console.log(chalk.dim(`Approved paths: ${compactList(result.approvedPaths, 12)}`));
|
|
705
|
+
if (matchingCloudApproval?.id) {
|
|
706
|
+
console.log(chalk.dim(`Runtime request: ${matchingCloudApproval.id} (${discoveredCloudApproval ? 'matched' : 'explicit'})`));
|
|
707
|
+
}
|
|
652
708
|
console.log('');
|
|
653
709
|
}
|
|
654
710
|
catch (error) {
|
|
@@ -898,6 +954,7 @@ function renderAIChangeRecord(record, recordPath) {
|
|
|
898
954
|
const pendingAmendments = record.plan.pendingAmendments.length;
|
|
899
955
|
const consequenceImpacts = topConsequenceImpactsFromRecord(record.understanding.latest?.consequenceUnderstanding);
|
|
900
956
|
const consequenceFindings = topConsequenceFindingsFromRecord(record.understanding.latest?.consequenceUnderstanding);
|
|
957
|
+
const reuseFindings = reuseFindingsFromRecord(record.understanding.latest);
|
|
901
958
|
console.log('');
|
|
902
959
|
console.log(chalk.bold(`AI Change Record ${record.session.sessionId}`));
|
|
903
960
|
console.log(chalk.dim('-'.repeat(76)));
|
|
@@ -912,6 +969,22 @@ function renderAIChangeRecord(record, recordPath) {
|
|
|
912
969
|
console.log(`Checks: ok=${counts.ok} warn=${counts.warn} block=${counts.block} approvals=${counts.approval}`);
|
|
913
970
|
console.log(`Oblig: ${record.architecture.summary.satisfied}/${record.architecture.summary.total} satisfied${record.architecture.summary.blockingPending ? chalk.yellow(` · ${record.architecture.summary.blockingPending} blocking`) : ''}`);
|
|
914
971
|
console.log(`Approvals: ${activeApprovals.length} active · ${record.approvals.length} lifecycle entr${record.approvals.length === 1 ? 'y' : 'ies'}`);
|
|
972
|
+
if (record.accountability) {
|
|
973
|
+
const facts = record.accountability.facts;
|
|
974
|
+
console.log('');
|
|
975
|
+
console.log(chalk.bold('Change accountability'));
|
|
976
|
+
console.log(`Asked: ${chalk.white(truncate(facts.agentGoal, 120))}`);
|
|
977
|
+
console.log(`Touched: ${chalk.dim(compactList(facts.touchedPaths, 8))}`);
|
|
978
|
+
console.log(`Allowed: ${chalk.dim(compactList(facts.allowedPaths, 6))}`);
|
|
979
|
+
console.log(`Blocked: ${facts.blockedBoundaries.length > 0 ? chalk.yellow(compactList(facts.blockedBoundaries, 6)) : chalk.dim('none')}`);
|
|
980
|
+
console.log(`Owners: ${facts.boundaryOwners.length > 0 ? chalk.white(compactList(facts.boundaryOwners, 6)) : chalk.dim('not recorded')}`);
|
|
981
|
+
console.log(`Approval: ${facts.approvalRequired ? chalk.yellow('required') : chalk.dim('not required')} · ${facts.exactPathApprovalOnly ? 'exact-path only' : 'no exact approval applied'}`);
|
|
982
|
+
console.log(`Neighbor: ${facts.neighboringSensitiveFilesBlocked ? chalk.green('contained') : chalk.dim('not observed')}`);
|
|
983
|
+
console.log(`Receipt: ${chalk.dim(facts.evidenceReceipt)} · source excluded=${facts.sourceExcluded ? 'yes' : 'no'}`);
|
|
984
|
+
if (record.accountability.assumptions.length > 0) {
|
|
985
|
+
console.log(`Assume: ${chalk.dim(compactList(record.accountability.assumptions, 2))}`);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
915
988
|
if (record.understanding.latest) {
|
|
916
989
|
const understanding = record.understanding.latest;
|
|
917
990
|
console.log(`Understand: ${understanding.changedSymbolCount} changed symbols · ` +
|
|
@@ -955,6 +1028,13 @@ function renderAIChangeRecord(record, recordPath) {
|
|
|
955
1028
|
console.log(chalk.dim(` ${finding.rank}. ${truncate(finding.summary, 140)}${consumers}${reasons ? ` · ${reasons}` : ''}`));
|
|
956
1029
|
}
|
|
957
1030
|
}
|
|
1031
|
+
if (reuseFindings.length > 0) {
|
|
1032
|
+
console.log(`Reuse: ${reuseFindings.length} advisory finding${reuseFindings.length === 1 ? '' : 's'}`);
|
|
1033
|
+
for (const finding of reuseFindings.slice(0, 5)) {
|
|
1034
|
+
console.log(chalk.dim(` ${finding.changed.file}#${finding.changed.name} resembles ` +
|
|
1035
|
+
`${finding.existing.file}#${finding.existing.name} · ${finding.matchType} · ${finding.confidence}`));
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
958
1038
|
}
|
|
959
1039
|
if (blocked.length > 0) {
|
|
960
1040
|
console.log('');
|
|
@@ -1039,6 +1119,17 @@ function topConsequenceFindingsFromRecord(value) {
|
|
|
1039
1119
|
return [{ rank, summary, consumerCount, nonTestConsumerCount, testConsumerCount, reasonCodes }];
|
|
1040
1120
|
}).sort((a, b) => a.rank - b.rank || a.summary.localeCompare(b.summary));
|
|
1041
1121
|
}
|
|
1122
|
+
function reuseFindingsFromRecord(value) {
|
|
1123
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1124
|
+
return [];
|
|
1125
|
+
const raw = value.reuseFindings;
|
|
1126
|
+
return Array.isArray(raw)
|
|
1127
|
+
? raw.filter((item) => Boolean(item) &&
|
|
1128
|
+
typeof item === 'object' &&
|
|
1129
|
+
!Array.isArray(item) &&
|
|
1130
|
+
item.schemaVersion === 'neurcode.reuse-finding.v1')
|
|
1131
|
+
: [];
|
|
1132
|
+
}
|
|
1042
1133
|
function aiChangeRecordCommand(options = {}) {
|
|
1043
1134
|
const repoRoot = (0, v0_governance_1.resolveRepoRoot)(options.dir || process.cwd());
|
|
1044
1135
|
const session = resolveAIChangeRecordSession(repoRoot, options);
|
|
@@ -1072,6 +1163,144 @@ function aiChangeRecordCommand(options = {}) {
|
|
|
1072
1163
|
}
|
|
1073
1164
|
renderAIChangeRecord(record, path.replace(`${repoRoot}/`, ''));
|
|
1074
1165
|
}
|
|
1166
|
+
const PUBLIC_AI_CHANGE_RECORD_DIR = '.neurcode-ai-record';
|
|
1167
|
+
function publicAIChangeRecordPath(repoRoot, sessionId) {
|
|
1168
|
+
if (!/^[A-Za-z0-9._-]+$/.test(sessionId)) {
|
|
1169
|
+
throw new Error('AI Change Record session id is not safe for an artifact filename');
|
|
1170
|
+
}
|
|
1171
|
+
return (0, node_path_1.join)(repoRoot, PUBLIC_AI_CHANGE_RECORD_DIR, `${sessionId}.json`);
|
|
1172
|
+
}
|
|
1173
|
+
function writeJsonFile(path, value) {
|
|
1174
|
+
const dir = (0, node_path_1.dirname)(path);
|
|
1175
|
+
if (!(0, node_fs_1.existsSync)(dir))
|
|
1176
|
+
(0, node_fs_1.mkdirSync)(dir, { recursive: true });
|
|
1177
|
+
(0, node_fs_1.writeFileSync)(path, JSON.stringify(value, null, 2) + '\n', 'utf8');
|
|
1178
|
+
}
|
|
1179
|
+
function readJsonFile(path) {
|
|
1180
|
+
return JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
|
|
1181
|
+
}
|
|
1182
|
+
function extractRecordAndReceipt(value) {
|
|
1183
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1184
|
+
return { record: null, receipt: null };
|
|
1185
|
+
const obj = value;
|
|
1186
|
+
const record = obj.record && typeof obj.record === 'object' && obj.record.recordType === 'ai-change-accountability-record'
|
|
1187
|
+
? obj.record
|
|
1188
|
+
: obj.recordType === 'ai-change-accountability-record'
|
|
1189
|
+
? obj
|
|
1190
|
+
: null;
|
|
1191
|
+
const receipt = obj.receipt && typeof obj.receipt === 'object'
|
|
1192
|
+
? obj.receipt
|
|
1193
|
+
: obj.backendReceipt && typeof obj.backendReceipt === 'object'
|
|
1194
|
+
? obj.backendReceipt
|
|
1195
|
+
: obj.schemaVersion === 'neurcode.ai-change-record-receipt.v1'
|
|
1196
|
+
? obj
|
|
1197
|
+
: null;
|
|
1198
|
+
return { record, receipt };
|
|
1199
|
+
}
|
|
1200
|
+
async function exportAIChangeRecordForCli(options = {}) {
|
|
1201
|
+
const repoRoot = (0, v0_governance_1.resolveRepoRoot)(options.dir || process.cwd());
|
|
1202
|
+
const session = resolveAIChangeRecordSession(repoRoot, options);
|
|
1203
|
+
if (!session) {
|
|
1204
|
+
throw new Error(options.sessionId
|
|
1205
|
+
? `No local governance session found for ${options.sessionId}`
|
|
1206
|
+
: 'No local governance sessions found');
|
|
1207
|
+
}
|
|
1208
|
+
const { record, path: localPath } = (0, governance_runtime_1.writeAIChangeRecord)(repoRoot, session);
|
|
1209
|
+
let receipt = null;
|
|
1210
|
+
let verification = null;
|
|
1211
|
+
const warnings = [];
|
|
1212
|
+
let trustLevel = record.integrity.trustLevel;
|
|
1213
|
+
if (options.signed) {
|
|
1214
|
+
try {
|
|
1215
|
+
const config = (0, config_1.loadConfig)();
|
|
1216
|
+
const connection = (0, runtime_connection_1.loadRuntimeConnection)(repoRoot);
|
|
1217
|
+
const metadata = (0, runtime_connection_2.collectRuntimeRepoMetadata)(repoRoot);
|
|
1218
|
+
const client = new api_client_1.ApiClient(config);
|
|
1219
|
+
const response = await client.signAIChangeRecord({
|
|
1220
|
+
repoId: connection?.repo.id ?? null,
|
|
1221
|
+
repoKey: connection?.repo.repoKey ?? metadata.remoteHash ?? metadata.rootHash,
|
|
1222
|
+
sessionId: record.session.sessionId,
|
|
1223
|
+
recordHash: record.integrity.recordHash,
|
|
1224
|
+
recordSchemaVersion: record.schemaVersion,
|
|
1225
|
+
recordGeneratedAt: record.generatedAt,
|
|
1226
|
+
});
|
|
1227
|
+
receipt = response.receipt || null;
|
|
1228
|
+
verification = response.verification || null;
|
|
1229
|
+
trustLevel = String(verification?.trustLevel || (response.ok ? 'backend_signed_verified' : 'backend_signed_invalid'));
|
|
1230
|
+
if (!response.ok) {
|
|
1231
|
+
warnings.push('Backend signing returned a non-valid verification result; exported as signed evidence needing review.');
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
catch (error) {
|
|
1235
|
+
warnings.push(`Backend signing unavailable; exported self-attested record only: ${error instanceof Error ? error.message : String(error)}`);
|
|
1236
|
+
trustLevel = 'self_attested';
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
const envelope = {
|
|
1240
|
+
schemaVersion: 'neurcode.ai-change-record-export.v1',
|
|
1241
|
+
generatedAt: new Date().toISOString(),
|
|
1242
|
+
trustLevel,
|
|
1243
|
+
record,
|
|
1244
|
+
...(receipt ? { receipt } : {}),
|
|
1245
|
+
...(verification ? { verification } : {}),
|
|
1246
|
+
warnings,
|
|
1247
|
+
privacy: {
|
|
1248
|
+
sourceUploaded: false,
|
|
1249
|
+
sourceFree: true,
|
|
1250
|
+
excludes: ['source code', 'diff hunks', 'patch bodies', 'raw prompts', 'secrets', 'raw file contents'],
|
|
1251
|
+
},
|
|
1252
|
+
};
|
|
1253
|
+
const publicPath = options.output ? (0, node_path_1.resolve)(repoRoot, options.output) : publicAIChangeRecordPath(repoRoot, record.session.sessionId);
|
|
1254
|
+
writeJsonFile(publicPath, envelope);
|
|
1255
|
+
return {
|
|
1256
|
+
ok: true,
|
|
1257
|
+
repoRoot,
|
|
1258
|
+
sessionId: record.session.sessionId,
|
|
1259
|
+
localPath,
|
|
1260
|
+
publicPath,
|
|
1261
|
+
publicRelativePath: (0, node_path_1.relative)(repoRoot, publicPath).replace(/\\/g, '/'),
|
|
1262
|
+
recordHash: record.integrity.recordHash,
|
|
1263
|
+
trustLevel,
|
|
1264
|
+
receipt: {
|
|
1265
|
+
present: Boolean(receipt),
|
|
1266
|
+
receiptId: typeof receipt?.receiptId === 'string' ? receipt.receiptId : null,
|
|
1267
|
+
keyId: typeof receipt?.signingKeyId === 'string' ? receipt.signingKeyId : null,
|
|
1268
|
+
verificationStatus: String(verification?.trustLevel || verification?.status || (receipt ? 'backend_signed_unverified' : 'self_attested')),
|
|
1269
|
+
},
|
|
1270
|
+
warnings,
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
function verifyAIChangeRecordForCli(options = {}) {
|
|
1274
|
+
if (!options.record)
|
|
1275
|
+
throw new Error('--record is required');
|
|
1276
|
+
const recordPayload = readJsonFile((0, node_path_1.resolve)(options.record));
|
|
1277
|
+
const recordParts = extractRecordAndReceipt(recordPayload);
|
|
1278
|
+
const receiptPayload = options.receipt ? readJsonFile((0, node_path_1.resolve)(options.receipt)) : recordPayload;
|
|
1279
|
+
const receiptParts = extractRecordAndReceipt(receiptPayload);
|
|
1280
|
+
const record = recordParts.record;
|
|
1281
|
+
const receipt = receiptParts.receipt;
|
|
1282
|
+
if (!record)
|
|
1283
|
+
throw new Error('No AI Change Record found in --record JSON');
|
|
1284
|
+
if (!receipt)
|
|
1285
|
+
throw new Error('No AI Change Record receipt found; pass --receipt or provide an export envelope');
|
|
1286
|
+
const verification = (0, governance_runtime_1.verifyAIChangeRecordReceipt)({
|
|
1287
|
+
recordHash: record.integrity.recordHash,
|
|
1288
|
+
receipt,
|
|
1289
|
+
signingSecret: process.env.NEURCODE_AI_CHANGE_RECORD_SIGNING_SECRET || null,
|
|
1290
|
+
expectedSigningKeyId: process.env.NEURCODE_AI_CHANGE_RECORD_SIGNING_KEY_ID || null,
|
|
1291
|
+
});
|
|
1292
|
+
return {
|
|
1293
|
+
ok: verification.valid,
|
|
1294
|
+
recordHash: record.integrity.recordHash,
|
|
1295
|
+
receiptId: verification.receiptId,
|
|
1296
|
+
trustLevel: verification.trustLevel,
|
|
1297
|
+
verification,
|
|
1298
|
+
privacy: {
|
|
1299
|
+
sourceUploaded: false,
|
|
1300
|
+
sourceFree: true,
|
|
1301
|
+
},
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1075
1304
|
function referenceLabel(ref) {
|
|
1076
1305
|
const owner = ref.referencingSymbol
|
|
1077
1306
|
? `${ref.referencingFile}#${ref.referencingSymbol}:${ref.line}`
|
|
@@ -1101,6 +1330,8 @@ function structuralEventDetail(artifact, artifactPath, repoRoot) {
|
|
|
1101
1330
|
})),
|
|
1102
1331
|
suppressedArtifacts: artifact.suppressedArtifacts,
|
|
1103
1332
|
digest: artifact.digest,
|
|
1333
|
+
repoSymbolIndex: artifact.repoSymbolIndex,
|
|
1334
|
+
reuseFindings: artifact.reuseFindings,
|
|
1104
1335
|
consequenceUnderstanding: artifact.consequenceUnderstanding,
|
|
1105
1336
|
planAlignment: artifact.planAlignment,
|
|
1106
1337
|
boundaryImpact: artifact.boundaryImpact,
|
|
@@ -1172,6 +1403,16 @@ function renderStructuralUnderstanding(artifact, artifactPath, repoRoot) {
|
|
|
1172
1403
|
}
|
|
1173
1404
|
}
|
|
1174
1405
|
}
|
|
1406
|
+
if (artifact.reuseFindings.length > 0) {
|
|
1407
|
+
console.log('');
|
|
1408
|
+
console.log(chalk.bold('Reuse governance advisories'));
|
|
1409
|
+
console.log(chalk.dim(` ${artifact.reuseFindings.length} advisory finding${artifact.reuseFindings.length === 1 ? '' : 's'} from ` +
|
|
1410
|
+
`${artifact.repoSymbolIndex.indexedSymbolCount} indexed TS/JS symbol${artifact.repoSymbolIndex.indexedSymbolCount === 1 ? '' : 's'}.`));
|
|
1411
|
+
for (const finding of artifact.reuseFindings.slice(0, 8)) {
|
|
1412
|
+
console.log(chalk.dim(` ${finding.changed.file}#${finding.changed.name} -> ${finding.existing.file}#${finding.existing.name}` +
|
|
1413
|
+
` · ${finding.matchType} · ${finding.confidence}`));
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1175
1416
|
if (artifact.digest.topReferences.length > 0 || artifact.digest.topSymbols.length > 0) {
|
|
1176
1417
|
console.log('');
|
|
1177
1418
|
console.log(chalk.bold('Structural digest'));
|