@remembrance-ai/opencode-plugin 0.2.3 → 0.2.5

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.
@@ -4798,8 +4798,8 @@ function parseSurfaceReleases(value) {
4798
4798
  );
4799
4799
  }
4800
4800
  function isCanonicalIsoTimestamp(value) {
4801
- const timestamp = Date.parse(value);
4802
- return Number.isFinite(timestamp) && new Date(timestamp).toISOString() === value;
4801
+ const timestamp2 = Date.parse(value);
4802
+ return Number.isFinite(timestamp2) && new Date(timestamp2).toISOString() === value;
4803
4803
  }
4804
4804
 
4805
4805
  // ../core/src/client-health-alerts.ts
@@ -9900,6 +9900,9 @@ var MAX_RSA_FACTOR_SEARCH_MODULUS = 1n << 4096n;
9900
9900
  var MAX_RSA_ARITHMETIC_WORK = 2 ** 32;
9901
9901
  var MAX_REQUEST_RSA_ARITHMETIC_WORK = 2 ** 34;
9902
9902
  var currentRedactionRequest = () => void 0;
9903
+ function trackRedactionRequests(current) {
9904
+ currentRedactionRequest = current;
9905
+ }
9903
9906
  var MIN_DETACHED_RSA_CONTINUATION_BYTES = 16;
9904
9907
  var MAX_DETACHED_RSA_CONTINUATION_READS = 1 << 20;
9905
9908
  var detachedRsaContinuationReads = /* @__PURE__ */ new WeakMap();
@@ -10506,9 +10509,137 @@ function serializedPublicRsaKeyValueIsValid2(value, metrics) {
10506
10509
  function rsaPublicNumbersArePlausible2(modulus, exponent, metrics) {
10507
10510
  return rsaPublicNumbersArePlausible(modulus, exponent, metrics);
10508
10511
  }
10512
+ function redactPayload(payload) {
10513
+ const analysis = analyzeSensitivePayload(payload);
10514
+ return redactAnalyzedPayload(payload, analysis);
10515
+ }
10516
+ function redactAnalyzedPayload(payload, analysis) {
10517
+ if (!payload || typeof payload !== "object") {
10518
+ if (typeof payload !== "string") return payload;
10519
+ const baseline = redactStringValue(payload, analysis.metrics);
10520
+ const ranges = lateStringOverlapRanges(payload, analysis.metrics);
10521
+ analysis.sensitiveMaterial ||= ranges.length > 0;
10522
+ return applyLateOverlapRanges(baseline, ranges, analysis.metrics);
10523
+ }
10524
+ const valuePlans = /* @__PURE__ */ new Map();
10525
+ const keyPlans = /* @__PURE__ */ new Map();
10526
+ const outputKeys = /* @__PURE__ */ new Map();
10527
+ const clones = analysis.graph.containers.map(
10528
+ (container) => analysis.numericPrivateContainers.has(container) ? "[redacted]" : container.kind === "array" ? new Array(container.value.length) : {}
10529
+ );
10530
+ for (const container of analysis.graph.containers) {
10531
+ if (analysis.numericPrivateContainers.has(container)) continue;
10532
+ const target = clones[container.id];
10533
+ if (container.kind === "array") {
10534
+ for (const edge of container.edges) {
10535
+ target[edge.index] = redactedEdgeValue(
10536
+ edge,
10537
+ analysis,
10538
+ clones,
10539
+ valuePlans
10540
+ );
10541
+ }
10542
+ continue;
10543
+ }
10544
+ const objectTarget = target;
10545
+ const redactedKeys = analysis.sensitiveObjectKeys.get(container.value);
10546
+ const reservedKeys = new Set(
10547
+ container.edges.filter((edge) => !redactedKeys?.has(edge.key)).map((edge) => edge.key)
10548
+ );
10549
+ const usedKeys = /* @__PURE__ */ new Set();
10550
+ const nextSuffix = /* @__PURE__ */ new Map();
10551
+ for (const edge of container.edges) {
10552
+ const keyPlan = redactedKeys?.has(edge.key) ? redactStringValue(edge.key, analysis.metrics) : unchangedStringProjection(edge.key);
10553
+ const forcedKey = redactedKeys?.has(edge.key) && !keyPlan.changed;
10554
+ keyPlans.set(edge, forcedKey ? fullyRedactedStringProjection() : keyPlan);
10555
+ const outputKey = redactedKeys?.has(edge.key) ? uniqueRedactedObjectKey(
10556
+ reservedKeys,
10557
+ usedKeys,
10558
+ nextSuffix,
10559
+ forcedKey ? "[redacted]" : keyPlan.value
10560
+ ) : edge.key;
10561
+ outputKeys.set(edge, outputKey);
10562
+ usedKeys.add(outputKey);
10563
+ const value = isSensitiveKey(edge.key) && edge.value !== null && edge.value !== void 0 ? "[redacted]" : redactedEdgeValue(edge, analysis, clones, valuePlans);
10564
+ Object.defineProperty(objectTarget, outputKey, {
10565
+ value,
10566
+ enumerable: true,
10567
+ configurable: true,
10568
+ writable: true
10569
+ });
10570
+ }
10571
+ }
10572
+ const claims = latePayloadOverlapRanges(analysis, valuePlans, keyPlans);
10573
+ for (const container of analysis.graph.containers) {
10574
+ if (analysis.numericPrivateContainers.has(container)) continue;
10575
+ const target = clones[container.id];
10576
+ const renamed = /* @__PURE__ */ new Map();
10577
+ for (const edge of container.edges) {
10578
+ const valuePlan = valuePlans.get(edge);
10579
+ const valueRanges = edge.valueToken && claims.get(edge.valueToken);
10580
+ if (valuePlan && valueRanges) {
10581
+ const key = container.kind === "array" ? edge.index : outputKeys.get(edge);
10582
+ target[key] = applyLateOverlapRanges(
10583
+ valuePlan,
10584
+ valueRanges,
10585
+ analysis.metrics
10586
+ );
10587
+ }
10588
+ const keyPlan = keyPlans.get(edge);
10589
+ const keyRanges = edge.keyToken && claims.get(edge.keyToken);
10590
+ if (keyPlan && keyRanges) {
10591
+ const oldKey = outputKeys.get(edge);
10592
+ const candidate = applyLateOverlapRanges(
10593
+ { ...keyPlan, value: oldKey },
10594
+ keyRanges,
10595
+ analysis.metrics
10596
+ );
10597
+ if (candidate !== oldKey) renamed.set(edge, candidate);
10598
+ }
10599
+ }
10600
+ if (renamed.size === 0) continue;
10601
+ const reserved = new Set(
10602
+ container.edges.filter((edge) => !renamed.has(edge)).map((edge) => outputKeys.get(edge))
10603
+ );
10604
+ const used = /* @__PURE__ */ new Set();
10605
+ const suffixes = /* @__PURE__ */ new Map();
10606
+ const entries = container.edges.map((edge) => {
10607
+ const oldKey = outputKeys.get(edge);
10608
+ const candidate = renamed.get(edge);
10609
+ const key = candidate === void 0 ? oldKey : uniqueRedactedObjectKey(reserved, used, suffixes, candidate);
10610
+ used.add(key);
10611
+ return { oldKey, key, value: target[oldKey] };
10612
+ });
10613
+ for (const { oldKey } of entries) delete target[oldKey];
10614
+ for (const { key, value } of entries)
10615
+ Object.defineProperty(target, key, {
10616
+ value,
10617
+ enumerable: true,
10618
+ configurable: true,
10619
+ writable: true
10620
+ });
10621
+ }
10622
+ return clones[analysis.graph.root.id];
10623
+ }
10509
10624
  function containsSensitiveMaterial(payload) {
10510
10625
  return inspectPayloadForSensitiveMaterial(payload).sensitiveMaterial;
10511
10626
  }
10627
+ function redactedEdgeValue(edge, analysis, clones, plans) {
10628
+ if (edge.child) return clones[edge.child.id];
10629
+ if (typeof edge.value !== "string") return edge.value;
10630
+ const ranges = analysis.privateKeyBodyRanges.get(edge.owner.value)?.get(edge.key);
10631
+ const native = ranges ? projectedTextRanges(edge.value, ranges, analysis.metrics) : unchangedStringProjection(edge.value);
10632
+ const lexical = redactStringValue(native.value, analysis.metrics);
10633
+ plans.set(edge, {
10634
+ ...lexical,
10635
+ retained: composeRetainedSourceSpans(
10636
+ native.retained,
10637
+ lexical.retained,
10638
+ analysis.metrics
10639
+ )
10640
+ });
10641
+ return lexical.value;
10642
+ }
10512
10643
  function inspectPayloadForSensitiveMaterial(payload) {
10513
10644
  const analysis = analyzeSensitivePayload(payload);
10514
10645
  latePayloadOverlapRanges(analysis);
@@ -12058,7 +12189,7 @@ function findIndependentlyEncodedPrivateKeyFrameProof(tokens, metrics) {
12058
12189
  const recoverableLength = recoverableProof?.length ?? null;
12059
12190
  const length = completeLength ?? recoverableLength;
12060
12191
  if (length === null) continue;
12061
- const continuation = recoverableProof?.basis === "factors" ? independentlyEncodedRsaCrtContinuationRanges(
12192
+ const continuation2 = recoverableProof?.basis === "factors" ? independentlyEncodedRsaCrtContinuationRanges(
12062
12193
  tokens,
12063
12194
  frames,
12064
12195
  bytes,
@@ -12073,10 +12204,10 @@ function findIndependentlyEncodedPrivateKeyFrameProof(tokens, metrics) {
12073
12204
  bytes,
12074
12205
  encoding,
12075
12206
  frames,
12076
- continuationRanges: continuation.ranges,
12207
+ continuationRanges: continuation2.ranges,
12077
12208
  start: frame.start,
12078
12209
  end: frame.start + length,
12079
- ambiguous: continuation.ambiguous,
12210
+ ambiguous: continuation2.ambiguous,
12080
12211
  complete: completeLength !== null,
12081
12212
  factorBacked: recoverableProof?.basis === "factors",
12082
12213
  recoverable: completeLength === null
@@ -14713,19 +14844,19 @@ function recordCryptographicMatchedTerminalOwnership(tokens, assessment, metrics
14713
14844
  }
14714
14845
  function matchedTerminalSourcePieceRanges(tokens, assessment) {
14715
14846
  const sourceStart = assessment.sourcePieceRanges[0].start;
14716
- const continuation = assessment.rsaCrtContinuations.filter(
14847
+ const continuation2 = assessment.rsaCrtContinuations.filter(
14717
14848
  (candidate) => candidate.start === sourceStart && candidate.status === "match" && candidate.mismatchAt === null
14718
14849
  ).sort((left, right) => right.matchedEnd - left.matchedEnd)[0];
14719
- if (!continuation) return [];
14850
+ if (!continuation2) return [];
14720
14851
  const ranges = [];
14721
14852
  for (const [pieceIndex, token] of tokens.entries()) {
14722
14853
  const source = assessment.sourcePieceRanges[pieceIndex];
14723
- if (source.end <= continuation.matchedEnd) {
14854
+ if (source.end <= continuation2.matchedEnd) {
14724
14855
  ranges.push({ pieceIndex, start: 0, end: token.value.length });
14725
14856
  continue;
14726
14857
  }
14727
- if (source.start >= continuation.matchedEnd) continue;
14728
- const matchedLength = continuation.matchedEnd - source.start;
14858
+ if (source.start >= continuation2.matchedEnd) continue;
14859
+ const matchedLength = continuation2.matchedEnd - source.start;
14729
14860
  if (matchedLength > 0 && /^=+$/u.test(token.value.slice(matchedLength))) {
14730
14861
  ranges.push({ pieceIndex, start: 0, end: token.value.length });
14731
14862
  }
@@ -15604,13 +15735,13 @@ function assessEncodedPieceSequence(pieces, textOf, metrics, requireBoundedRecov
15604
15735
  (completeRange) => completeRange.start < end && start < completeRange.end
15605
15736
  );
15606
15737
  const authenticatedFactorRange = scanned.rsaCrtContinuations.some(
15607
- (continuation) => {
15608
- const ownedEnd = Math.min(end, continuation.matchedEnd);
15609
- if (continuation.start >= ownedEnd || start >= continuation.matchedEnd) {
15738
+ (continuation2) => {
15739
+ const ownedEnd = Math.min(end, continuation2.matchedEnd);
15740
+ if (continuation2.start >= ownedEnd || start >= continuation2.matchedEnd) {
15610
15741
  return false;
15611
15742
  }
15612
- if (position.start < continuation.factorEnd) return true;
15613
- return ownedEnd - Math.max(position.start, continuation.factorEnd) >= continuation.minimumAuthenticatedCharacters;
15743
+ if (position.start < continuation2.factorEnd) return true;
15744
+ return ownedEnd - Math.max(position.start, continuation2.factorEnd) >= continuation2.minimumAuthenticatedCharacters;
15614
15745
  }
15615
15746
  );
15616
15747
  if (!authoritativeComplete2 && !authenticatedFactorRange) continue;
@@ -15774,7 +15905,7 @@ function encodedAssessmentHasMatchedCrtContinuationThroughEnd(assessment, pieceC
15774
15905
  const sourceStart = assessment.sourcePieceRanges[0].start;
15775
15906
  const sourceEnd = assessment.sourcePieceRanges[pieceCount - 1].end;
15776
15907
  return assessment.rsaCrtContinuations.some(
15777
- (continuation) => continuation.start === sourceStart && continuation.status === "match" && continuation.mismatchAt === null && continuation.matchedEnd <= sourceEnd && sourceEnd - continuation.matchedEnd <= MAX_ADJACENT_ENCODED_PREFIX_CHARACTERS
15908
+ (continuation2) => continuation2.start === sourceStart && continuation2.status === "match" && continuation2.mismatchAt === null && continuation2.matchedEnd <= sourceEnd && sourceEnd - continuation2.matchedEnd <= MAX_ADJACENT_ENCODED_PREFIX_CHARACTERS
15778
15909
  );
15779
15910
  }
15780
15911
  function encodedAssessmentOwnsEverySourcePiece(assessment, pieceCount) {
@@ -15796,7 +15927,7 @@ function encodedAssessmentOwnsEverySourcePiece(assessment, pieceCount) {
15796
15927
  }
15797
15928
  const terminalSource = assessment.sourcePieceRanges[terminalIndex];
15798
15929
  return assessment.rsaCrtContinuations.some(
15799
- (continuation) => continuation.status === "match" && continuation.mismatchAt === null && continuation.factorEnd < terminalSource.end && continuation.matchedEnd === terminalSource.end
15930
+ (continuation2) => continuation2.status === "match" && continuation2.mismatchAt === null && continuation2.factorEnd < terminalSource.end && continuation2.matchedEnd === terminalSource.end
15800
15931
  );
15801
15932
  }
15802
15933
  function encodedAssessmentAllowsFactorOmission(assessment, pieceIndex) {
@@ -15807,11 +15938,11 @@ function encodedAssessmentAllowsFactorOmission(assessment, pieceIndex) {
15807
15938
  )) {
15808
15939
  return false;
15809
15940
  }
15810
- return assessment.rsaCrtContinuations.every((continuation) => {
15811
- if (piece.end <= continuation.start || piece.start >= continuation.end) {
15941
+ return assessment.rsaCrtContinuations.every((continuation2) => {
15942
+ if (piece.end <= continuation2.start || piece.start >= continuation2.end) {
15812
15943
  return true;
15813
15944
  }
15814
- return continuation.mismatchAt !== null && continuation.mismatchAt < piece.end && continuation.matchedEnd <= piece.start;
15945
+ return continuation2.mismatchAt !== null && continuation2.mismatchAt < piece.end && continuation2.matchedEnd <= piece.start;
15815
15946
  });
15816
15947
  }
15817
15948
  function encodedAssessmentAllowsRecognizableFactorOmission(assessment, pieceIndex) {
@@ -15819,11 +15950,11 @@ function encodedAssessmentAllowsRecognizableFactorOmission(assessment, pieceInde
15819
15950
  return true;
15820
15951
  }
15821
15952
  const piece = assessment.sourcePieceRanges[pieceIndex];
15822
- return assessment.rsaCrtContinuations.every((continuation) => {
15823
- if (piece.end <= continuation.start || piece.start >= continuation.end) {
15953
+ return assessment.rsaCrtContinuations.every((continuation2) => {
15954
+ if (piece.end <= continuation2.start || piece.start >= continuation2.end) {
15824
15955
  return true;
15825
15956
  }
15826
- return continuation.factorEnd <= piece.start && (continuation.matchedEnd <= piece.start || continuation.mismatchAt !== null && continuation.mismatchAt < piece.end);
15957
+ return continuation2.factorEnd <= piece.start && (continuation2.matchedEnd <= piece.start || continuation2.mismatchAt !== null && continuation2.mismatchAt < piece.end);
15827
15958
  });
15828
15959
  }
15829
15960
  function encodedAssessmentStartsAtSource(assessment) {
@@ -17368,7 +17499,7 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
17368
17499
  if (recoverableProof?.basis === "factors") {
17369
17500
  const sourceStart = offsets ? offsets[cursor] : cursor;
17370
17501
  const sourceEnd = offsets ? offsets[segment.end - 1] + 1 : segment.end;
17371
- const continuation = rsaPrivateKeyCrtContinuationConsistency(
17502
+ const continuation2 = rsaPrivateKeyCrtContinuationConsistency(
17372
17503
  recoverableProof,
17373
17504
  text,
17374
17505
  cursor,
@@ -17385,9 +17516,9 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
17385
17516
  bitOffset
17386
17517
  );
17387
17518
  const sourceFactorEnd = offsets ? offsets[exactEnd - 1] + 1 : exactEnd;
17388
- const sourceMatchedEnd = offsets ? offsets[continuation.matchedEnd - 1] + 1 : continuation.matchedEnd;
17519
+ const sourceMatchedEnd = offsets ? offsets[continuation2.matchedEnd - 1] + 1 : continuation2.matchedEnd;
17389
17520
  const minimumAuthenticatedCharacters = minimumRsaCrtContinuationSourceCharacters(framing);
17390
- const authenticatedMatchedEnd = continuation.matchedEnd - exactEnd >= minimumAuthenticatedCharacters ? continuation.matchedEnd : exactEnd;
17521
+ const authenticatedMatchedEnd = continuation2.matchedEnd - exactEnd >= minimumAuthenticatedCharacters ? continuation2.matchedEnd : exactEnd;
17391
17522
  matchedFactorEnd = Math.max(exactEnd, authenticatedMatchedEnd);
17392
17523
  rsaCrtContinuations.push({
17393
17524
  start: sourceStart,
@@ -17395,8 +17526,8 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
17395
17526
  factorEnd: sourceFactorEnd,
17396
17527
  matchedEnd: sourceMatchedEnd,
17397
17528
  minimumAuthenticatedCharacters,
17398
- mismatchAt: continuation.mismatchAt === null ? null : offsets ? offsets[continuation.mismatchAt] : continuation.mismatchAt,
17399
- status: continuation.status
17529
+ mismatchAt: continuation2.mismatchAt === null ? null : offsets ? offsets[continuation2.mismatchAt] : continuation2.mismatchAt,
17530
+ status: continuation2.status
17400
17531
  });
17401
17532
  }
17402
17533
  const exactFactorEnd = recoverableProof?.basis === "factors" && recoverableLength !== null ? encodedPrivateKeyInteriorEnd(
@@ -20513,6 +20644,16 @@ function isShortPemBoundaryFragment(value) {
20513
20644
  if (isCompletePemBoundary(trimmed)) return true;
20514
20645
  return trimmed.length <= 32 && /^-{5}(?:BEGIN|END)[A-Z0-9_-]{0,18}$/iu.test(trimmed) && exactPrivateKeyMarker2(trimmed) === null;
20515
20646
  }
20647
+ function uniqueRedactedObjectKey(reserved, used, nextSuffixByBase, candidate) {
20648
+ const base = candidate === "[redacted]" ? "[redacted-key]" : candidate;
20649
+ if (!reserved.has(base) && !used.has(base)) return base;
20650
+ let suffix = nextSuffixByBase.get(base) ?? 2;
20651
+ while (reserved.has(`${base}-${suffix}`) || used.has(`${base}-${suffix}`)) {
20652
+ suffix += 1;
20653
+ }
20654
+ nextSuffixByBase.set(base, suffix + 1);
20655
+ return `${base}-${suffix}`;
20656
+ }
20516
20657
  function createRedactionWorkMetrics() {
20517
20658
  return {
20518
20659
  nodesVisited: 0,
@@ -21891,7 +22032,7 @@ function strictIndependentPrivateSourceRanges(scope, metrics, document) {
21891
22032
  );
21892
22033
  claims.push({ token: frame.token, ...range });
21893
22034
  }
21894
- const continuation = complete ? completeRsaPrivateKeyCopies(
22035
+ const continuation2 = complete ? completeRsaPrivateKeyCopies(
21895
22036
  scope,
21896
22037
  frames,
21897
22038
  bytes,
@@ -21912,16 +22053,16 @@ function strictIndependentPrivateSourceRanges(scope, metrics, document) {
21912
22053
  tokenIndexes,
21913
22054
  metrics
21914
22055
  ) : completion;
21915
- if (!continuation) continue;
21916
- if (continuation.ambiguous || detachedRsaContinuationReadsSpent(metrics) > MAX_DETACHED_RSA_CONTINUATION_READS) {
22056
+ if (!continuation2) continue;
22057
+ if (continuation2.ambiguous || detachedRsaContinuationReadsSpent(metrics) > MAX_DETACHED_RSA_CONTINUATION_READS) {
21917
22058
  for (const frame of frames) {
21918
22059
  metrics.ownershipSteps += 1;
21919
22060
  claims.push(wholeTokenSourceRange(frame.token));
21920
22061
  }
21921
- claims.push(...continuation.closed);
21922
- if (continuation.ambiguous) continue;
22062
+ claims.push(...continuation2.closed);
22063
+ if (continuation2.ambiguous) continue;
21923
22064
  }
21924
- for (const range of continuation.ranges) {
22065
+ for (const range of continuation2.ranges) {
21925
22066
  if (range.token === detached) continue;
21926
22067
  claims.push(range);
21927
22068
  }
@@ -22612,6 +22753,9 @@ function unchangedStringProjection(value) {
22612
22753
  retained: value.length ? [{ start: 0, end: value.length, outputStart: 0 }] : []
22613
22754
  };
22614
22755
  }
22756
+ function fullyRedactedStringProjection() {
22757
+ return { value: "[redacted]", changed: true, retained: [] };
22758
+ }
22615
22759
  function appendRetainedSourceSpan(spans, span) {
22616
22760
  spans.push(span);
22617
22761
  }
@@ -22651,6 +22795,67 @@ function retainedAfterRedactionRanges(retained, ranges, metrics, replacementLeng
22651
22795
  }
22652
22796
  return result;
22653
22797
  }
22798
+ function projectedTextRanges(value, ranges, metrics) {
22799
+ if (ranges.length === 1 && ranges[0].start === 0 && ranges[0].end === value.length) {
22800
+ return fullyRedactedStringProjection();
22801
+ }
22802
+ const original = unchangedStringProjection(value);
22803
+ return {
22804
+ value: redactTextRanges(value, ranges),
22805
+ changed: ranges.length > 0,
22806
+ retained: retainedAfterRedactionRanges(original.retained, ranges, metrics)
22807
+ };
22808
+ }
22809
+ function composeRetainedSourceSpans(first, second, metrics) {
22810
+ if (first.length === 0 || second.length === 0) return [];
22811
+ const result = [];
22812
+ let leftIndex = 0;
22813
+ let rightIndex = 0;
22814
+ while (leftIndex < first.length && rightIndex < second.length) {
22815
+ metrics.ownershipSteps += 1;
22816
+ const left = first[leftIndex];
22817
+ const right = second[rightIndex];
22818
+ const leftEnd = left.outputStart + left.end - left.start;
22819
+ const start = Math.max(left.outputStart, right.start);
22820
+ const end = Math.min(leftEnd, right.end);
22821
+ if (start < end)
22822
+ appendRetainedSourceSpan(result, {
22823
+ start: left.start + start - left.outputStart,
22824
+ end: left.start + end - left.outputStart,
22825
+ outputStart: right.outputStart + start - right.start
22826
+ });
22827
+ if (leftEnd <= right.end) leftIndex += 1;
22828
+ if (right.end <= leftEnd) rightIndex += 1;
22829
+ }
22830
+ return result;
22831
+ }
22832
+ function applyLateOverlapRanges(baseline, claims, metrics) {
22833
+ if (claims.length === 0 || baseline.retained.length === 0)
22834
+ return baseline.value;
22835
+ const projected = [];
22836
+ let claimIndex = 0;
22837
+ for (const [index, span] of baseline.retained.entries()) {
22838
+ metrics.ownershipSteps += 1;
22839
+ while (claimIndex < claims.length && claims[claimIndex].end <= span.start) {
22840
+ metrics.ownershipSteps += 1;
22841
+ claimIndex += 1;
22842
+ }
22843
+ let current = claimIndex;
22844
+ while (current < claims.length && claims[current].start < span.end) {
22845
+ metrics.ownershipSteps += 1;
22846
+ const claim = claims[current++];
22847
+ const start = Math.max(span.start, claim.start);
22848
+ const end = Math.min(span.end, claim.end);
22849
+ const previous = baseline.retained[index - 1];
22850
+ const next = baseline.retained[index + 1];
22851
+ projected.push({
22852
+ start: start === span.start ? previous ? previous.outputStart + previous.end - previous.start : 0 : span.outputStart + start - span.start,
22853
+ end: end === span.end ? next ? next.outputStart : baseline.value.length : span.outputStart + end - span.start
22854
+ });
22855
+ }
22856
+ }
22857
+ return projected.length === 0 ? baseline.value : redactTextRanges(baseline.value, mergeOrderedTextRanges([], projected));
22858
+ }
22654
22859
  function latePayloadOverlapRanges(analysis, valuePlans, keyPlans) {
22655
22860
  const { graph, metrics } = analysis;
22656
22861
  const claims = /* @__PURE__ */ new Map();
@@ -23446,7 +23651,8 @@ var remembrance_mcp_consent_lanes_default = {
23446
23651
  propose_skill_idea: "skill_candidate",
23447
23652
  submit_suggestion: "skill_suggestion",
23448
23653
  submit_resource: "resource_submission",
23449
- submit_resource_review: "resource_review"
23654
+ submit_resource_review: "resource_review",
23655
+ repair_review_draft: "admin_review_repair"
23450
23656
  };
23451
23657
 
23452
23658
  // ../core/src/remembrance-mcp-policy.ts
@@ -23487,6 +23693,10 @@ var REMEMBRANCE_MCP_OPTIONAL_SHARED_CONTRIBUTION_TOOLS = Object.freeze(
23487
23693
  "register_agent_key"
23488
23694
  ]
23489
23695
  );
23696
+ var REMEMBRANCE_MCP_OPTIONAL_ADMIN_REVIEW_TOOLS = Object.freeze([
23697
+ "get_review_comparison",
23698
+ "repair_review_draft"
23699
+ ]);
23490
23700
  var REMEMBRANCE_MCP_LOCAL_ONLY_TOOLS = Object.freeze([
23491
23701
  "bootstrap_agent_identity",
23492
23702
  "acknowledge_feedback_denial",
@@ -23526,6 +23736,7 @@ var REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS = Object.freeze([
23526
23736
  var REMEMBRANCE_MCP_ALL_TOOLS = Object.freeze([
23527
23737
  ...REMEMBRANCE_MCP_RECOMMENDED_ORG_TOOLS,
23528
23738
  ...REMEMBRANCE_MCP_OPTIONAL_SHARED_CONTRIBUTION_TOOLS,
23739
+ ...REMEMBRANCE_MCP_OPTIONAL_ADMIN_REVIEW_TOOLS,
23529
23740
  ...REMEMBRANCE_MCP_LOCAL_ONLY_TOOLS
23530
23741
  ]);
23531
23742
  var REMEMBRANCE_MCP_BOUNDED_WRITE_POLICY_MAX_BYTES_BY_PAYLOAD_CLASS = Object.freeze({
@@ -23621,6 +23832,8 @@ var REMEMBRANCE_MCP_TOOL_SECURITY = freezeMcpToolSecurityManifest({
23621
23832
  link_current_installation: bounded("bounded_metadata"),
23622
23833
  get_skill: read(),
23623
23834
  get_resource: read(),
23835
+ get_review_comparison: read(),
23836
+ repair_review_draft: content("repair_review_draft", "private_skill"),
23624
23837
  bootstrap_agent_identity: bounded("bounded_metadata"),
23625
23838
  acknowledge_feedback_denial: local("bounded_feedback"),
23626
23839
  decline_pending_action: local("bounded_metadata"),
@@ -23849,6 +24062,501 @@ ${geminiRule(tool)}`;
23849
24062
  ].join("\n\n")
23850
24063
  });
23851
24064
 
24065
+ // ../core/src/private-skill-completion.ts
24066
+ var PRIVATE_SKILL_COMPLETION_VERSION = "private-skill-completion-v1";
24067
+ var opaqueId = external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH);
24068
+ var privateSkillCompletionRevisionIdSchema = external_exports.string().regex(/^pscr_[a-f0-9]{18}$/u);
24069
+ var privateSkillCompletionRequestIdSchema = external_exports.string().regex(/^pscc_[a-f0-9]{32}$/u);
24070
+ var privateSkillCompletionStatusRequestSchema = external_exports.object({
24071
+ contract_version: external_exports.literal(PRIVATE_SKILL_COMPLETION_VERSION),
24072
+ public_id: opaqueId
24073
+ }).strict();
24074
+ var privateSkillCompletionSourceRequestSchema = privateSkillCompletionStatusRequestSchema.extend({
24075
+ revision_id: privateSkillCompletionRevisionIdSchema
24076
+ }).strict();
24077
+ var privateSkillCompletionApprovedSourceSchema = privateSkillIdeaRequestSchema.omit({ agent: true, idempotency_key: true, enterprise_encryption: true }).strict();
24078
+ var privateSkillCompletionSourceResponseSchema = privateSkillCompletionSourceRequestSchema.extend({
24079
+ capture: privateSkillCompletionApprovedSourceSchema.describe("Current approved submission; proposed_skill_md may be null or absent. New revisions still require a complete skill body.")
24080
+ }).strict();
24081
+ var privateSkillCompletionRequestStatusSchema = privateSkillCompletionStatusRequestSchema.extend({
24082
+ request_id: privateSkillCompletionRequestIdSchema
24083
+ }).strict();
24084
+ var continuation = privateSkillCompletionRequestStatusSchema.extend({
24085
+ expected: external_exports.object({
24086
+ completion_id: opaqueId,
24087
+ revision_id: privateSkillCompletionRevisionIdSchema,
24088
+ version: external_exports.number().int().nonnegative()
24089
+ }).strict()
24090
+ });
24091
+ var revisedCapture = privateSkillCaptureSchema.superRefine((capture2, context) => {
24092
+ const pending = [{ value: capture2.proposed_metadata, path: ["proposed_metadata"] }];
24093
+ while (pending.length) {
24094
+ const { value, path } = pending.pop();
24095
+ if (!value || typeof value !== "object") continue;
24096
+ for (const [key, entry] of Object.entries(value)) {
24097
+ if (key.startsWith("_remembrance_")) {
24098
+ context.addIssue({ code: "custom", path: [...path, key], message: "Server provenance fields are reserved." });
24099
+ return;
24100
+ }
24101
+ pending.push({ value: entry, path: [...path, key] });
24102
+ }
24103
+ }
24104
+ });
24105
+ var privateSkillCompletionContinuationSchema = external_exports.discriminatedUnion("operation", [
24106
+ continuation.extend({ operation: external_exports.literal("declare_intent"), intent: external_exports.literal("skill_output") }).strict(),
24107
+ continuation.extend({ operation: external_exports.literal("revise"), capture: revisedCapture }).strict(),
24108
+ continuation.extend({ operation: external_exports.literal("resume"), mode: external_exports.literal("changed_revision"), deadline_at: external_exports.number().int().positive() }).strict()
24109
+ ]);
24110
+
24111
+ // ../core/src/verifier.ts
24112
+ var duplicateCandidateSchema = external_exports.object({
24113
+ type: external_exports.enum(["skill", "resource", "remembrance"]),
24114
+ id: external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH),
24115
+ slug: external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH).optional(),
24116
+ similarity: external_exports.number().min(0).max(1)
24117
+ });
24118
+ var PROPOSED_METADATA_MAX_KEYWORDS = 25;
24119
+ var PROPOSED_METADATA_MAX_TAGS = 15;
24120
+ var PROPOSED_METADATA_MAX_DOMAINS = 8;
24121
+ var PROPOSED_METADATA_MAX_TERM_LENGTH = 64;
24122
+ var PROPOSED_METADATA_MAX_RATIONALE_LENGTH = 2e3;
24123
+ var PROPOSED_METADATA_MAX_MODEL_LENGTH = MAX_SHORT_TEXT_LENGTH;
24124
+ var LOW_VALUE_PROPOSED_METADATA_EXACT_TERMS = /* @__PURE__ */ new Set([
24125
+ "agent",
24126
+ "agents",
24127
+ "agent-skill",
24128
+ "agent-skills",
24129
+ "backfill",
24130
+ "candidate",
24131
+ "candidates",
24132
+ "leaderboard",
24133
+ "import",
24134
+ "imported",
24135
+ "rank",
24136
+ "ranking",
24137
+ "skill",
24138
+ "skills",
24139
+ "skills-sh",
24140
+ "skill-candidate",
24141
+ "skill-candidates"
24142
+ ]);
24143
+ var LOW_VALUE_PROPOSED_METADATA_PATTERNS = [
24144
+ /\bagent\s+skills?\b/i,
24145
+ /\bagentspace\b/i,
24146
+ /\bskill\s+candidates?\b/i,
24147
+ /\bskills?[\s.-]*sh\b/i,
24148
+ /\bleaderboard\s+rank\b/i,
24149
+ /\bnpx\s+skills\s+add\b/i
24150
+ ];
24151
+ function sanitizeProposedMetadataTerm(value) {
24152
+ if (typeof value !== "string") {
24153
+ return null;
24154
+ }
24155
+ const trimmed = value.trim().slice(0, PROPOSED_METADATA_MAX_TERM_LENGTH);
24156
+ if (!trimmed) {
24157
+ return null;
24158
+ }
24159
+ const normalized2 = trimmed.toLowerCase().replace(/[_/.]+/g, "-").replace(/\s+/g, " ").replace(/^-+|-+$/g, "");
24160
+ if (LOW_VALUE_PROPOSED_METADATA_EXACT_TERMS.has(normalized2)) {
24161
+ return null;
24162
+ }
24163
+ if (LOW_VALUE_PROPOSED_METADATA_PATTERNS.some(
24164
+ (pattern) => pattern.test(trimmed)
24165
+ )) {
24166
+ return null;
24167
+ }
24168
+ return trimmed;
24169
+ }
24170
+ var proposedMetadataTermArraySchema = (max) => external_exports.preprocess(
24171
+ (value) => {
24172
+ if (!Array.isArray(value)) {
24173
+ return value;
24174
+ }
24175
+ const seen = /* @__PURE__ */ new Set();
24176
+ const terms = [];
24177
+ for (const entry of value) {
24178
+ const trimmed = sanitizeProposedMetadataTerm(entry);
24179
+ if (!trimmed) {
24180
+ continue;
24181
+ }
24182
+ const key = trimmed.toLowerCase();
24183
+ if (seen.has(key)) {
24184
+ continue;
24185
+ }
24186
+ seen.add(key);
24187
+ terms.push(trimmed);
24188
+ }
24189
+ return terms.slice(0, max);
24190
+ },
24191
+ external_exports.array(external_exports.string().min(1).max(PROPOSED_METADATA_MAX_TERM_LENGTH)).max(max)
24192
+ );
24193
+ var proposedSkillMetadataSchema = external_exports.object({
24194
+ keywords: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_KEYWORDS),
24195
+ tags: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_TAGS),
24196
+ domains: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_DOMAINS),
24197
+ rationale: external_exports.string().trim().min(1).max(PROPOSED_METADATA_MAX_RATIONALE_LENGTH),
24198
+ model: external_exports.string().trim().min(1).max(PROPOSED_METADATA_MAX_MODEL_LENGTH)
24199
+ });
24200
+ var verifierOutputSchema = external_exports.object({
24201
+ recommended_action: verifierActionSchema,
24202
+ confidence: external_exports.number().min(0).max(1),
24203
+ duplicate_candidates: external_exports.array(duplicateCandidateSchema).max(20).default([]),
24204
+ safety_flags: external_exports.array(external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH)).max(40).default([]),
24205
+ summary: external_exports.string().min(1).max(MAX_LONG_TEXT_LENGTH),
24206
+ proposed_patch: external_exports.string().max(MAX_LONG_TEXT_LENGTH).nullable().default(null),
24207
+ score_updates: external_exports.record(external_exports.unknown()).superRefine((value, ctx) => {
24208
+ if (serializedJsonBytes(value) > MAX_JSON_FIELD_BYTES) {
24209
+ addSerializedJsonBytesIssue(
24210
+ ctx,
24211
+ MAX_JSON_FIELD_BYTES,
24212
+ `score_updates must be ${MAX_JSON_FIELD_BYTES} bytes or smaller`
24213
+ );
24214
+ }
24215
+ }).nullable().default(null),
24216
+ // Advisory retrieval enrichment (see proposedSkillMetadataSchema). Optional
24217
+ // and defaults to null so existing verifier outputs remain valid.
24218
+ proposed_metadata: proposedSkillMetadataSchema.nullable().default(null),
24219
+ // Advisory evidence-routing assessment. Deterministic routing and the
24220
+ // existing safety/review gates decide whether it can create a candidate.
24221
+ // Topology is advisory and newer than the base verifier contract. A legacy
24222
+ // or malformed topology fragment must not discard an otherwise valid safety
24223
+ // verdict; it degrades to null, which the topology router retains as
24224
+ // evidence-only rather than allowing an unclassified mutation.
24225
+ topology_assessment: skillTopologyAssessmentSchema.nullable().default(null).catch(null)
24226
+ });
24227
+
24228
+ // ../core/src/verification-policy.ts
24229
+ var verificationReviewReasonCodeSchema = external_exports.enum([
24230
+ "safe_useful",
24231
+ "insufficient_evidence",
24232
+ "duplicate",
24233
+ "strategy_divergence",
24234
+ "quality_regression",
24235
+ "out_of_scope",
24236
+ "policy_preference",
24237
+ "sensitive_data",
24238
+ "prompt_injection",
24239
+ "malware_or_phishing",
24240
+ "spam",
24241
+ "invalid_submission",
24242
+ "unsupported_operation",
24243
+ "other"
24244
+ ]);
24245
+ var verifierAssessmentSchema = external_exports.object({
24246
+ evidence_quality: external_exports.number().min(0).max(1),
24247
+ safety_risk: external_exports.number().min(0).max(1),
24248
+ quality_confidence: external_exports.number().min(0).max(1),
24249
+ duplicate_likelihood: external_exports.number().min(0).max(1),
24250
+ applicability: external_exports.number().min(0).max(1),
24251
+ novelty: external_exports.number().min(0).max(1)
24252
+ }).strict();
24253
+ var verificationRubricPackSchema = external_exports.object({
24254
+ version: external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH),
24255
+ evidence_standard: external_exports.enum(["strict", "balanced", "permissive"]),
24256
+ duplicate_strategy: external_exports.enum(["human", "merge_when_clear"]),
24257
+ quality_regression_tolerance: external_exports.enum(["none", "minor"]),
24258
+ external_dependency_handling: external_exports.enum(["human", "verified_only"])
24259
+ }).strict();
24260
+ var verificationPolicyVerifierOutputSchema = verifierOutputSchema.extend({
24261
+ // Existing and external approvers remain compatible when this is absent.
24262
+ assessment: verifierAssessmentSchema.nullable().default(null)
24263
+ });
24264
+ var verificationAdminReviewActionSchema = adminReviewActionSchema.extend({
24265
+ reason_code: verificationReviewReasonCodeSchema.optional(),
24266
+ topology_action: skillTopologyActionSchema.optional()
24267
+ }).superRefine((value, ctx) => {
24268
+ if (value.reason_code === "other" && !value.note) {
24269
+ ctx.addIssue({
24270
+ code: external_exports.ZodIssueCode.custom,
24271
+ message: "A note is required when the review reason is other",
24272
+ path: ["note"]
24273
+ });
24274
+ }
24275
+ if (value.topology_action && value.action !== "accept" && value.action !== "merge" && value.action !== "fork") {
24276
+ ctx.addIssue({
24277
+ code: external_exports.ZodIssueCode.custom,
24278
+ message: "A topology route may be selected only when accepting, merging, or forking the reviewed evidence",
24279
+ path: ["topology_action"]
24280
+ });
24281
+ }
24282
+ });
24283
+ var BENIGN_REVIEW_FLAGS = /* @__PURE__ */ new Set([
24284
+ "public_skill_change_requires_human_review",
24285
+ "public_skill_change_duplicate_requires_human_review",
24286
+ "public_evidence_requires_human_review",
24287
+ "score_updates_discarded"
24288
+ ]);
24289
+ var SAFE_VERIFICATION_POLICY_FLAG_CATEGORIES = /* @__PURE__ */ new Set([
24290
+ ...BENIGN_REVIEW_FLAGS,
24291
+ "verification_unavailable",
24292
+ "prompt_injection",
24293
+ "sensitive_data",
24294
+ "malware_or_phishing",
24295
+ "spam",
24296
+ "other_safety_signal"
24297
+ ]);
24298
+
24299
+ // ../core/src/admin-review-decision-contract.ts
24300
+ var identifier = external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH);
24301
+ var nullableIdentifier = identifier.nullable();
24302
+ var timestamp = external_exports.string().datetime();
24303
+ var targetTypes = external_exports.enum([
24304
+ "remembrance",
24305
+ "resource",
24306
+ "resource_review",
24307
+ "skill_idea",
24308
+ "suggestion"
24309
+ ]);
24310
+ var reviewDecisionPreviewSelectorSchema = external_exports.object({
24311
+ action: adminReviewActionValueSchema.nullable().default(null),
24312
+ topology_action: skillTopologyActionSchema.nullable().default(null),
24313
+ reason_code: verificationReviewReasonCodeSchema.nullable().default(null)
24314
+ }).strict().superRefine((value, ctx) => {
24315
+ if (value.topology_action && !["accept", "merge", "fork"].includes(value.action ?? "")) {
24316
+ ctx.addIssue({
24317
+ code: external_exports.ZodIssueCode.custom,
24318
+ path: ["topology_action"],
24319
+ message: "A topology route requires an accepting, merging, or forking preview."
24320
+ });
24321
+ }
24322
+ });
24323
+ var overlayRevisionSchema = external_exports.object({
24324
+ id: identifier,
24325
+ status: identifier,
24326
+ version: identifier,
24327
+ revision: external_exports.number().int().nonnegative().nullable(),
24328
+ updated_at: timestamp,
24329
+ private_content_ref: nullableIdentifier,
24330
+ private_catalog_ref: nullableIdentifier,
24331
+ private_catalog_revision_id: nullableIdentifier,
24332
+ private_catalog_version_id: nullableIdentifier,
24333
+ evolution_mode: nullableIdentifier
24334
+ }).strict();
24335
+ var skillRevisionSchema = external_exports.object({
24336
+ id: identifier,
24337
+ slug: identifier,
24338
+ status: identifier,
24339
+ visibility: identifier,
24340
+ version: identifier,
24341
+ current_version_id: nullableIdentifier,
24342
+ updated_at: timestamp
24343
+ }).strict();
24344
+ var versionRevisionSchema = external_exports.object({
24345
+ id: identifier,
24346
+ skill_id: identifier,
24347
+ version: identifier,
24348
+ status: identifier,
24349
+ updated_at: timestamp,
24350
+ private_content_ref: nullableIdentifier,
24351
+ private_content_revision_id: nullableIdentifier,
24352
+ private_content_org_id: nullableIdentifier
24353
+ }).strict();
24354
+ var consumedBaselineSchema = external_exports.object({
24355
+ kind: external_exports.enum(["bundled_seed", "skill_metadata", "public_sync"]),
24356
+ digest: identifier
24357
+ }).strict();
24358
+ var reviewDecisionSnapshotSchema = external_exports.object({
24359
+ schema_version: external_exports.literal("admin-review-decision-snapshot-v1"),
24360
+ org_id: identifier,
24361
+ public_skill_access_policy: external_exports.enum(["allow", "org_only"]),
24362
+ selected_route: reviewDecisionPreviewSelectorSchema,
24363
+ actor: external_exports.object({
24364
+ type: identifier,
24365
+ id: identifier,
24366
+ org_id: identifier,
24367
+ api_key_id: nullableIdentifier,
24368
+ token_id: nullableIdentifier
24369
+ }).strict(),
24370
+ job: external_exports.object({
24371
+ id: identifier,
24372
+ target_type: targetTypes,
24373
+ target_id: identifier,
24374
+ status: identifier,
24375
+ updated_at: timestamp,
24376
+ verifier_input_hash: nullableIdentifier,
24377
+ private_verification_artifact_id: nullableIdentifier,
24378
+ private_verification_result_digest: nullableIdentifier,
24379
+ private_semantic_context_ref: nullableIdentifier,
24380
+ private_context_ref: nullableIdentifier,
24381
+ private_context_revision_id: nullableIdentifier
24382
+ }).strict(),
24383
+ target: external_exports.object({
24384
+ id: identifier,
24385
+ updated_at: timestamp,
24386
+ payload_ref: nullableIdentifier,
24387
+ superseded_by_submission_id: nullableIdentifier,
24388
+ disposition_job_id: nullableIdentifier
24389
+ }).strict(),
24390
+ private_payload: external_exports.object({
24391
+ id: identifier,
24392
+ updated_at: timestamp,
24393
+ encryption_mode: identifier,
24394
+ inspection_status: nullableIdentifier,
24395
+ inspection_updated_at: timestamp.nullable(),
24396
+ inspection_projection_digest: nullableIdentifier,
24397
+ inspection_inspector_digest: nullableIdentifier
24398
+ }).strict().nullable(),
24399
+ protected_source_binding: external_exports.object({
24400
+ schema_version: external_exports.literal("protected-submission-source-v1"),
24401
+ source_type: external_exports.enum(["skill_idea", "suggestion", "remembrance"]),
24402
+ source_id: identifier,
24403
+ source_public_id: identifier,
24404
+ content_digest: identifier,
24405
+ inline_job_digest: identifier.nullable()
24406
+ }).strict().optional(),
24407
+ legacy_public_payload: external_exports.object({
24408
+ schema_version: external_exports.literal("legacy-public-remembrance-payload-v1"),
24409
+ id: identifier,
24410
+ updated_at: timestamp,
24411
+ source_public_id: identifier,
24412
+ raw_digest: identifier,
24413
+ redacted_digest: identifier,
24414
+ target_digest: identifier,
24415
+ inline_job_digest: identifier.nullable()
24416
+ }).strict().optional(),
24417
+ current_skill: external_exports.object({
24418
+ slug: identifier,
24419
+ overlay: overlayRevisionSchema.nullable(),
24420
+ version: versionRevisionSchema.nullable(),
24421
+ consumed_baseline: consumedBaselineSchema.nullable()
24422
+ }).strict().nullable(),
24423
+ source_skill: external_exports.object({
24424
+ skill: skillRevisionSchema,
24425
+ version: versionRevisionSchema.nullable(),
24426
+ consumed_baseline: consumedBaselineSchema.nullable()
24427
+ }).strict().nullable(),
24428
+ parent_skill: external_exports.object({
24429
+ skill: skillRevisionSchema,
24430
+ version: versionRevisionSchema,
24431
+ overlay: overlayRevisionSchema.nullable()
24432
+ }).strict().nullable()
24433
+ }).strict();
24434
+
24435
+ // ../core/src/review-workflows.ts
24436
+ var PRIVATE_SKILL_REVIEW_REPAIR_VERSION = "private-skill-review-repair-v1";
24437
+ var REVIEW_COMPARISON_TOOL_DESCRIPTION = "Organization admin:review only. Read complete exact source, parent and current skill versions already linked to one pending review job. Supply no action, route, organization or arbitrary skill ID. This does not select a route or grant decision authority: inspect the current review detail and its fresh snapshot separately before any decision. An unavailable, held, changed or foreign reference refuses the whole comparison; nothing is truncated or silently substituted.";
24438
+ var REVIEW_DRAFT_REPAIR_TOOL_DESCRIPTION = "Organization admin:review only; explicit delegated AI review authority, not routine learning permission. Create one complete protected replacement for a pending private skill draft using its current unselected review snapshot. Use a stable psrr_ plus 32 lowercase hex request_id; the transport sets Idempotency-Key to that exact ID. Exact replay returns the original replacement receipt; changed input under that ID conflicts. All normal secret inspection, protection, routing, verification and review checks apply. The local client requires inspection to leave the authored capture unchanged before sending. A local hold returns content-free recovery, never an alternate transport or a rewritten original. Creation preserves the original and never approves, rejects or supersedes it. Review the replacement normally, then close the original separately only after proving an accepted, tenant-readable active replacement skill. No public or cross-organization fallback.";
24439
+ var REVIEW_DRAFT_REPAIR_NEXT_INSTRUCTION = "Review the replacement normally. Keep the original open until an accepted, tenant-readable active skill version proves the replacement usable.";
24440
+ var reviewWorkflowJobIdSchema = external_exports.string().regex(/^job_[a-f0-9]{18}$/u);
24441
+ var privateSkillReviewRepairRequestIdSchema = external_exports.string().regex(/^psrr_[a-f0-9]{32}$/u);
24442
+ var referenceIdentifier = external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH);
24443
+ var MAX_REVIEW_REFERENCE_BODY_BYTES = 1048576;
24444
+ var reviewReferenceSkillSchema = external_exports.object({
24445
+ skill_id: referenceIdentifier,
24446
+ slug: referenceIdentifier,
24447
+ version_id: referenceIdentifier,
24448
+ version: referenceIdentifier,
24449
+ skill_md: external_exports.string().min(1).max(MAX_REVIEW_REFERENCE_BODY_BYTES).refine((value) => new TextEncoder().encode(value).length <= MAX_REVIEW_REFERENCE_BODY_BYTES),
24450
+ content_hash: referenceIdentifier
24451
+ }).strict();
24452
+ var reviewReferenceComparisonSchema = external_exports.object({
24453
+ schema_version: external_exports.literal("review-reference-comparison-v1"),
24454
+ job_id: reviewWorkflowJobIdSchema,
24455
+ source_skill: reviewReferenceSkillSchema.nullable(),
24456
+ parent_skill: reviewReferenceSkillSchema.nullable(),
24457
+ current_skill: reviewReferenceSkillSchema.nullable()
24458
+ }).strict();
24459
+ function reviewWorkflowResponseBound(tool, body, request) {
24460
+ if (tool === "get_review_comparison") {
24461
+ const parsed2 = reviewReferenceComparisonSchema.safeParse(body);
24462
+ return parsed2.success && parsed2.data.job_id === request.job_id;
24463
+ }
24464
+ if (tool !== "repair_review_draft") return false;
24465
+ const parsed = external_exports.object({
24466
+ contract_version: external_exports.literal(PRIVATE_SKILL_REVIEW_REPAIR_VERSION),
24467
+ request_id: privateSkillReviewRepairRequestIdSchema,
24468
+ original_job_id: reviewWorkflowJobIdSchema,
24469
+ replacement: external_exports.object({
24470
+ public_id: external_exports.string().regex(/^ipub_[a-f0-9]{18}$/u),
24471
+ job_id: reviewWorkflowJobIdSchema,
24472
+ status: external_exports.enum(["submitted", "duplicate", "accepted", "rejected", "merged", "forked", "needs_review", "quarantined"]),
24473
+ visibility: external_exports.literal("organization_private")
24474
+ }).strict(),
24475
+ replayed: external_exports.boolean(),
24476
+ original_disposition: external_exports.literal("unchanged"),
24477
+ verification: external_exports.object({
24478
+ verification_job: external_exports.object({
24479
+ id: reviewWorkflowJobIdSchema,
24480
+ status: verificationJobStatusSchema,
24481
+ target_type: external_exports.literal("skill_idea"),
24482
+ target_id: external_exports.string().regex(/^idea_[a-f0-9]{18}$/u)
24483
+ }).strict(),
24484
+ queue: external_exports.object({ queued: external_exports.boolean(), queueJobId: reviewWorkflowJobIdSchema.nullable() }).strict()
24485
+ }).strict().nullable(),
24486
+ verification_status: verificationJobStatusSchema,
24487
+ dispatch_state: external_exports.enum(["existing_persisted_job", "queued", "mongo_poll_fallback"]),
24488
+ next_action: external_exports.object({
24489
+ method: external_exports.literal("GET"),
24490
+ path: external_exports.literal("/api/v1/admin/review-queue"),
24491
+ query: external_exports.object({ job_id: reviewWorkflowJobIdSchema, review_provenance: external_exports.literal("delegated_ai") }).strict(),
24492
+ instruction: external_exports.literal(REVIEW_DRAFT_REPAIR_NEXT_INSTRUCTION)
24493
+ }).strict()
24494
+ }).strict().safeParse(body);
24495
+ if (!parsed.success) return false;
24496
+ const receipt = parsed.data;
24497
+ if (receipt.request_id !== request.request_id || receipt.original_job_id !== request.job_id || receipt.replacement.job_id === receipt.original_job_id || receipt.next_action.query.job_id !== receipt.replacement.job_id) return false;
24498
+ if (receipt.replayed) return receipt.verification === null && receipt.dispatch_state === "existing_persisted_job";
24499
+ const verification = receipt.verification;
24500
+ return verification !== null && verification.verification_job.id === receipt.replacement.job_id && verification.verification_job.status === receipt.verification_status && (verification.queue.queued ? receipt.dispatch_state === "queued" && verification.queue.queueJobId === receipt.replacement.job_id : receipt.dispatch_state === "mongo_poll_fallback" && verification.queue.queueJobId === null);
24501
+ }
24502
+ var reviewReferenceComparisonRequestSchema = external_exports.object({
24503
+ job_id: reviewWorkflowJobIdSchema,
24504
+ review_provenance: external_exports.literal("delegated_ai").default("delegated_ai")
24505
+ }).strict();
24506
+ function checkJsonGraph(value, context, reservedKeys) {
24507
+ const pending = [{ value, depth: 0 }];
24508
+ const seen = /* @__PURE__ */ new Set();
24509
+ let nodes = 0;
24510
+ while (pending.length) {
24511
+ const entry = pending.pop();
24512
+ if (++nodes > 1e4 || entry.depth > 32) {
24513
+ context.addIssue({ code: "custom", message: "JSON structure exceeds the bounded review request limits." });
24514
+ return false;
24515
+ }
24516
+ const current = entry.value;
24517
+ if (current === null || typeof current === "string" || typeof current === "boolean" || typeof current === "number" && Number.isFinite(current)) continue;
24518
+ if (typeof current !== "object" || seen.has(current)) {
24519
+ context.addIssue({ code: "custom", message: "Review requests must contain finite, acyclic JSON values." });
24520
+ return false;
24521
+ }
24522
+ seen.add(current);
24523
+ for (const [key, child] of Object.entries(current)) {
24524
+ if (reservedKeys && key.startsWith("_remembrance_")) {
24525
+ context.addIssue({ code: "custom", message: "Server provenance fields are reserved." });
24526
+ return false;
24527
+ }
24528
+ pending.push({ value: child, depth: entry.depth + 1 });
24529
+ }
24530
+ }
24531
+ return true;
24532
+ }
24533
+ var reviewSnapshot = reviewDecisionSnapshotSchema.superRefine((value, context) => {
24534
+ if (!checkJsonGraph(value, context, false)) return;
24535
+ if (serializedJsonBytes(value) > MAX_JSON_FIELD_BYTES) {
24536
+ addSerializedJsonBytesIssue(context, MAX_JSON_FIELD_BYTES, "Review snapshot exceeds its JSON byte limit.");
24537
+ }
24538
+ });
24539
+ var repairCapture = privateSkillCaptureSchema.superRefine((capture2, context) => {
24540
+ checkJsonGraph(capture2.proposed_metadata, context, true);
24541
+ });
24542
+ var privateSkillReviewRepairRequest = external_exports.object({
24543
+ contract_version: external_exports.literal(PRIVATE_SKILL_REVIEW_REPAIR_VERSION),
24544
+ job_id: reviewWorkflowJobIdSchema,
24545
+ request_id: privateSkillReviewRepairRequestIdSchema,
24546
+ review_provenance: external_exports.literal("delegated_ai").default("delegated_ai"),
24547
+ expected_review_snapshot: reviewSnapshot,
24548
+ capture: repairCapture
24549
+ }).strict().superRefine((value, context) => {
24550
+ if (!checkJsonGraph(value, context, false)) return;
24551
+ if (serializedJsonBytes(value) > DEFAULT_MUTATION_BODY_LIMIT_BYTES) {
24552
+ addSerializedJsonBytesIssue(context, DEFAULT_MUTATION_BODY_LIMIT_BYTES, "Review repair exceeds its JSON byte limit; nothing is truncated.");
24553
+ }
24554
+ });
24555
+ var privateSkillReviewRepairRequestSchema = external_exports.preprocess((value, context) => {
24556
+ if (!checkJsonGraph(value, context, false)) return external_exports.NEVER;
24557
+ return value;
24558
+ }, privateSkillReviewRepairRequest);
24559
+
23852
24560
  // ../core/src/seed.ts
23853
24561
  var siteUrl = "https://remembrance.dev";
23854
24562
  var feedbackUrl = `${siteUrl}/api/v1/agent/remembrances`;
@@ -26357,122 +27065,33 @@ function invalidToolArgumentsMessage(error, schema) {
26357
27065
  ).join("; ")}${more > 0 ? ` (+${more} more)` : ""}.`;
26358
27066
  }
26359
27067
 
26360
- // ../core/src/verifier.ts
26361
- var duplicateCandidateSchema = external_exports.object({
26362
- type: external_exports.enum(["skill", "resource", "remembrance"]),
26363
- id: external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH),
26364
- slug: external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH).optional(),
26365
- similarity: external_exports.number().min(0).max(1)
26366
- });
26367
- var PROPOSED_METADATA_MAX_KEYWORDS = 25;
26368
- var PROPOSED_METADATA_MAX_TAGS = 15;
26369
- var PROPOSED_METADATA_MAX_DOMAINS = 8;
26370
- var PROPOSED_METADATA_MAX_TERM_LENGTH = 64;
26371
- var PROPOSED_METADATA_MAX_RATIONALE_LENGTH = 2e3;
26372
- var PROPOSED_METADATA_MAX_MODEL_LENGTH = MAX_SHORT_TEXT_LENGTH;
26373
- var LOW_VALUE_PROPOSED_METADATA_EXACT_TERMS = /* @__PURE__ */ new Set([
26374
- "agent",
26375
- "agents",
26376
- "agent-skill",
26377
- "agent-skills",
26378
- "backfill",
26379
- "candidate",
26380
- "candidates",
26381
- "leaderboard",
26382
- "import",
26383
- "imported",
26384
- "rank",
26385
- "ranking",
26386
- "skill",
26387
- "skills",
26388
- "skills-sh",
26389
- "skill-candidate",
26390
- "skill-candidates"
26391
- ]);
26392
- var LOW_VALUE_PROPOSED_METADATA_PATTERNS = [
26393
- /\bagent\s+skills?\b/i,
26394
- /\bagentspace\b/i,
26395
- /\bskill\s+candidates?\b/i,
26396
- /\bskills?[\s.-]*sh\b/i,
26397
- /\bleaderboard\s+rank\b/i,
26398
- /\bnpx\s+skills\s+add\b/i
26399
- ];
26400
- function sanitizeProposedMetadataTerm(value) {
26401
- if (typeof value !== "string") {
26402
- return null;
26403
- }
26404
- const trimmed = value.trim().slice(0, PROPOSED_METADATA_MAX_TERM_LENGTH);
26405
- if (!trimmed) {
26406
- return null;
26407
- }
26408
- const normalized2 = trimmed.toLowerCase().replace(/[_/.]+/g, "-").replace(/\s+/g, " ").replace(/^-+|-+$/g, "");
26409
- if (LOW_VALUE_PROPOSED_METADATA_EXACT_TERMS.has(normalized2)) {
26410
- return null;
27068
+ // src/private-skill-protection-recovery.ts
27069
+ var PRIVATE_SKILL_CONFIGURATION_REFUSAL = "private_admission_configuration_error";
27070
+ var PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL = "private_skill_permanent_service_refusal";
27071
+ function isPrivateSkillConfigurationHold(draft) {
27072
+ return draft.state === "held_validation" && draft.last_error_code === PRIVATE_SKILL_CONFIGURATION_REFUSAL;
27073
+ }
27074
+ function privateSkillPermanentRefusalGuidance(draft) {
27075
+ if (isPrivateSkillConfigurationHold(draft)) {
27076
+ return {
27077
+ next_action: null,
27078
+ action_required: "Private protection configuration refused this submission. Keep the exact encrypted draft. Ask the organization administrator to correct the selected protection configuration; customer-held submissions require a valid customer-encrypted envelope. Do not change key ownership, protection mode, destination, or consent automatically. Only after an authorized correction, explicitly retry this same draft once with retry_private_skill_candidate. An unchanged refusal remains held; no replacement or acceptance is claimed.",
27079
+ recovery_after_correction: {
27080
+ automatic_retry: false,
27081
+ condition: "organization_administrator_corrected_private_protection_configuration",
27082
+ tool: "retry_private_skill_candidate",
27083
+ arguments: { draft_id: draft.draft_id }
27084
+ }
27085
+ };
26411
27086
  }
26412
- if (LOW_VALUE_PROPOSED_METADATA_PATTERNS.some(
26413
- (pattern) => pattern.test(trimmed)
26414
- )) {
26415
- return null;
27087
+ if (draft.state === "held_validation" && draft.last_error_code === PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL) {
27088
+ return {
27089
+ next_action: null,
27090
+ action_required: "The private service explicitly refused unchanged retries. Keep the encrypted draft and inspect this retained hold. No automatic retry, alternate transport, replacement, or successful recovery is authorized by this unknown refusal."
27091
+ };
26416
27092
  }
26417
- return trimmed;
27093
+ return {};
26418
27094
  }
26419
- var proposedMetadataTermArraySchema = (max) => external_exports.preprocess(
26420
- (value) => {
26421
- if (!Array.isArray(value)) {
26422
- return value;
26423
- }
26424
- const seen = /* @__PURE__ */ new Set();
26425
- const terms = [];
26426
- for (const entry of value) {
26427
- const trimmed = sanitizeProposedMetadataTerm(entry);
26428
- if (!trimmed) {
26429
- continue;
26430
- }
26431
- const key = trimmed.toLowerCase();
26432
- if (seen.has(key)) {
26433
- continue;
26434
- }
26435
- seen.add(key);
26436
- terms.push(trimmed);
26437
- }
26438
- return terms.slice(0, max);
26439
- },
26440
- external_exports.array(external_exports.string().min(1).max(PROPOSED_METADATA_MAX_TERM_LENGTH)).max(max)
26441
- );
26442
- var proposedSkillMetadataSchema = external_exports.object({
26443
- keywords: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_KEYWORDS),
26444
- tags: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_TAGS),
26445
- domains: proposedMetadataTermArraySchema(PROPOSED_METADATA_MAX_DOMAINS),
26446
- rationale: external_exports.string().trim().min(1).max(PROPOSED_METADATA_MAX_RATIONALE_LENGTH),
26447
- model: external_exports.string().trim().min(1).max(PROPOSED_METADATA_MAX_MODEL_LENGTH)
26448
- });
26449
- var verifierOutputSchema = external_exports.object({
26450
- recommended_action: verifierActionSchema,
26451
- confidence: external_exports.number().min(0).max(1),
26452
- duplicate_candidates: external_exports.array(duplicateCandidateSchema).max(20).default([]),
26453
- safety_flags: external_exports.array(external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH)).max(40).default([]),
26454
- summary: external_exports.string().min(1).max(MAX_LONG_TEXT_LENGTH),
26455
- proposed_patch: external_exports.string().max(MAX_LONG_TEXT_LENGTH).nullable().default(null),
26456
- score_updates: external_exports.record(external_exports.unknown()).superRefine((value, ctx) => {
26457
- if (serializedJsonBytes(value) > MAX_JSON_FIELD_BYTES) {
26458
- addSerializedJsonBytesIssue(
26459
- ctx,
26460
- MAX_JSON_FIELD_BYTES,
26461
- `score_updates must be ${MAX_JSON_FIELD_BYTES} bytes or smaller`
26462
- );
26463
- }
26464
- }).nullable().default(null),
26465
- // Advisory retrieval enrichment (see proposedSkillMetadataSchema). Optional
26466
- // and defaults to null so existing verifier outputs remain valid.
26467
- proposed_metadata: proposedSkillMetadataSchema.nullable().default(null),
26468
- // Advisory evidence-routing assessment. Deterministic routing and the
26469
- // existing safety/review gates decide whether it can create a candidate.
26470
- // Topology is advisory and newer than the base verifier contract. A legacy
26471
- // or malformed topology fragment must not discard an otherwise valid safety
26472
- // verdict; it degrades to null, which the topology router retains as
26473
- // evidence-only rather than allowing an unclassified mutation.
26474
- topology_assessment: skillTopologyAssessmentSchema.nullable().default(null).catch(null)
26475
- });
26476
27095
 
26477
27096
  // src/server.ts
26478
27097
  import { existsSync as existsSync6 } from "node:fs";
@@ -28229,6 +28848,19 @@ var remembranceToolSchema = remembrancePayloadSchema.extend({
28229
28848
  )
28230
28849
  });
28231
28850
  var declaredToolDefinitions = [
28851
+ readTool(
28852
+ "get_review_comparison",
28853
+ REVIEW_COMPARISON_TOOL_DESCRIPTION,
28854
+ "/api/v1/admin/review-queue/comparison",
28855
+ reviewReferenceComparisonRequestSchema,
28856
+ "GET"
28857
+ ),
28858
+ contentWriteTool(
28859
+ "repair_review_draft",
28860
+ REVIEW_DRAFT_REPAIR_TOOL_DESCRIPTION,
28861
+ "/api/v1/admin/review-queue/repairs",
28862
+ privateSkillReviewRepairRequestSchema
28863
+ ),
28232
28864
  readTool(
28233
28865
  "get_connection_status",
28234
28866
  REMEMBRANCE_CONNECTION_STATUS_TOOL_DESCRIPTION,
@@ -28391,7 +29023,7 @@ var declaredToolDefinitions = [
28391
29023
  ),
28392
29024
  localNetworkTool(
28393
29025
  "retry_private_skill_candidate",
28394
- "Retry one retained private-skill draft through the same private_skill approval lane as submit_private_skill_candidate. Network access is allowed only for authorization-pending or due transient retry states, and for a draft an older server refused only for length: that waits out any delay the server set, then reads its signed capability and resends the exact draft only if it admits it. A fresh ready draft is rejected locally. It never switches transport or visibility.",
29026
+ "Retry one retained private-skill draft through the same private_skill approval lane as submit_private_skill_candidate. Network access is allowed only for authorization-pending or due transient retry states, an explicit same-draft retry after an administrator corrected a private-protection configuration hold, and for a draft an older server refused only for length: that waits out any delay the server set, then reads its signed capability and resends the exact draft only if it admits it. Configuration holds never schedule automatic retries; an unchanged refusal remains held. A fresh ready draft is rejected locally. It never switches transport, visibility, key ownership, or protection mode.",
28395
29027
  "retry_private_skill_candidate",
28396
29028
  privateSkillDraftReferenceSchema,
28397
29029
  "content_write"
@@ -28978,13 +29610,13 @@ function validateServedToolDefinition(definition) {
28978
29610
  canonicalToolDefinitionForDispatch(definition);
28979
29611
  }
28980
29612
  function annotationsForTool(name) {
28981
- const readOnly = name === "list_skills" || name === "get_effective_preferences" || name === "get_value_proof" || name === "run_connection_doctor" || name === "get_private_lesson_policy" || name === "inspect_private_lesson_outbox" || name === "inspect_private_learning_outbox" || name === "get_pending_action_payload";
29613
+ const readOnly = name === "get_review_comparison" || name === "list_skills" || name === "get_effective_preferences" || name === "get_value_proof" || name === "run_connection_doctor" || name === "get_private_lesson_policy" || name === "inspect_private_lesson_outbox" || name === "inspect_private_learning_outbox" || name === "get_pending_action_payload";
28982
29614
  const openWorld = name === "submit_feedback" || name === "submit_remembrance" || name === "propose_skill_idea" || name === "submit_suggestion" || name === "submit_resource" || name === "submit_resource_review";
28983
29615
  return {
28984
29616
  readOnlyHint: readOnly,
28985
29617
  openWorldHint: openWorld,
28986
29618
  destructiveHint: name === "delete_private_lesson_candidate" || name === "delete_private_skill_candidate",
28987
- ...readOnly || name === "queue_private_skill_import" || name === "acknowledge_feedback_denial" || name === "decline_pending_action" || name === "submit_private_lesson_candidate" || name === "retry_private_lesson_candidate" || name === "submit_private_skill_candidate" || name === "retry_private_skill_candidate" ? { idempotentHint: true } : {}
29619
+ ...readOnly || name === "queue_private_skill_import" || name === "acknowledge_feedback_denial" || name === "decline_pending_action" || name === "submit_private_lesson_candidate" || name === "retry_private_lesson_candidate" || name === "submit_private_skill_candidate" || name === "retry_private_skill_candidate" || name === "repair_review_draft" ? { idempotentHint: true } : {}
28988
29620
  };
28989
29621
  }
28990
29622
  var ROUTINE_PRIVATE_CAPTURE_REPLACED_TOOLS = /* @__PURE__ */ new Set([
@@ -45270,7 +45902,7 @@ var require_timestamp = __commonJS({
45270
45902
  resolve: (str) => parseSexagesimal(str, false),
45271
45903
  stringify: stringifySexagesimal
45272
45904
  };
45273
- var timestamp = {
45905
+ var timestamp2 = {
45274
45906
  identify: (value) => value instanceof Date,
45275
45907
  default: true,
45276
45908
  tag: "tag:yaml.org,2002:timestamp",
@@ -45279,7 +45911,7 @@ var require_timestamp = __commonJS({
45279
45911
  // assumed to be 00:00:00Z (start of day, UTC).
45280
45912
  test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
45281
45913
  resolve(str) {
45282
- const match = str.match(timestamp.test);
45914
+ const match = str.match(timestamp2.test);
45283
45915
  if (!match)
45284
45916
  throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
45285
45917
  const [, year, month, day, hour, minute, second] = match.map(Number);
@@ -45298,7 +45930,7 @@ var require_timestamp = __commonJS({
45298
45930
  };
45299
45931
  exports.floatTime = floatTime;
45300
45932
  exports.intTime = intTime;
45301
- exports.timestamp = timestamp;
45933
+ exports.timestamp = timestamp2;
45302
45934
  }
45303
45935
  });
45304
45936
  var require_schema3 = __commonJS({
@@ -45316,7 +45948,7 @@ var require_schema3 = __commonJS({
45316
45948
  var omap = require_omap();
45317
45949
  var pairs = require_pairs();
45318
45950
  var set = require_set();
45319
- var timestamp = require_timestamp();
45951
+ var timestamp2 = require_timestamp();
45320
45952
  var schema = [
45321
45953
  map.map,
45322
45954
  seq.seq,
@@ -45336,9 +45968,9 @@ var require_schema3 = __commonJS({
45336
45968
  omap.omap,
45337
45969
  pairs.pairs,
45338
45970
  set.set,
45339
- timestamp.intTime,
45340
- timestamp.floatTime,
45341
- timestamp.timestamp
45971
+ timestamp2.intTime,
45972
+ timestamp2.floatTime,
45973
+ timestamp2.timestamp
45342
45974
  ];
45343
45975
  exports.schema = schema;
45344
45976
  }
@@ -45361,7 +45993,7 @@ var require_tags = __commonJS({
45361
45993
  var pairs = require_pairs();
45362
45994
  var schema$2 = require_schema3();
45363
45995
  var set = require_set();
45364
- var timestamp = require_timestamp();
45996
+ var timestamp2 = require_timestamp();
45365
45997
  var schemas = /* @__PURE__ */ new Map([
45366
45998
  ["core", schema.schema],
45367
45999
  ["failsafe", [map.map, seq.seq, string.string]],
@@ -45375,11 +46007,11 @@ var require_tags = __commonJS({
45375
46007
  float: float.float,
45376
46008
  floatExp: float.floatExp,
45377
46009
  floatNaN: float.floatNaN,
45378
- floatTime: timestamp.floatTime,
46010
+ floatTime: timestamp2.floatTime,
45379
46011
  int: int.int,
45380
46012
  intHex: int.intHex,
45381
46013
  intOct: int.intOct,
45382
- intTime: timestamp.intTime,
46014
+ intTime: timestamp2.intTime,
45383
46015
  map: map.map,
45384
46016
  merge: merge.merge,
45385
46017
  null: _null.nullTag,
@@ -45387,7 +46019,7 @@ var require_tags = __commonJS({
45387
46019
  pairs: pairs.pairs,
45388
46020
  seq: seq.seq,
45389
46021
  set: set.set,
45390
- timestamp: timestamp.timestamp
46022
+ timestamp: timestamp2.timestamp
45391
46023
  };
45392
46024
  var coreKnownTags = {
45393
46025
  "tag:yaml.org,2002:binary": binary.binary,
@@ -45395,7 +46027,7 @@ var require_tags = __commonJS({
45395
46027
  "tag:yaml.org,2002:omap": omap.omap,
45396
46028
  "tag:yaml.org,2002:pairs": pairs.pairs,
45397
46029
  "tag:yaml.org,2002:set": set.set,
45398
- "tag:yaml.org,2002:timestamp": timestamp.timestamp
46030
+ "tag:yaml.org,2002:timestamp": timestamp2.timestamp
45399
46031
  };
45400
46032
  function getTags(customTags, schemaName, addMergeTag) {
45401
46033
  const schemaTags = schemas.get(schemaName);
@@ -62461,7 +63093,8 @@ async function reinspectPrivateSkillSubmissionCandidate(draftId, options = {}) {
62461
63093
  const resumingReinspectionHold = isPrivateSkillSubmissionReinspectionHold(current);
62462
63094
  const resumingDestinationHold = isPrivateSkillDestinationHold(current) && !isPrivateSkillDestinationRecoveryBlocked(current, destination);
62463
63095
  const resumingResolution = current.delivery_resolution !== null;
62464
- const resumingHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution;
63096
+ const resumingConfigurationHold = options.resumeConfigurationHold === true && isPrivateSkillConfigurationHold(current);
63097
+ const resumingHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution || resumingConfigurationHold;
62465
63098
  if (resumingReinspectionHold && !resumingResolution && current.inspection?.inspector_digest === PRIVATE_LEARNING_INSPECTOR_DIGEST && current.inspection.outcome !== "unchanged" && current.inspection.outcome !== "redacted") {
62466
63099
  return Object.freeze({ status: "held", draft: current });
62467
63100
  }
@@ -65328,6 +65961,7 @@ async function inspectPrivateLearningOutbox(input, persistence) {
65328
65961
  status: skillResult.value.recovery_items.length > 0 ? "recovery_required" : "ok",
65329
65962
  drafts: skillResult.value.drafts.map((draft) => ({
65330
65963
  ...draft,
65964
+ ...privateSkillPermanentRefusalGuidance(draft),
65331
65965
  recovery_context: { status: "context_unavailable" },
65332
65966
  agent_recovery: privateSkillExactInspectionRecovery(draft)
65333
65967
  })),
@@ -65633,6 +66267,7 @@ function privateSkillSelectedDraftResult(draft) {
65633
66267
  draft,
65634
66268
  PRIVATE_LEARNING_CAPTURE_VERSION
65635
66269
  ),
66270
+ ...privateSkillPermanentRefusalGuidance(draft),
65636
66271
  recovery_context: recoveryContext,
65637
66272
  native_recovery_context: nativeContext ? {
65638
66273
  ...nativeContext,
@@ -66153,9 +66788,68 @@ function createLocalPersistenceCapabilities(dependencies = {}) {
66153
66788
  });
66154
66789
  }
66155
66790
 
66156
- // src/network-transport.ts
66791
+ // ../core/src/redaction-request-budget.ts
66157
66792
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
66158
- var networkExecutionAuthority = new AsyncLocalStorage2();
66793
+ var requests = new AsyncLocalStorage2();
66794
+ trackRedactionRequests(() => requests.getStore());
66795
+ function withRedactionRequestBudget(run) {
66796
+ return requests.getStore() ? run() : requests.run({}, run);
66797
+ }
66798
+
66799
+ // src/review-repair-inspection.ts
66800
+ function inspectReviewRepairForTransport(value) {
66801
+ const request = privateSkillReviewRepairRequestSchema.parse(value);
66802
+ const inspection = inspectPrivateSkillCandidate(request.capture);
66803
+ if (inspection.status === "complete" && inspection.decision.outcome === "unchanged") {
66804
+ const values = [];
66805
+ const pending = [request.expected_review_snapshot];
66806
+ while (pending.length) {
66807
+ const entry = pending.pop();
66808
+ if (entry !== null && typeof entry === "object") pending.push(...Object.values(entry));
66809
+ else values.push(entry);
66810
+ }
66811
+ try {
66812
+ if (canonicalJson(withRedactionRequestBudget(() => redactPayload(values))) !== canonicalJson(values)) {
66813
+ return { ready: false, refusal: {
66814
+ status: "held",
66815
+ code: "review_repair_wire_inspection_hold",
66816
+ delivery: "not_delivered",
66817
+ candidate_sent: false,
66818
+ candidate_stored: false,
66819
+ original_disposition: "unchanged",
66820
+ next_action: "Retain the original. Read a fresh normal content-free review snapshot; do not send suspected secrets, rewrite the held request, or use another transport."
66821
+ } };
66822
+ }
66823
+ } catch {
66824
+ return { ready: false, refusal: {
66825
+ status: "held",
66826
+ code: "review_repair_wire_inspection_failure",
66827
+ delivery: "not_delivered",
66828
+ candidate_sent: false,
66829
+ candidate_stored: false,
66830
+ original_disposition: "unchanged",
66831
+ next_action: "Retain the original. Correct the local inspection failure before retrying; do not reformulate around an operational failure."
66832
+ } };
66833
+ }
66834
+ return { ready: true, request };
66835
+ }
66836
+ const reason = inspection.status === "complete" ? "authored_capture_changed_by_inspection" : inspection.status === "incomplete" ? inspection.reason : inspection.error_code;
66837
+ return { ready: false, refusal: {
66838
+ status: "held",
66839
+ code: "review_repair_local_inspection_hold",
66840
+ delivery: "not_delivered",
66841
+ candidate_sent: false,
66842
+ candidate_stored: false,
66843
+ original_disposition: "unchanged",
66844
+ reason_code: reason,
66845
+ inspection: inspection.decision,
66846
+ next_action: inspection.status === "invalid" ? "Retain the original. Correct the local inspection failure before retrying the same unchanged request; do not reformulate around an operational failure or use another transport." : "Retain the original. Prepare a complete safe replacement from authenticated task context and inspect it again. Do not recover suspected secrets, invent missing instructions, or bypass a host denial."
66847
+ } };
66848
+ }
66849
+
66850
+ // src/network-transport.ts
66851
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
66852
+ var networkExecutionAuthority = new AsyncLocalStorage3();
66159
66853
  var guardedFetches = /* @__PURE__ */ new WeakSet();
66160
66854
  function installRuntimeFetchGuard() {
66161
66855
  const delegate = globalThis.fetch;
@@ -67868,7 +68562,7 @@ function inspectPrivateLearningOutbox2(input, dependencies = {}) {
67868
68562
  }
67869
68563
  var MAX_REMOTE_RESPONSE_BYTES = 4 * 1024 * 1024;
67870
68564
  var DOCTOR_PROBE_TIMEOUT_MS = 7500;
67871
- var SERVER_VERSION = true ? "0.2.3" : "0.0.0-dev";
68565
+ var SERVER_VERSION = true ? "0.2.5" : "0.0.0-dev";
67872
68566
  var tools2 = toolDefinitions;
67873
68567
  var doctorCliRequested = process.argv[2] === "doctor";
67874
68568
  var nativeContextCliRequested = process.argv[2] === "--native-context";
@@ -68227,6 +68921,11 @@ async function callToolWithinExecution(runtimeDefinition, rawArguments, dependen
68227
68921
  );
68228
68922
  }
68229
68923
  async function callNetworkToolWithinExecution(definition, payload, access, transport) {
68924
+ if (definition.name === "repair_review_draft") {
68925
+ const inspection = inspectReviewRepairForTransport(payload);
68926
+ if (!inspection.ready) return inspection.refusal;
68927
+ payload = inspection.request;
68928
+ }
68230
68929
  if (definition.local === "bootstrap_agent_identity") {
68231
68930
  return bootstrapAgentIdentity(payload, access, transport);
68232
68931
  }
@@ -68288,7 +68987,11 @@ async function callNetworkToolWithinExecution(definition, payload, access, trans
68288
68987
  access.credential.source,
68289
68988
  access.configuration.issue
68290
68989
  );
68291
- const result = definition.name === "get_connection_status" && localConfigurationError ? { ok: false, status: 0, error: localConfigurationError } : await callRemembrance(definition, payload, { access, transport });
68990
+ const result = definition.name === "get_connection_status" && localConfigurationError ? { ok: false, status: 0, error: localConfigurationError } : await callRemembrance(definition, payload, {
68991
+ access,
68992
+ transport,
68993
+ ...["get_review_comparison", "repair_review_draft"].includes(definition.name) ? { redirect: "manual" } : {}
68994
+ });
68292
68995
  if (definition.name === "get_connection_status") {
68293
68996
  const status = localConnectionStatus(result, {
68294
68997
  apiBase: access.configuration.baseUrl,
@@ -68503,11 +69206,11 @@ function retryAfterDelayMs(value, nowMs = Date.now()) {
68503
69206
  Number(trimmed) * 1e3
68504
69207
  );
68505
69208
  }
68506
- const timestamp = Date.parse(trimmed);
68507
- if (!Number.isFinite(timestamp)) return null;
69209
+ const timestamp2 = Date.parse(trimmed);
69210
+ if (!Number.isFinite(timestamp2)) return null;
68508
69211
  return Math.min(
68509
69212
  PRIVATE_LEARNING_MAX_RETRY_DELAY_MS,
68510
- Math.max(0, timestamp - nowMs)
69213
+ Math.max(0, timestamp2 - nowMs)
68511
69214
  );
68512
69215
  }
68513
69216
  function privateLessonDestinationForAccess(access) {
@@ -68570,6 +69273,10 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
68570
69273
  });
68571
69274
  }
68572
69275
  let draft = await readPrivateSkillDraft(draftId);
69276
+ const resumingConfigurationHold = mode === "retry" && isPrivateSkillConfigurationHold(draft);
69277
+ if (isPrivateSkillConfigurationHold(draft) && !resumingConfigurationHold) {
69278
+ return privateSkillDraftActionResult2(draft, { status: "not_submitted" });
69279
+ }
68573
69280
  const destination = privateSkillDestinationForAccess(access);
68574
69281
  const resumingReinspectionHold = isPrivateSkillSubmissionReinspectionHold(draft);
68575
69282
  const resumingDestinationHold = isPrivateSkillDestinationHold(draft) && !isPrivateSkillDestinationRecoveryBlocked(draft, destination);
@@ -68582,10 +69289,10 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
68582
69289
  next_action: null
68583
69290
  });
68584
69291
  }
68585
- const resumingLocalHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution;
69292
+ const resumingLocalHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution || resumingConfigurationHold;
68586
69293
  const deferredDestinationProof = draft.state === "retry_scheduled" && draft.last_error_code === "private_skill_destination_audience_proof_unavailable";
68587
69294
  const awaitingDestinationCapability = isPrivateSkillDestinationCapabilityHold(draft) && !resumingResolution;
68588
- if ((mode === "retry" && !resumingResolution || deferredDestinationProof || resumingResolution && draft.state === "retry_scheduled") && !resumingReinspectionHold && !resumingDestinationHold && !awaitingDestinationCapability) {
69295
+ if ((mode === "retry" && !resumingResolution || deferredDestinationProof || resumingResolution && draft.state === "retry_scheduled") && !resumingReinspectionHold && !resumingDestinationHold && !resumingConfigurationHold && !awaitingDestinationCapability) {
68589
69296
  const retryGate = privateSkillRetryGate(draft);
68590
69297
  if (retryGate) {
68591
69298
  return privateSkillDraftActionResult2(draft, retryGate);
@@ -68614,7 +69321,8 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
68614
69321
  });
68615
69322
  }
68616
69323
  const reinspection = await reinspectPrivateSkillSubmissionCandidate(draftId, {
68617
- destination
69324
+ destination,
69325
+ resumeConfigurationHold: resumingConfigurationHold
68618
69326
  });
68619
69327
  draft = reinspection.draft;
68620
69328
  if (reinspection.status === "held") {
@@ -68927,6 +69635,16 @@ async function holdPrivateSkillDestination(draft, errorCode) {
68927
69635
  async function persistPrivateSkillFailure(draft, result, destinationBodyLimit) {
68928
69636
  return updatePrivateSkillDraft(draft.draft_id, (current) => {
68929
69637
  const attempts = current.attempts;
69638
+ const failure = remembranceMcpToolFailure(result, "propose_private_skill");
69639
+ if (failure && failure.http_status >= 500 && failure.http_status <= 599 && !failure.retryable) {
69640
+ return {
69641
+ ...current,
69642
+ state: "held_validation",
69643
+ next_retry_at: null,
69644
+ last_error_code: failure.code === PRIVATE_SKILL_CONFIGURATION_REFUSAL ? PRIVATE_SKILL_CONFIGURATION_REFUSAL : PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL,
69645
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
69646
+ };
69647
+ }
68930
69648
  if (destinationBodyLimit !== null) {
68931
69649
  const nextRetryAt = privateSkillRetryAt(attempts);
68932
69650
  return {
@@ -69255,7 +69973,8 @@ function privateSkillDraftActionResult2(draft, extra = {}) {
69255
69973
  last_error_code: draft.last_error_code,
69256
69974
  retained_locally: true,
69257
69975
  next_action: privateSkillDraftNextAction(draft),
69258
- ...extra
69976
+ ...extra,
69977
+ ...privateSkillPermanentRefusalGuidance(draft)
69259
69978
  };
69260
69979
  }
69261
69980
  function privateSkillDraftNextAction(draft) {
@@ -69693,8 +70412,8 @@ function privateLessonRetryGate(draft) {
69693
70412
  }
69694
70413
  function retryDue(nextRetryAt) {
69695
70414
  if (!nextRetryAt) return true;
69696
- const timestamp = Date.parse(nextRetryAt);
69697
- return !Number.isFinite(timestamp) || timestamp <= Date.now();
70415
+ const timestamp2 = Date.parse(nextRetryAt);
70416
+ return !Number.isFinite(timestamp2) || timestamp2 <= Date.now();
69698
70417
  }
69699
70418
  async function submitPrivateLessonHoldTelemetry(initialDraft, access, allowPolicyRefresh, transport) {
69700
70419
  let draft = initialDraft;
@@ -70856,6 +71575,9 @@ async function callRemembrance(definition, rawArguments, options) {
70856
71575
  throw new McpPublicError(configurationError);
70857
71576
  }
70858
71577
  const apiKey = credential.apiKey;
71578
+ if (definition.name === "repair_review_draft") {
71579
+ headers["Idempotency-Key"] = String(parsed.request_id);
71580
+ }
70859
71581
  if (apiKey) {
70860
71582
  headers["x-remembrance-api-key"] = apiKey;
70861
71583
  }
@@ -70899,6 +71621,7 @@ async function callRemembrance(definition, rawArguments, options) {
70899
71621
  let response;
70900
71622
  let body;
70901
71623
  let redirectRejected = false;
71624
+ let reviewWorkflowStatus = 0;
70902
71625
  try {
70903
71626
  const execute = async () => {
70904
71627
  const nextResponse = await transport.request(
@@ -70911,6 +71634,7 @@ async function callRemembrance(definition, rawArguments, options) {
70911
71634
  signal: controller.signal
70912
71635
  }
70913
71636
  );
71637
+ reviewWorkflowStatus = nextResponse.status;
70914
71638
  if (options.redirect === "manual" && (nextResponse.redirected || nextResponse.status >= 300 && nextResponse.status < 400)) {
70915
71639
  void nextResponse.body?.cancel().catch(() => void 0);
70916
71640
  return {
@@ -70925,7 +71649,13 @@ async function callRemembrance(definition, rawArguments, options) {
70925
71649
  let nextBody;
70926
71650
  try {
70927
71651
  nextBody = await readBoundedResponseJson(nextResponse);
71652
+ if (nextResponse.ok && ["get_review_comparison", "repair_review_draft"].includes(definition.name) && !reviewWorkflowResponseBound(definition.name, nextBody, parsed)) {
71653
+ throw new McpPublicError("The review response did not match this request.");
71654
+ }
70928
71655
  } catch {
71656
+ if (["get_review_comparison", "repair_review_draft"].includes(definition.name)) {
71657
+ throw new McpPublicError("The review response is unreadable or unbound.");
71658
+ }
70929
71659
  if (controller.signal.aborted) {
70930
71660
  throw new DOMException("Request timed out", "AbortError");
70931
71661
  }
@@ -70964,6 +71694,26 @@ async function callRemembrance(definition, rawArguments, options) {
70964
71694
  }
70965
71695
  }
70966
71696
  } catch (error) {
71697
+ if (definition.name === "repair_review_draft") {
71698
+ return {
71699
+ ok: false,
71700
+ status: reviewWorkflowStatus,
71701
+ error: "The review repair outcome is unknown. Reconcile by repeating only this exact request with the same request_id; do not create another replacement.",
71702
+ body: {
71703
+ code: "review_repair_outcome_unknown",
71704
+ delivery: "unknown",
71705
+ request_id: parsed.request_id,
71706
+ next_action: "Keep the original and repeat only the identical request_id, capture and snapshot to recover the committed receipt. Do not change input or use a new ID while this outcome is unknown."
71707
+ }
71708
+ };
71709
+ }
71710
+ if (definition.name === "get_review_comparison") {
71711
+ return {
71712
+ ok: false,
71713
+ status: reviewWorkflowStatus,
71714
+ body: { code: "review_comparison_unreadable", error: "No valid comparison was returned for this exact review job. Keep it unchanged and read its current references again." }
71715
+ };
71716
+ }
70967
71717
  return {
70968
71718
  ok: false,
70969
71719
  status: 0,
@@ -70972,6 +71722,25 @@ async function callRemembrance(definition, rawArguments, options) {
70972
71722
  } finally {
70973
71723
  clearTimeout(timeout);
70974
71724
  }
71725
+ if (["get_review_comparison", "repair_review_draft"].includes(definition.name) && (!response.ok || redirectRejected)) {
71726
+ const failure = remembranceMcpToolFailure({
71727
+ ok: false,
71728
+ status: response.status,
71729
+ body,
71730
+ retry_after: response.headers.get("retry-after"),
71731
+ redirect_rejected: redirectRejected
71732
+ }, definition.name);
71733
+ body = {
71734
+ error: failure?.message ?? "The review operation failed.",
71735
+ code: failure?.code ?? "review_workflow_failed",
71736
+ retryable: failure?.retryable ?? false,
71737
+ delivery: failure?.delivery ?? "unknown",
71738
+ ...definition.name === "repair_review_draft" ? {
71739
+ request_id: parsed.request_id,
71740
+ next_action: "If delivery is unknown, repeat only the identical request_id, capture and snapshot to reconcile it. Never create a new replacement for an unresolved write."
71741
+ } : {}
71742
+ };
71743
+ }
70975
71744
  const verifiedBody = definition.name === "get_value_proof" && response.ok ? await verifySignedValueProofWithKeyRefresh(
70976
71745
  body,
70977
71746
  (forceRefresh) => fetchValueProofKeySet(forceRefresh, access, transport)
@@ -71490,7 +72259,7 @@ function endpointFor(definition, payload) {
71490
72259
  const query2 = privateLessonPolicyQuery(payload);
71491
72260
  return query2 ? `${endpoint}?${query2}` : endpoint;
71492
72261
  }
71493
- const queryKeys = definition.name === "list_skills" ? ["q", "slug", "cursor", "limit"] : ["query_id", "result_id"];
72262
+ const queryKeys = definition.name === "list_skills" ? ["q", "slug", "cursor", "limit"] : definition.name === "get_review_comparison" ? ["job_id", "review_provenance"] : ["query_id", "result_id"];
71494
72263
  for (const key of queryKeys) {
71495
72264
  const value = payload[key];
71496
72265
  if (typeof value === "string" && value || typeof value === "number" && Number.isFinite(value)) {