snipara-companion 2.0.5 → 2.0.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/README.md CHANGED
@@ -724,6 +724,12 @@ snipara-companion run \
724
724
  package-surface review, verification plan, and final Judgment Card. Review-only
725
725
  guard findings can be acknowledged with the printed guard action card command;
726
726
  blocking conflicts still make the release judgment non-proceedable.
727
+ When a served judgment id is available, add `--served-judgment-id` so `run` can
728
+ write first-party Advisor Influence receipts for recommendations that visibly
729
+ change the plan. The receipt payload includes stable skip/record counts,
730
+ bounded automation metadata, and observed verification evidence from guard,
731
+ package review, and policy-gate results without treating those checks as
732
+ outcome proof.
727
733
 
728
734
  For the full Project Intelligence and Continuity Layer roadmap, scaffold the
729
735
  built-in managed workflow plan:
package/dist/index.d.ts CHANGED
@@ -2143,17 +2143,24 @@ interface ProjectRunPackageReview {
2143
2143
  }
2144
2144
  interface ProjectRunAdvisorReceiptWrite {
2145
2145
  advisorRecommendationId: string;
2146
- status: "recorded" | "error";
2146
+ status: "recorded" | "skipped" | "error";
2147
+ agentDecision?: AdvisorInfluenceAgentDecision;
2148
+ changedBecauseOfRecommendation?: boolean;
2147
2149
  result?: RecordAdvisorInfluenceReceiptResult;
2150
+ reason?: ProjectRunAdvisorReceiptSkipReason;
2148
2151
  error?: string;
2149
2152
  }
2153
+ type ProjectRunAdvisorReceiptSkipReason = "explicitly_skipped" | "no_advisor_recommendations" | "missing_served_judgment_id" | "no_plan_adaptation" | "write_limit_exceeded";
2150
2154
  interface ProjectRunAdvisorReceiptCapture {
2151
2155
  status: "skipped" | "recorded" | "partial" | "error";
2152
2156
  servedJudgmentId?: string;
2157
+ totalRecommendationCount: number;
2158
+ eligibleCount: number;
2153
2159
  attemptedCount: number;
2154
2160
  recordedCount: number;
2161
+ skippedCount: number;
2155
2162
  writes: ProjectRunAdvisorReceiptWrite[];
2156
- reason?: string;
2163
+ reason?: ProjectRunAdvisorReceiptSkipReason;
2157
2164
  }
2158
2165
  interface ProjectIntelligenceRunResult {
2159
2166
  version: "project-intelligence.production-run.v1";
package/dist/index.js CHANGED
@@ -11945,6 +11945,7 @@ function formatPolicyGateDecision(gateDecision) {
11945
11945
  // src/commands/run.ts
11946
11946
  var GUARD_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
11947
11947
  var RAW_OUTPUT_PREVIEW_BYTES = 64e3;
11948
+ var ADVISOR_RECEIPT_WRITE_LIMIT = 6;
11948
11949
  function normalizeStringList2(values) {
11949
11950
  return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))];
11950
11951
  }
@@ -12036,6 +12037,21 @@ function advisorReceiptDecision(recommendation, judgmentCard) {
12036
12037
  }
12037
12038
  return "modified";
12038
12039
  }
12040
+ function advisorReceiptChangedBecauseOfRecommendation(args) {
12041
+ if (args.recommendation.severity === "block" && args.judgmentCard.canProceed === "block") {
12042
+ return true;
12043
+ }
12044
+ if (args.recommendation.severity === "risk") {
12045
+ return true;
12046
+ }
12047
+ if (args.recommendation.expectedBehaviorChange?.trim()) {
12048
+ return true;
12049
+ }
12050
+ if (args.recommendation.recommendedVerification.length > 0) {
12051
+ return true;
12052
+ }
12053
+ return args.judgmentCard.requiredActions.length > 0;
12054
+ }
12039
12055
  function advisorReceiptBehaviorChange(recommendation, judgmentCard) {
12040
12056
  const verification = recommendation.recommendedVerification.slice(0, 3).join("; ");
12041
12057
  const mode = recommendation.severity === "block" || recommendation.severity === "risk" ? "required action" : "advisory action";
@@ -12087,75 +12103,202 @@ function advisorReceiptMetadata(args) {
12087
12103
  toolActions,
12088
12104
  humanOverride: null,
12089
12105
  judgmentState: args.judgmentCard.state,
12090
- canProceed: args.judgmentCard.canProceed
12106
+ canProceed: args.judgmentCard.canProceed,
12107
+ verificationEvidence: args.verificationEvidence,
12108
+ verificationBackfill: {
12109
+ version: "advisor-receipt-verification-backfill-v1",
12110
+ executedCount: args.verificationEvidence.filter((item) => item.status !== "skipped").length,
12111
+ skippedCount: args.verificationEvidence.filter((item) => item.status === "skipped").length,
12112
+ caveat: "Verification evidence records commands or gates observed by this run; it is not outcome proof."
12113
+ },
12114
+ receiptAutomation: {
12115
+ version: "first-party-advisor-receipt-automation-v1",
12116
+ trigger: "snipara-companion run",
12117
+ selectedRecommendationRank: args.recommendationIndex + 1,
12118
+ totalRecommendations: args.totalRecommendations,
12119
+ writeLimit: ADVISOR_RECEIPT_WRITE_LIMIT,
12120
+ skipReason: null,
12121
+ reason: "served judgment id and plan adaptation were present"
12122
+ }
12091
12123
  };
12092
12124
  }
12125
+ function skippedAdvisorReceiptWrite(recommendation, reason, agentDecision, changedBecauseOfRecommendation) {
12126
+ return {
12127
+ advisorRecommendationId: recommendation.id,
12128
+ status: "skipped",
12129
+ ...agentDecision ? { agentDecision } : {},
12130
+ ...changedBecauseOfRecommendation !== void 0 ? { changedBecauseOfRecommendation } : {},
12131
+ reason
12132
+ };
12133
+ }
12134
+ function advisorReceiptCaptureStatus(args) {
12135
+ if (args.eligibleCount === 0) return "skipped";
12136
+ if (args.recordedCount === args.eligibleCount && args.errorCount === 0 && args.skippedCount === 0) {
12137
+ return "recorded";
12138
+ }
12139
+ if (args.recordedCount > 0) return "partial";
12140
+ if (args.errorCount > 0) return "error";
12141
+ return "skipped";
12142
+ }
12143
+ function verificationEvidenceFromRun(args) {
12144
+ const evidence = [];
12145
+ if (args.guard) {
12146
+ evidence.push({
12147
+ source: "collaboration_guard",
12148
+ label: "Collaboration guard",
12149
+ status: args.guard.status === 0 ? "passed" : "failed",
12150
+ command: args.guard.command,
12151
+ exitCode: args.guard.status,
12152
+ detail: args.guard.status === 0 ? "Pre-deploy collaboration guard passed or only review-only warnings were acknowledged." : args.guard.error ?? args.guard.stderr.trim() ?? `Guard exited ${args.guard.status}.`
12153
+ });
12154
+ }
12155
+ if (args.packageReview) {
12156
+ evidence.push({
12157
+ source: "package_review",
12158
+ label: "Package surface review",
12159
+ status: args.packageReview.status === "ok" ? "passed" : args.packageReview.status === "skipped" ? "skipped" : "failed",
12160
+ command: args.packageReview.command,
12161
+ detail: args.packageReview.status === "ok" ? "npm package metadata was read successfully." : args.packageReview.error ?? `Package review ${args.packageReview.status}.`
12162
+ });
12163
+ }
12164
+ if (args.policyGates) {
12165
+ evidence.push({
12166
+ source: "policy_gates",
12167
+ label: "Policy gates",
12168
+ status: args.policyGates.summary.block > 0 ? "failed" : args.policyGates.summary.requiredAction > 0 ? "warning" : "passed",
12169
+ detail: `Strongest policy gate: ${args.policyGates.summary.strongestSeverity}; advisory ${args.policyGates.summary.advisory}, required ${args.policyGates.summary.requiredAction}, block ${args.policyGates.summary.block}.`
12170
+ });
12171
+ }
12172
+ return evidence;
12173
+ }
12174
+ function verificationExecutedFromEvidence(evidence) {
12175
+ return evidence.filter((item) => item.status !== "skipped").map(
12176
+ (item) => item.command ? `${item.label}: ${item.command} (${item.status})` : `${item.label}: ${item.status}`
12177
+ );
12178
+ }
12093
12179
  async function recordFirstPartyAdvisorReceipts(args) {
12180
+ const allRecommendations = args.judgmentCard.advisorRecommendations;
12094
12181
  if (args.options.skipAdvisorReceipts) {
12095
12182
  return {
12096
12183
  status: "skipped",
12184
+ totalRecommendationCount: allRecommendations.length,
12185
+ eligibleCount: 0,
12097
12186
  attemptedCount: 0,
12098
12187
  recordedCount: 0,
12188
+ skippedCount: allRecommendations.length,
12099
12189
  writes: [],
12100
- reason: "advisor receipt capture was explicitly skipped"
12190
+ reason: "explicitly_skipped"
12101
12191
  };
12102
12192
  }
12103
- if (args.judgmentCard.advisorRecommendations.length === 0) {
12104
- return void 0;
12193
+ if (allRecommendations.length === 0) {
12194
+ return {
12195
+ status: "skipped",
12196
+ totalRecommendationCount: 0,
12197
+ eligibleCount: 0,
12198
+ attemptedCount: 0,
12199
+ recordedCount: 0,
12200
+ skippedCount: 0,
12201
+ writes: [],
12202
+ reason: "no_advisor_recommendations"
12203
+ };
12105
12204
  }
12106
12205
  const servedJudgmentId = servedJudgmentIdForRun(args.options, args.brief);
12107
12206
  if (!servedJudgmentId) {
12207
+ const writes2 = allRecommendations.slice(0, ADVISOR_RECEIPT_WRITE_LIMIT).map(
12208
+ (recommendation) => skippedAdvisorReceiptWrite(recommendation, "missing_served_judgment_id")
12209
+ );
12108
12210
  return {
12109
12211
  status: "skipped",
12212
+ totalRecommendationCount: allRecommendations.length,
12213
+ eligibleCount: 0,
12110
12214
  attemptedCount: 0,
12111
12215
  recordedCount: 0,
12112
- writes: [],
12113
- reason: "no served judgment id was available for first-party advisor receipts"
12216
+ skippedCount: writes2.length,
12217
+ writes: writes2,
12218
+ reason: "missing_served_judgment_id"
12114
12219
  };
12115
12220
  }
12116
12221
  const client = createClient(1e4);
12117
- const recommendations = args.judgmentCard.advisorRecommendations.slice(0, 6);
12118
- const writes = await Promise.all(
12119
- recommendations.map(async (recommendation) => {
12120
- try {
12121
- const agentDecision = advisorReceiptDecision(recommendation, args.judgmentCard);
12122
- const behaviorChange = advisorReceiptBehaviorChange(recommendation, args.judgmentCard);
12123
- const result = await client.recordAdvisorInfluenceReceipt({
12124
- servedJudgmentId,
12125
- recommendation: advisorReceiptRecommendation(recommendation),
12126
- agentDecision,
12127
- behaviorChange,
12128
- verificationExecuted: [],
12129
- outcomeLinkStatus: "pending",
12130
- metadata: advisorReceiptMetadata({
12131
- options: args.options,
12132
- brief: args.brief,
12133
- judgmentCard: args.judgmentCard,
12222
+ const verificationEvidence = args.verificationEvidence ?? [];
12223
+ const verificationExecuted = verificationExecutedFromEvidence(verificationEvidence);
12224
+ const selectedRecommendations = allRecommendations.slice(0, ADVISOR_RECEIPT_WRITE_LIMIT);
12225
+ const overflowWrites = allRecommendations.slice(ADVISOR_RECEIPT_WRITE_LIMIT).map((recommendation) => skippedAdvisorReceiptWrite(recommendation, "write_limit_exceeded"));
12226
+ const writes = [
12227
+ ...await Promise.all(
12228
+ selectedRecommendations.map(
12229
+ async (recommendation, recommendationIndex) => {
12230
+ const agentDecision = advisorReceiptDecision(recommendation, args.judgmentCard);
12231
+ const changedBecauseOfRecommendation = advisorReceiptChangedBecauseOfRecommendation({
12134
12232
  recommendation,
12135
- agentDecision,
12136
- behaviorChange
12137
- })
12138
- });
12139
- return {
12140
- advisorRecommendationId: recommendation.id,
12141
- status: "recorded",
12142
- result
12143
- };
12144
- } catch (error) {
12145
- return {
12146
- advisorRecommendationId: recommendation.id,
12147
- status: "error",
12148
- error: error instanceof Error ? error.message : String(error)
12149
- };
12150
- }
12151
- })
12152
- );
12233
+ judgmentCard: args.judgmentCard
12234
+ });
12235
+ if (!changedBecauseOfRecommendation) {
12236
+ return skippedAdvisorReceiptWrite(
12237
+ recommendation,
12238
+ "no_plan_adaptation",
12239
+ agentDecision,
12240
+ false
12241
+ );
12242
+ }
12243
+ try {
12244
+ const behaviorChange = advisorReceiptBehaviorChange(recommendation, args.judgmentCard);
12245
+ const result = await client.recordAdvisorInfluenceReceipt({
12246
+ servedJudgmentId,
12247
+ recommendation: advisorReceiptRecommendation(recommendation),
12248
+ agentDecision,
12249
+ behaviorChange,
12250
+ verificationExecuted,
12251
+ outcomeLinkStatus: "pending",
12252
+ metadata: advisorReceiptMetadata({
12253
+ options: args.options,
12254
+ brief: args.brief,
12255
+ judgmentCard: args.judgmentCard,
12256
+ recommendation,
12257
+ recommendationIndex,
12258
+ totalRecommendations: allRecommendations.length,
12259
+ verificationEvidence,
12260
+ agentDecision,
12261
+ behaviorChange
12262
+ })
12263
+ });
12264
+ return {
12265
+ advisorRecommendationId: recommendation.id,
12266
+ status: "recorded",
12267
+ agentDecision,
12268
+ changedBecauseOfRecommendation,
12269
+ result
12270
+ };
12271
+ } catch (error) {
12272
+ return {
12273
+ advisorRecommendationId: recommendation.id,
12274
+ status: "error",
12275
+ agentDecision,
12276
+ changedBecauseOfRecommendation,
12277
+ error: error instanceof Error ? error.message : String(error)
12278
+ };
12279
+ }
12280
+ }
12281
+ )
12282
+ ),
12283
+ ...overflowWrites
12284
+ ];
12153
12285
  const recordedCount = writes.filter((write) => write.status === "recorded").length;
12286
+ const skippedCount = writes.filter((write) => write.status === "skipped").length;
12287
+ const errorCount = writes.filter((write) => write.status === "error").length;
12288
+ const eligibleCount = writes.filter((write) => write.status !== "skipped").length;
12154
12289
  return {
12155
- status: recordedCount === writes.length ? "recorded" : recordedCount > 0 ? "partial" : "error",
12290
+ status: advisorReceiptCaptureStatus({
12291
+ eligibleCount,
12292
+ recordedCount,
12293
+ skippedCount,
12294
+ errorCount
12295
+ }),
12156
12296
  servedJudgmentId,
12157
- attemptedCount: writes.length,
12297
+ totalRecommendationCount: allRecommendations.length,
12298
+ eligibleCount,
12299
+ attemptedCount: eligibleCount,
12158
12300
  recordedCount,
12301
+ skippedCount,
12159
12302
  writes
12160
12303
  };
12161
12304
  }
@@ -12274,11 +12417,6 @@ async function buildProjectIntelligenceRun(options) {
12274
12417
  packageReview,
12275
12418
  errors: runErrors
12276
12419
  });
12277
- const advisorReceiptCapture = await recordFirstPartyAdvisorReceipts({
12278
- options,
12279
- brief,
12280
- judgmentCard
12281
- });
12282
12420
  const policyGates = evaluateProjectPolicyGates({
12283
12421
  task: options.task,
12284
12422
  release: options.release,
@@ -12290,6 +12428,17 @@ async function buildProjectIntelligenceRun(options) {
12290
12428
  packageReview,
12291
12429
  judgmentCard
12292
12430
  });
12431
+ const verificationEvidence = verificationEvidenceFromRun({
12432
+ guard,
12433
+ packageReview,
12434
+ policyGates
12435
+ });
12436
+ const advisorReceiptCapture = await recordFirstPartyAdvisorReceipts({
12437
+ options,
12438
+ brief,
12439
+ judgmentCard,
12440
+ verificationEvidence
12441
+ });
12293
12442
  const suggestedCommands = [
12294
12443
  ...brief.suggestedCommands,
12295
12444
  ...policyGates.suggestedCommands,
@@ -12368,8 +12517,16 @@ async function projectIntelligenceRunCommand(options) {
12368
12517
  console.log(
12369
12518
  `Recorded: ${result.advisorReceiptCapture.recordedCount}/${result.advisorReceiptCapture.attemptedCount}`
12370
12519
  );
12520
+ if (result.advisorReceiptCapture.skippedCount > 0) {
12521
+ console.log(`Skipped: ${result.advisorReceiptCapture.skippedCount}`);
12522
+ }
12371
12523
  if (result.advisorReceiptCapture.reason) {
12372
- console.log(result.advisorReceiptCapture.reason);
12524
+ console.log(`Reason: ${result.advisorReceiptCapture.reason}`);
12525
+ }
12526
+ for (const write of result.advisorReceiptCapture.writes.slice(0, 4)) {
12527
+ if (write.status === "skipped" && write.reason) {
12528
+ console.log(`- skipped ${write.advisorRecommendationId}: ${write.reason}`);
12529
+ }
12373
12530
  }
12374
12531
  console.log("");
12375
12532
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snipara-companion",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Snipara Git-style companion CLI for local workflow continuity, hooks, hosted context, and Mini Snipara OSS workflows",
5
5
  "main": "dist/index.js",
6
6
  "bin": {