@remembrance-ai/opencode-plugin 0.2.2 → 0.2.4
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 +64 -6
- package/opencode.json +2 -2
- package/package.json +1 -1
- package/scripts/hook-core.mjs +1405 -396
- package/servers/remembrance-mcp.mjs +798 -176
- package/skills/remembrancer/SKILL.md +13 -0
- package/skills/remembrancer/references/remembrance-setup.md +864 -150
- package/src/index.mjs +74 -29
|
@@ -738,8 +738,8 @@ var ZodIssueCode = util.arrayToEnum([
|
|
|
738
738
|
"not_finite"
|
|
739
739
|
]);
|
|
740
740
|
var quotelessJson = (obj) => {
|
|
741
|
-
const
|
|
742
|
-
return
|
|
741
|
+
const json2 = JSON.stringify(obj, null, 2);
|
|
742
|
+
return json2.replace(/"([^"]+)":/g, "$1:");
|
|
743
743
|
};
|
|
744
744
|
var ZodError = class _ZodError extends Error {
|
|
745
745
|
get errors() {
|
|
@@ -12058,7 +12058,7 @@ function findIndependentlyEncodedPrivateKeyFrameProof(tokens, metrics) {
|
|
|
12058
12058
|
const recoverableLength = recoverableProof?.length ?? null;
|
|
12059
12059
|
const length = completeLength ?? recoverableLength;
|
|
12060
12060
|
if (length === null) continue;
|
|
12061
|
-
const
|
|
12061
|
+
const continuation2 = recoverableProof?.basis === "factors" ? independentlyEncodedRsaCrtContinuationRanges(
|
|
12062
12062
|
tokens,
|
|
12063
12063
|
frames,
|
|
12064
12064
|
bytes,
|
|
@@ -12073,10 +12073,10 @@ function findIndependentlyEncodedPrivateKeyFrameProof(tokens, metrics) {
|
|
|
12073
12073
|
bytes,
|
|
12074
12074
|
encoding,
|
|
12075
12075
|
frames,
|
|
12076
|
-
continuationRanges:
|
|
12076
|
+
continuationRanges: continuation2.ranges,
|
|
12077
12077
|
start: frame.start,
|
|
12078
12078
|
end: frame.start + length,
|
|
12079
|
-
ambiguous:
|
|
12079
|
+
ambiguous: continuation2.ambiguous,
|
|
12080
12080
|
complete: completeLength !== null,
|
|
12081
12081
|
factorBacked: recoverableProof?.basis === "factors",
|
|
12082
12082
|
recoverable: completeLength === null
|
|
@@ -14713,19 +14713,19 @@ function recordCryptographicMatchedTerminalOwnership(tokens, assessment, metrics
|
|
|
14713
14713
|
}
|
|
14714
14714
|
function matchedTerminalSourcePieceRanges(tokens, assessment) {
|
|
14715
14715
|
const sourceStart = assessment.sourcePieceRanges[0].start;
|
|
14716
|
-
const
|
|
14716
|
+
const continuation2 = assessment.rsaCrtContinuations.filter(
|
|
14717
14717
|
(candidate) => candidate.start === sourceStart && candidate.status === "match" && candidate.mismatchAt === null
|
|
14718
14718
|
).sort((left, right) => right.matchedEnd - left.matchedEnd)[0];
|
|
14719
|
-
if (!
|
|
14719
|
+
if (!continuation2) return [];
|
|
14720
14720
|
const ranges = [];
|
|
14721
14721
|
for (const [pieceIndex, token] of tokens.entries()) {
|
|
14722
14722
|
const source = assessment.sourcePieceRanges[pieceIndex];
|
|
14723
|
-
if (source.end <=
|
|
14723
|
+
if (source.end <= continuation2.matchedEnd) {
|
|
14724
14724
|
ranges.push({ pieceIndex, start: 0, end: token.value.length });
|
|
14725
14725
|
continue;
|
|
14726
14726
|
}
|
|
14727
|
-
if (source.start >=
|
|
14728
|
-
const matchedLength =
|
|
14727
|
+
if (source.start >= continuation2.matchedEnd) continue;
|
|
14728
|
+
const matchedLength = continuation2.matchedEnd - source.start;
|
|
14729
14729
|
if (matchedLength > 0 && /^=+$/u.test(token.value.slice(matchedLength))) {
|
|
14730
14730
|
ranges.push({ pieceIndex, start: 0, end: token.value.length });
|
|
14731
14731
|
}
|
|
@@ -15604,13 +15604,13 @@ function assessEncodedPieceSequence(pieces, textOf, metrics, requireBoundedRecov
|
|
|
15604
15604
|
(completeRange) => completeRange.start < end && start < completeRange.end
|
|
15605
15605
|
);
|
|
15606
15606
|
const authenticatedFactorRange = scanned.rsaCrtContinuations.some(
|
|
15607
|
-
(
|
|
15608
|
-
const ownedEnd = Math.min(end,
|
|
15609
|
-
if (
|
|
15607
|
+
(continuation2) => {
|
|
15608
|
+
const ownedEnd = Math.min(end, continuation2.matchedEnd);
|
|
15609
|
+
if (continuation2.start >= ownedEnd || start >= continuation2.matchedEnd) {
|
|
15610
15610
|
return false;
|
|
15611
15611
|
}
|
|
15612
|
-
if (position.start <
|
|
15613
|
-
return ownedEnd - Math.max(position.start,
|
|
15612
|
+
if (position.start < continuation2.factorEnd) return true;
|
|
15613
|
+
return ownedEnd - Math.max(position.start, continuation2.factorEnd) >= continuation2.minimumAuthenticatedCharacters;
|
|
15614
15614
|
}
|
|
15615
15615
|
);
|
|
15616
15616
|
if (!authoritativeComplete2 && !authenticatedFactorRange) continue;
|
|
@@ -15774,7 +15774,7 @@ function encodedAssessmentHasMatchedCrtContinuationThroughEnd(assessment, pieceC
|
|
|
15774
15774
|
const sourceStart = assessment.sourcePieceRanges[0].start;
|
|
15775
15775
|
const sourceEnd = assessment.sourcePieceRanges[pieceCount - 1].end;
|
|
15776
15776
|
return assessment.rsaCrtContinuations.some(
|
|
15777
|
-
(
|
|
15777
|
+
(continuation2) => continuation2.start === sourceStart && continuation2.status === "match" && continuation2.mismatchAt === null && continuation2.matchedEnd <= sourceEnd && sourceEnd - continuation2.matchedEnd <= MAX_ADJACENT_ENCODED_PREFIX_CHARACTERS
|
|
15778
15778
|
);
|
|
15779
15779
|
}
|
|
15780
15780
|
function encodedAssessmentOwnsEverySourcePiece(assessment, pieceCount) {
|
|
@@ -15796,7 +15796,7 @@ function encodedAssessmentOwnsEverySourcePiece(assessment, pieceCount) {
|
|
|
15796
15796
|
}
|
|
15797
15797
|
const terminalSource = assessment.sourcePieceRanges[terminalIndex];
|
|
15798
15798
|
return assessment.rsaCrtContinuations.some(
|
|
15799
|
-
(
|
|
15799
|
+
(continuation2) => continuation2.status === "match" && continuation2.mismatchAt === null && continuation2.factorEnd < terminalSource.end && continuation2.matchedEnd === terminalSource.end
|
|
15800
15800
|
);
|
|
15801
15801
|
}
|
|
15802
15802
|
function encodedAssessmentAllowsFactorOmission(assessment, pieceIndex) {
|
|
@@ -15807,11 +15807,11 @@ function encodedAssessmentAllowsFactorOmission(assessment, pieceIndex) {
|
|
|
15807
15807
|
)) {
|
|
15808
15808
|
return false;
|
|
15809
15809
|
}
|
|
15810
|
-
return assessment.rsaCrtContinuations.every((
|
|
15811
|
-
if (piece.end <=
|
|
15810
|
+
return assessment.rsaCrtContinuations.every((continuation2) => {
|
|
15811
|
+
if (piece.end <= continuation2.start || piece.start >= continuation2.end) {
|
|
15812
15812
|
return true;
|
|
15813
15813
|
}
|
|
15814
|
-
return
|
|
15814
|
+
return continuation2.mismatchAt !== null && continuation2.mismatchAt < piece.end && continuation2.matchedEnd <= piece.start;
|
|
15815
15815
|
});
|
|
15816
15816
|
}
|
|
15817
15817
|
function encodedAssessmentAllowsRecognizableFactorOmission(assessment, pieceIndex) {
|
|
@@ -15819,11 +15819,11 @@ function encodedAssessmentAllowsRecognizableFactorOmission(assessment, pieceInde
|
|
|
15819
15819
|
return true;
|
|
15820
15820
|
}
|
|
15821
15821
|
const piece = assessment.sourcePieceRanges[pieceIndex];
|
|
15822
|
-
return assessment.rsaCrtContinuations.every((
|
|
15823
|
-
if (piece.end <=
|
|
15822
|
+
return assessment.rsaCrtContinuations.every((continuation2) => {
|
|
15823
|
+
if (piece.end <= continuation2.start || piece.start >= continuation2.end) {
|
|
15824
15824
|
return true;
|
|
15825
15825
|
}
|
|
15826
|
-
return
|
|
15826
|
+
return continuation2.factorEnd <= piece.start && (continuation2.matchedEnd <= piece.start || continuation2.mismatchAt !== null && continuation2.mismatchAt < piece.end);
|
|
15827
15827
|
});
|
|
15828
15828
|
}
|
|
15829
15829
|
function encodedAssessmentStartsAtSource(assessment) {
|
|
@@ -17368,7 +17368,7 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
|
|
|
17368
17368
|
if (recoverableProof?.basis === "factors") {
|
|
17369
17369
|
const sourceStart = offsets ? offsets[cursor] : cursor;
|
|
17370
17370
|
const sourceEnd = offsets ? offsets[segment.end - 1] + 1 : segment.end;
|
|
17371
|
-
const
|
|
17371
|
+
const continuation2 = rsaPrivateKeyCrtContinuationConsistency(
|
|
17372
17372
|
recoverableProof,
|
|
17373
17373
|
text,
|
|
17374
17374
|
cursor,
|
|
@@ -17385,9 +17385,9 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
|
|
|
17385
17385
|
bitOffset
|
|
17386
17386
|
);
|
|
17387
17387
|
const sourceFactorEnd = offsets ? offsets[exactEnd - 1] + 1 : exactEnd;
|
|
17388
|
-
const sourceMatchedEnd = offsets ? offsets[
|
|
17388
|
+
const sourceMatchedEnd = offsets ? offsets[continuation2.matchedEnd - 1] + 1 : continuation2.matchedEnd;
|
|
17389
17389
|
const minimumAuthenticatedCharacters = minimumRsaCrtContinuationSourceCharacters(framing);
|
|
17390
|
-
const authenticatedMatchedEnd =
|
|
17390
|
+
const authenticatedMatchedEnd = continuation2.matchedEnd - exactEnd >= minimumAuthenticatedCharacters ? continuation2.matchedEnd : exactEnd;
|
|
17391
17391
|
matchedFactorEnd = Math.max(exactEnd, authenticatedMatchedEnd);
|
|
17392
17392
|
rsaCrtContinuations.push({
|
|
17393
17393
|
start: sourceStart,
|
|
@@ -17395,8 +17395,8 @@ function scanEncodedPrivateKeyRanges(value, metrics, allowAdjacentPrefix = true,
|
|
|
17395
17395
|
factorEnd: sourceFactorEnd,
|
|
17396
17396
|
matchedEnd: sourceMatchedEnd,
|
|
17397
17397
|
minimumAuthenticatedCharacters,
|
|
17398
|
-
mismatchAt:
|
|
17399
|
-
status:
|
|
17398
|
+
mismatchAt: continuation2.mismatchAt === null ? null : offsets ? offsets[continuation2.mismatchAt] : continuation2.mismatchAt,
|
|
17399
|
+
status: continuation2.status
|
|
17400
17400
|
});
|
|
17401
17401
|
}
|
|
17402
17402
|
const exactFactorEnd = recoverableProof?.basis === "factors" && recoverableLength !== null ? encodedPrivateKeyInteriorEnd(
|
|
@@ -20857,8 +20857,8 @@ function formattedEncodedPrivateKeyRanges(value, metrics, directStrongRanges, ha
|
|
|
20857
20857
|
ranges.push(
|
|
20858
20858
|
...subtractTextRanges(jsonArrays.failClosed, excludedAssemblyRanges)
|
|
20859
20859
|
);
|
|
20860
|
-
for (const
|
|
20861
|
-
const candidates = assemblyPieces(
|
|
20860
|
+
for (const json2 of jsonArrays.groups) {
|
|
20861
|
+
const candidates = assemblyPieces(json2, true);
|
|
20862
20862
|
append(
|
|
20863
20863
|
strongFormattedPieceRanges(
|
|
20864
20864
|
candidates,
|
|
@@ -21891,7 +21891,7 @@ function strictIndependentPrivateSourceRanges(scope, metrics, document) {
|
|
|
21891
21891
|
);
|
|
21892
21892
|
claims.push({ token: frame.token, ...range });
|
|
21893
21893
|
}
|
|
21894
|
-
const
|
|
21894
|
+
const continuation2 = complete ? completeRsaPrivateKeyCopies(
|
|
21895
21895
|
scope,
|
|
21896
21896
|
frames,
|
|
21897
21897
|
bytes,
|
|
@@ -21912,16 +21912,16 @@ function strictIndependentPrivateSourceRanges(scope, metrics, document) {
|
|
|
21912
21912
|
tokenIndexes,
|
|
21913
21913
|
metrics
|
|
21914
21914
|
) : completion;
|
|
21915
|
-
if (!
|
|
21916
|
-
if (
|
|
21915
|
+
if (!continuation2) continue;
|
|
21916
|
+
if (continuation2.ambiguous || detachedRsaContinuationReadsSpent(metrics) > MAX_DETACHED_RSA_CONTINUATION_READS) {
|
|
21917
21917
|
for (const frame of frames) {
|
|
21918
21918
|
metrics.ownershipSteps += 1;
|
|
21919
21919
|
claims.push(wholeTokenSourceRange(frame.token));
|
|
21920
21920
|
}
|
|
21921
|
-
claims.push(...
|
|
21922
|
-
if (
|
|
21921
|
+
claims.push(...continuation2.closed);
|
|
21922
|
+
if (continuation2.ambiguous) continue;
|
|
21923
21923
|
}
|
|
21924
|
-
for (const range of
|
|
21924
|
+
for (const range of continuation2.ranges) {
|
|
21925
21925
|
if (range.token === detached) continue;
|
|
21926
21926
|
claims.push(range);
|
|
21927
21927
|
}
|
|
@@ -23727,23 +23727,197 @@ function remembranceMcpToolSecurity(name) {
|
|
|
23727
23727
|
return REMEMBRANCE_MCP_TOOL_SECURITY[name];
|
|
23728
23728
|
}
|
|
23729
23729
|
|
|
23730
|
+
// ../core/src/private-submission-approval.ts
|
|
23731
|
+
var tools = REMEMBRANCE_MCP_PRIVATE_LEARNING_NETWORK_ACTIONS;
|
|
23732
|
+
var PRIVATE_SUBMISSION_LOCAL_CAPTURE_TOOL = "capture_learning";
|
|
23733
|
+
var PRIVATE_SUBMISSION_LOCAL_CAPTURE_NOTE = "capture_learning stays on this machine and sends nothing";
|
|
23734
|
+
var capture = PRIVATE_SUBMISSION_LOCAL_CAPTURE_TOOL;
|
|
23735
|
+
var withCapture = [...tools, capture];
|
|
23736
|
+
var hostedTools = tools.filter(
|
|
23737
|
+
(tool) => !REMEMBRANCE_MCP_LOCAL_ONLY_TOOLS.includes(tool)
|
|
23738
|
+
);
|
|
23739
|
+
var localOnlyComment = `# Local only: ${PRIVATE_SUBMISSION_LOCAL_CAPTURE_NOTE}.`;
|
|
23740
|
+
var PRIVATE_SUBMISSION_CONFIRMED_DELETE_TOOLS = Object.freeze([
|
|
23741
|
+
"delete_private_lesson_candidate",
|
|
23742
|
+
"delete_private_skill_candidate"
|
|
23743
|
+
]);
|
|
23744
|
+
var isConfirmedDelete = (tool) => PRIVATE_SUBMISSION_CONFIRMED_DELETE_TOOLS.includes(
|
|
23745
|
+
tool
|
|
23746
|
+
);
|
|
23747
|
+
var GEMINI_ADMIN_ALLOWED_TOOLS = Object.freeze(
|
|
23748
|
+
REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS.filter(
|
|
23749
|
+
(tool) => !isConfirmedDelete(tool)
|
|
23750
|
+
)
|
|
23751
|
+
);
|
|
23752
|
+
var json = (value) => JSON.stringify(value, null, 2);
|
|
23753
|
+
var approveTables = (server, names = tools) => names.map((tool) => `[${server}.tools.${tool}]
|
|
23754
|
+
approval_mode = "approve"`).join("\n\n");
|
|
23755
|
+
var geminiRule = (tool, decision = "allow") => `[[rule]]
|
|
23756
|
+
mcpName = "remembrance"
|
|
23757
|
+
toolName = "${tool}"
|
|
23758
|
+
decision = "${decision}"
|
|
23759
|
+
priority = 200`;
|
|
23760
|
+
var claudeCodePluginTools = withCapture.map(
|
|
23761
|
+
(tool) => `mcp__plugin_remembrance_remembrance__${tool}`
|
|
23762
|
+
);
|
|
23763
|
+
var codexPluginServer = 'plugins."remembrance@remembrance".mcp_servers.remembrance';
|
|
23764
|
+
var PRIVATE_SUBMISSION_APPROVAL_SNIPPETS = Object.freeze({
|
|
23765
|
+
claudeCodePlugin: json({ permissions: { allow: claudeCodePluginTools } }),
|
|
23766
|
+
// Managed approval for the plugin's local server: the force-enable and the
|
|
23767
|
+
// allow rules only. The optional lockdown keys are separate because they
|
|
23768
|
+
// change much more than approval.
|
|
23769
|
+
claudeCodeManagedPlugin: json({
|
|
23770
|
+
enabledPlugins: { "remembrance@remembrance": true },
|
|
23771
|
+
permissions: { allow: claudeCodePluginTools }
|
|
23772
|
+
}),
|
|
23773
|
+
claudeCodeManagedLockdown: json({
|
|
23774
|
+
strictKnownMarketplaces: [
|
|
23775
|
+
{ source: "github", repo: "dreamarkinc/remembrance-skills" }
|
|
23776
|
+
],
|
|
23777
|
+
allowManagedHooksOnly: true
|
|
23778
|
+
}),
|
|
23779
|
+
// A local standalone server named `remembrance`.
|
|
23780
|
+
claudeCodeServer: json({
|
|
23781
|
+
permissions: {
|
|
23782
|
+
allow: withCapture.map((tool) => `mcp__remembrance__${tool}`)
|
|
23783
|
+
}
|
|
23784
|
+
}),
|
|
23785
|
+
// Hosted MCP, including the managed-mcp.json path.
|
|
23786
|
+
claudeCodeHosted: json({
|
|
23787
|
+
permissions: {
|
|
23788
|
+
allow: hostedTools.map((tool) => `mcp__remembrance__${tool}`)
|
|
23789
|
+
}
|
|
23790
|
+
}),
|
|
23791
|
+
codexPlugin: approveTables(codexPluginServer),
|
|
23792
|
+
codexManualServer: approveTables("mcp_servers.remembrance"),
|
|
23793
|
+
// Optional and separate: Codex asks before capture_learning only under the
|
|
23794
|
+
// managed `writes` mode, and an `approve` table skips Auto-review.
|
|
23795
|
+
codexPluginCapture: [
|
|
23796
|
+
localOnlyComment,
|
|
23797
|
+
"# Approving it also skips Auto-review for the lesson it captures.",
|
|
23798
|
+
approveTables(codexPluginServer, [capture])
|
|
23799
|
+
].join("\n"),
|
|
23800
|
+
cursorIde: json({
|
|
23801
|
+
mcpAllowlist: withCapture.map((tool) => `remembrance:${tool}`)
|
|
23802
|
+
}),
|
|
23803
|
+
cursorCli: json({
|
|
23804
|
+
permissions: {
|
|
23805
|
+
allow: withCapture.map((tool) => `Mcp(remembrance:${tool})`)
|
|
23806
|
+
}
|
|
23807
|
+
}),
|
|
23808
|
+
openCode: json({
|
|
23809
|
+
permission: Object.fromEntries(
|
|
23810
|
+
withCapture.map((tool) => [`remembrance_${tool}`, "allow"])
|
|
23811
|
+
)
|
|
23812
|
+
}),
|
|
23813
|
+
openClaw: json({
|
|
23814
|
+
plugins: {
|
|
23815
|
+
entries: {
|
|
23816
|
+
remembrance: {
|
|
23817
|
+
config: {
|
|
23818
|
+
privateLearningEgressApprovals: Object.fromEntries(
|
|
23819
|
+
tools.map((tool) => [
|
|
23820
|
+
REMEMBRANCE_MCP_TOOL_SECURITY[tool].consent_class,
|
|
23821
|
+
true
|
|
23822
|
+
])
|
|
23823
|
+
)
|
|
23824
|
+
}
|
|
23825
|
+
}
|
|
23826
|
+
}
|
|
23827
|
+
}
|
|
23828
|
+
}),
|
|
23829
|
+
geminiCli: [
|
|
23830
|
+
...tools.map((tool) => geminiRule(tool)),
|
|
23831
|
+
`${localOnlyComment}
|
|
23832
|
+
${geminiRule(capture)}`
|
|
23833
|
+
].join("\n\n"),
|
|
23834
|
+
// The managed recipe's admin policy file. It holds the step's own rules
|
|
23835
|
+
// above exactly once, so administrators use it instead of them.
|
|
23836
|
+
geminiCliAdmin: [
|
|
23837
|
+
[
|
|
23838
|
+
"# One exact rule per tool in includeTools: allow, except the two",
|
|
23839
|
+
"# confirmed-delete tools, which ask. To make a tool ask, change its",
|
|
23840
|
+
'# decision to "ask_user" rather than deleting its rule: an admin ask',
|
|
23841
|
+
"# outranks users' own allow rules, and without one a user's allow decides."
|
|
23842
|
+
].join("\n"),
|
|
23843
|
+
...REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS.map((tool) => {
|
|
23844
|
+
if (isConfirmedDelete(tool)) return geminiRule(tool, "ask_user");
|
|
23845
|
+
if (tool === capture) return `${localOnlyComment}
|
|
23846
|
+
${geminiRule(tool)}`;
|
|
23847
|
+
return geminiRule(tool);
|
|
23848
|
+
})
|
|
23849
|
+
].join("\n\n")
|
|
23850
|
+
});
|
|
23851
|
+
|
|
23852
|
+
// ../core/src/private-skill-completion.ts
|
|
23853
|
+
var PRIVATE_SKILL_COMPLETION_VERSION = "private-skill-completion-v1";
|
|
23854
|
+
var opaqueId = external_exports.string().min(1).max(MAX_SHORT_TEXT_LENGTH);
|
|
23855
|
+
var privateSkillCompletionRevisionIdSchema = external_exports.string().regex(/^pscr_[a-f0-9]{18}$/u);
|
|
23856
|
+
var privateSkillCompletionRequestIdSchema = external_exports.string().regex(/^pscc_[a-f0-9]{32}$/u);
|
|
23857
|
+
var privateSkillCompletionStatusRequestSchema = external_exports.object({
|
|
23858
|
+
contract_version: external_exports.literal(PRIVATE_SKILL_COMPLETION_VERSION),
|
|
23859
|
+
public_id: opaqueId
|
|
23860
|
+
}).strict();
|
|
23861
|
+
var privateSkillCompletionSourceRequestSchema = privateSkillCompletionStatusRequestSchema.extend({
|
|
23862
|
+
revision_id: privateSkillCompletionRevisionIdSchema
|
|
23863
|
+
}).strict();
|
|
23864
|
+
var privateSkillCompletionApprovedSourceSchema = privateSkillIdeaRequestSchema.omit({ agent: true, idempotency_key: true, enterprise_encryption: true }).strict();
|
|
23865
|
+
var privateSkillCompletionSourceResponseSchema = privateSkillCompletionSourceRequestSchema.extend({
|
|
23866
|
+
capture: privateSkillCompletionApprovedSourceSchema.describe("Current approved submission; proposed_skill_md may be null or absent. New revisions still require a complete skill body.")
|
|
23867
|
+
}).strict();
|
|
23868
|
+
var privateSkillCompletionRequestStatusSchema = privateSkillCompletionStatusRequestSchema.extend({
|
|
23869
|
+
request_id: privateSkillCompletionRequestIdSchema
|
|
23870
|
+
}).strict();
|
|
23871
|
+
var continuation = privateSkillCompletionRequestStatusSchema.extend({
|
|
23872
|
+
expected: external_exports.object({
|
|
23873
|
+
completion_id: opaqueId,
|
|
23874
|
+
revision_id: privateSkillCompletionRevisionIdSchema,
|
|
23875
|
+
version: external_exports.number().int().nonnegative()
|
|
23876
|
+
}).strict()
|
|
23877
|
+
});
|
|
23878
|
+
var revisedCapture = privateSkillCaptureSchema.superRefine((capture2, context) => {
|
|
23879
|
+
const pending = [{ value: capture2.proposed_metadata, path: ["proposed_metadata"] }];
|
|
23880
|
+
while (pending.length) {
|
|
23881
|
+
const { value, path } = pending.pop();
|
|
23882
|
+
if (!value || typeof value !== "object") continue;
|
|
23883
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
23884
|
+
if (key.startsWith("_remembrance_")) {
|
|
23885
|
+
context.addIssue({ code: "custom", path: [...path, key], message: "Server provenance fields are reserved." });
|
|
23886
|
+
return;
|
|
23887
|
+
}
|
|
23888
|
+
pending.push({ value: entry, path: [...path, key] });
|
|
23889
|
+
}
|
|
23890
|
+
}
|
|
23891
|
+
});
|
|
23892
|
+
var privateSkillCompletionContinuationSchema = external_exports.discriminatedUnion("operation", [
|
|
23893
|
+
continuation.extend({ operation: external_exports.literal("declare_intent"), intent: external_exports.literal("skill_output") }).strict(),
|
|
23894
|
+
continuation.extend({ operation: external_exports.literal("revise"), capture: revisedCapture }).strict(),
|
|
23895
|
+
continuation.extend({ operation: external_exports.literal("resume"), mode: external_exports.literal("changed_revision"), deadline_at: external_exports.number().int().positive() }).strict()
|
|
23896
|
+
]);
|
|
23897
|
+
|
|
23730
23898
|
// ../core/src/seed.ts
|
|
23731
23899
|
var siteUrl = "https://remembrance.dev";
|
|
23732
23900
|
var feedbackUrl = `${siteUrl}/api/v1/agent/remembrances`;
|
|
23733
|
-
var
|
|
23734
|
-
|
|
23735
|
-
|
|
23736
|
-
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
(tool) => ` ${JSON.stringify(`mcp__remembrance__${tool}`)},`
|
|
23741
|
-
).join("\n");
|
|
23901
|
+
var jsonItems = (values, indent) => values.map((value) => `${indent}${JSON.stringify(value)}`).join(",\n");
|
|
23902
|
+
var recommendedClaudeToolJson = jsonItems(
|
|
23903
|
+
REMEMBRANCE_MCP_RECOMMENDED_ORG_TOOLS.map(
|
|
23904
|
+
(tool) => `mcp__remembrance__${tool}`
|
|
23905
|
+
),
|
|
23906
|
+
" "
|
|
23907
|
+
);
|
|
23742
23908
|
var recommendedLocalOrganizationToolToml = REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS.map(
|
|
23743
23909
|
(tool) => ` ${JSON.stringify(tool)},`
|
|
23744
23910
|
).join("\n");
|
|
23745
|
-
var
|
|
23746
|
-
|
|
23911
|
+
var geminiIncludeToolJson = jsonItems(
|
|
23912
|
+
REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS,
|
|
23913
|
+
" "
|
|
23914
|
+
);
|
|
23915
|
+
var openClawToolFilterJson = jsonItems(
|
|
23916
|
+
REMEMBRANCE_MCP_RECOMMENDED_LOCAL_ORG_TOOLS,
|
|
23917
|
+
" "
|
|
23918
|
+
);
|
|
23919
|
+
var privateSubmissionToolList = REMEMBRANCE_MCP_PRIVATE_LEARNING_NETWORK_ACTIONS.map(
|
|
23920
|
+
(tool) => `- \`${tool}\``
|
|
23747
23921
|
).join("\n");
|
|
23748
23922
|
var SKILL_INSTALL_COMMAND = "npx skills add dreamarkinc/remembrance-skills --skill remembrancer";
|
|
23749
23923
|
var skillInstallCommand = SKILL_INSTALL_COMMAND;
|
|
@@ -23828,7 +24002,7 @@ var seedSkills = [
|
|
|
23828
24002
|
summary: "Operational setup and troubleshooting workflow for Remembrance across Claude Code, Codex, OpenClaw, Cursor, Gemini, MCP, REST, skill-only installs, enterprise keys, and local agent identity.",
|
|
23829
24003
|
status: "active",
|
|
23830
24004
|
visibility: "public",
|
|
23831
|
-
version: "0.1.
|
|
24005
|
+
version: "0.1.39",
|
|
23832
24006
|
domains: ["agent-skills", "mcp", "resource-discovery"],
|
|
23833
24007
|
tags: [
|
|
23834
24008
|
"remembrance",
|
|
@@ -23879,7 +24053,7 @@ var seedSkills = [
|
|
|
23879
24053
|
"gemini",
|
|
23880
24054
|
"rest"
|
|
23881
24055
|
],
|
|
23882
|
-
version: "0.1.
|
|
24056
|
+
version: "0.1.39",
|
|
23883
24057
|
status: "active",
|
|
23884
24058
|
visibility: "public",
|
|
23885
24059
|
providers: ["codex", "claude", "cursor", "openclaw", "generic"],
|
|
@@ -23922,7 +24096,8 @@ var seedSkills = [
|
|
|
23922
24096
|
},
|
|
23923
24097
|
contraindications: [
|
|
23924
24098
|
"Do not ask the user to paste raw API keys, private key material, tokens, cookies, or full config files containing secrets.",
|
|
23925
|
-
"Do not store org keys in public project files or submit them back to Remembrance."
|
|
24099
|
+
"Do not store org keys in public project files or submit them back to Remembrance.",
|
|
24100
|
+
"Do not change host approval or permission settings, or answer the host's approval of your own pending action, without the user's consent; ask the user (for managed settings, the administrator) first."
|
|
23926
24101
|
],
|
|
23927
24102
|
feedback_url: feedbackUrl,
|
|
23928
24103
|
install_command: skillInstallCommand,
|
|
@@ -23942,7 +24117,9 @@ var seedSkills = [
|
|
|
23942
24117
|
"OpenClaw ClawHub search can return unrelated remembrance-named packages; verify the official package points to dreamarkinc/remembrance-skills before installing.",
|
|
23943
24118
|
"Until allowConversationAccess is enabled, OpenClaw holds only the plugin's completion hook; the prompt, tool and subagent-end hooks already run, and the prompt hook can query the registry.",
|
|
23944
24119
|
"Cursor local and cloud distribution are separate: configure the team plugin and Team MCP, then verify hook and receipt behavior on each enabled surface.",
|
|
23945
|
-
"MCP tools can be missing when the client uses the wrong config shape for its runtime."
|
|
24120
|
+
"MCP tools can be missing when the client uses the wrong config shape for its runtime.",
|
|
24121
|
+
"Without persisted host approval for the four private submit and retry tools, an organization install on a host that asks before them stops every private lesson or skill submission for a manual approval, and unattended or headless runs deny it.",
|
|
24122
|
+
"On hosts that also ask before the local-only capture_learning, a headless run denies the capture itself unless its entry is approved, so no draft reaches the submit tools."
|
|
23946
24123
|
],
|
|
23947
24124
|
suggested_patches: [
|
|
23948
24125
|
"Add runtime-specific screenshots once each agent's plugin manager UI stabilizes.",
|
|
@@ -23969,6 +24146,8 @@ REST/HTTPS, skill-only installs, enterprise org keys, local identity, and common
|
|
|
23969
24146
|
propose_private_skill because it has no durable device outbox.
|
|
23970
24147
|
- A native plugin appears installed but hooks, trust prompts, or MCP tools do
|
|
23971
24148
|
not work.
|
|
24149
|
+
- An organization install stops for approval at every private lesson or skill
|
|
24150
|
+
submission, or an unattended or headless run denies it.
|
|
23972
24151
|
- A request fails with 401, 403, 404, 413, 422, 429, or a missing-key error.
|
|
23973
24152
|
|
|
23974
24153
|
## First decision
|
|
@@ -23982,6 +24161,11 @@ REST/HTTPS, skill-only installs, enterprise org keys, local identity, and common
|
|
|
23982
24161
|
5. Use the skills.sh entry skill only when the runtime can load filesystem
|
|
23983
24162
|
skills but not native plugins.
|
|
23984
24163
|
|
|
24164
|
+
With an organization key, a plugin or MCP install also needs the step in
|
|
24165
|
+
"Highly Recommended: approve private submissions" below; ask the user to apply
|
|
24166
|
+
it rather than changing host settings yourself. REST and skill-only installs
|
|
24167
|
+
have no MCP tools to approve.
|
|
24168
|
+
|
|
23985
24169
|
Raw MCP, REST, and skill-only paths do not have native Stop hooks. They must
|
|
23986
24170
|
self-check before finishing and submit \`type: "failure_report"\` remembrances
|
|
23987
24171
|
for reusable self-corrections, user-caught mistakes, CI/deploy failures, and
|
|
@@ -24085,51 +24269,6 @@ show the same review screen again; never use the automation-only trust bypass
|
|
|
24085
24269
|
for normal installation. Fully restart Codex, submit one prompt, use one
|
|
24086
24270
|
Remembrance tool, complete one turn, and run \`run_connection_doctor\`.
|
|
24087
24271
|
|
|
24088
|
-
### Optional unattended routine feedback in Codex
|
|
24089
|
-
|
|
24090
|
-
After the user explicitly opts in, add only these two tool overrides to the
|
|
24091
|
-
user-level \`~/.codex/config.toml\`. This approval persists across future
|
|
24092
|
-
sessions on this installation until removed; installation alone does not grant
|
|
24093
|
-
it. Merge with existing tables rather than duplicating them:
|
|
24094
|
-
|
|
24095
|
-
~~~toml
|
|
24096
|
-
[plugins."remembrance@remembrance".mcp_servers.remembrance.tools.submit_query_feedback]
|
|
24097
|
-
approval_mode = "approve"
|
|
24098
|
-
|
|
24099
|
-
[plugins."remembrance@remembrance".mcp_servers.remembrance.tools.submit_feedback]
|
|
24100
|
-
approval_mode = "approve"
|
|
24101
|
-
~~~
|
|
24102
|
-
|
|
24103
|
-
Use this opt-in for an organization-authenticated local plugin whose
|
|
24104
|
-
\`submit_feedback\` schema is categorical and rejects \`lesson\`. Query-fit
|
|
24105
|
-
ratings send Remembrance-issued query/result IDs, categorical verdicts, and
|
|
24106
|
-
required reasons; post-use ratings send the skill slug, those correlation IDs, usefulness/rating,
|
|
24107
|
-
and stable idempotency. Keep optional notes and evidence out of routine
|
|
24108
|
-
ratings: do not automatically attach internal receipt hashes, task prose,
|
|
24109
|
-
source content, raw logs, or private URLs. Public substantive reports retain
|
|
24110
|
-
their separate evidence requirements; reusable private lessons use
|
|
24111
|
-
\`capture_learning\` and its exact returned action.
|
|
24112
|
-
|
|
24113
|
-
These are real writes, not read-only diagnostics. Post-use feedback can enter
|
|
24114
|
-
verification and incur processing cost under the existing organization policy.
|
|
24115
|
-
The two overrides do not approve private lesson/skill submission, publishing,
|
|
24116
|
-
deletion, reset, preference changes, or other tools. They do not widen the
|
|
24117
|
-
server's enabled tool set or override managed policy, guardian decisions,
|
|
24118
|
-
network restrictions, or organization processing grants. Do not set the whole
|
|
24119
|
-
server's approval default to \`approve\` for this purpose.
|
|
24120
|
-
|
|
24121
|
-
Tool overrides persist when authentication or schemas change. Remove or
|
|
24122
|
-
re-review both approvals before switching to anonymous or hosted transport,
|
|
24123
|
-
enabling legacy broad writes, or changing the organization or destination.
|
|
24124
|
-
|
|
24125
|
-
To revoke this opt-in, remove only these two tool-level approval entries;
|
|
24126
|
-
the inherited approval policy applies again. Reconnect the plugin or start a
|
|
24127
|
-
fresh Codex session if the current host does not reload config, then verify
|
|
24128
|
-
with a minimal eligible rating. A healthy connection doctor verifies the
|
|
24129
|
-
connection, not that host approval policy permits feedback. A denial means
|
|
24130
|
-
that rating was not submitted; acknowledge it locally and do not retry through
|
|
24131
|
-
another transport. See the [official installed-server policy guide](https://developers.openai.com/plugins/build/plugins#configure-installed-server-policy).
|
|
24132
|
-
|
|
24133
24272
|
OpenClaw:
|
|
24134
24273
|
|
|
24135
24274
|
~~~bash
|
|
@@ -24177,25 +24316,300 @@ Cursor plugin installs this Remembrancer skill, an always-apply Cursor rule, a
|
|
|
24177
24316
|
plugin-managed MCP server config, and hooks that ask for feedback only after
|
|
24178
24317
|
actual Remembrance MCP use.
|
|
24179
24318
|
|
|
24180
|
-
For local plugin testing before marketplace approval
|
|
24319
|
+
For local plugin testing before marketplace approval, copy the plugin into its
|
|
24320
|
+
own folder under Cursor's local plugin folder, then restart Cursor or run
|
|
24321
|
+
**Developer: Reload Window**:
|
|
24181
24322
|
|
|
24182
24323
|
~~~bash
|
|
24183
|
-
mkdir -p ~/.cursor/plugins/local
|
|
24184
|
-
|
|
24324
|
+
mkdir -p ~/.cursor/plugins/local/remembrance
|
|
24325
|
+
cp -R /absolute/path/to/remembrance/packages/cursor-plugin/. ~/.cursor/plugins/local/remembrance/
|
|
24185
24326
|
~~~
|
|
24186
24327
|
|
|
24328
|
+
Copy the files rather than linking them: Cursor skips a symbolic link that
|
|
24329
|
+
points to a plugin elsewhere on disk. On Teams and Enterprise, local plugins
|
|
24330
|
+
load only when an administrator allows **Allow Local Plugin Imports**, which is
|
|
24331
|
+
off by default on Enterprise.
|
|
24332
|
+
|
|
24187
24333
|
Cursor now documents conversation hooks for cloud agents, but a local plugin
|
|
24188
24334
|
install does not automatically provision the cloud surface. Distribute the
|
|
24189
|
-
plugin through the team marketplace, register Remembrance
|
|
24190
|
-
|
|
24191
|
-
receipts in both local and cloud runs.
|
|
24335
|
+
plugin through the team marketplace, register Remembrance as a Team MCP server
|
|
24336
|
+
under **Dashboard > Plugins & MCPs**, and verify query, invocation, feedback,
|
|
24337
|
+
and contribution receipts in both local and cloud runs.
|
|
24192
24338
|
|
|
24193
24339
|
After installing any native plugin, restart the agent app/session and approve
|
|
24194
24340
|
the runtime's trust request when one appears. For Codex, complete the hook
|
|
24195
24341
|
review above if Codex requests it; unchanged, previously trusted definitions
|
|
24196
24342
|
may not show another review screen. Changed hook definitions show the review
|
|
24197
24343
|
screen again. A currently running Codex or Claude thread usually cannot
|
|
24198
|
-
hot-load newly installed plugin tools.
|
|
24344
|
+
hot-load newly installed plugin tools. With an organization key, then ask the
|
|
24345
|
+
user to complete the Highly Recommended step below.
|
|
24346
|
+
|
|
24347
|
+
### Optional unattended routine feedback in Codex
|
|
24348
|
+
|
|
24349
|
+
After the user explicitly opts in, add only these two tool overrides to the
|
|
24350
|
+
user-level \`~/.codex/config.toml\`. This approval persists across future
|
|
24351
|
+
sessions on this installation until removed; installation alone does not grant
|
|
24352
|
+
it. Merge with existing tables rather than duplicating them:
|
|
24353
|
+
|
|
24354
|
+
~~~toml
|
|
24355
|
+
[plugins."remembrance@remembrance".mcp_servers.remembrance.tools.submit_query_feedback]
|
|
24356
|
+
approval_mode = "approve"
|
|
24357
|
+
|
|
24358
|
+
[plugins."remembrance@remembrance".mcp_servers.remembrance.tools.submit_feedback]
|
|
24359
|
+
approval_mode = "approve"
|
|
24360
|
+
~~~
|
|
24361
|
+
|
|
24362
|
+
Use this opt-in for an organization-authenticated local plugin whose
|
|
24363
|
+
\`submit_feedback\` schema is categorical and rejects \`lesson\`. Query-fit
|
|
24364
|
+
ratings send Remembrance-issued query/result IDs, categorical verdicts, and
|
|
24365
|
+
required reasons; post-use ratings send the skill slug, those correlation IDs, usefulness/rating,
|
|
24366
|
+
and stable idempotency. Keep optional notes and evidence out of routine
|
|
24367
|
+
ratings: do not automatically attach internal receipt hashes, task prose,
|
|
24368
|
+
source content, raw logs, or private URLs. Public substantive reports retain
|
|
24369
|
+
their separate evidence requirements; reusable private lessons use
|
|
24370
|
+
\`capture_learning\` and its exact returned action.
|
|
24371
|
+
|
|
24372
|
+
These are real writes, not read-only diagnostics. Post-use feedback can enter
|
|
24373
|
+
verification and incur processing cost under the existing organization policy.
|
|
24374
|
+
The two overrides do not approve private lesson/skill submission (the Highly
|
|
24375
|
+
Recommended step below covers that), publishing, deletion, reset, preference
|
|
24376
|
+
changes, or other tools. They do not widen the server's enabled tool set or
|
|
24377
|
+
override managed policy, network restrictions, or organization processing
|
|
24378
|
+
grants. They do skip the Codex approval prompt and its Auto-review (guardian)
|
|
24379
|
+
evaluation for these two tools. Do not set the whole server's approval default
|
|
24380
|
+
to \`approve\` for this purpose.
|
|
24381
|
+
|
|
24382
|
+
Tool overrides persist when authentication or schemas change. Remove or
|
|
24383
|
+
re-review both approvals before switching to anonymous or hosted transport,
|
|
24384
|
+
enabling legacy broad writes, or changing the organization or destination.
|
|
24385
|
+
|
|
24386
|
+
To revoke this opt-in, remove only these two tool-level approval entries;
|
|
24387
|
+
the inherited approval policy applies again. Reconnect the plugin or start a
|
|
24388
|
+
fresh Codex session if the current host does not reload config, then verify
|
|
24389
|
+
with a minimal eligible rating. A healthy connection doctor verifies the
|
|
24390
|
+
connection, not that host approval policy permits feedback. A denial means
|
|
24391
|
+
that rating was not submitted; acknowledge it locally and do not retry through
|
|
24392
|
+
another transport. See the [official installed-server policy guide](https://developers.openai.com/plugins/build/plugins#configure-installed-server-policy).
|
|
24393
|
+
|
|
24394
|
+
## Highly Recommended: approve private submissions
|
|
24395
|
+
|
|
24396
|
+
For organizations that use Remembrance with a private organization key, this
|
|
24397
|
+
step is required for Remembrance to do its job fully. Without it, on hosts that
|
|
24398
|
+
ask before these tools, every private lesson or skill submission stops for a
|
|
24399
|
+
manual approval, and unattended or headless runs deny it. Public-only use,
|
|
24400
|
+
without an organization key, does not need it.
|
|
24401
|
+
|
|
24402
|
+
Ask the user (for managed settings, the administrator) before applying this
|
|
24403
|
+
step. An agent never edits host permission or settings files without the
|
|
24404
|
+
user's consent, and never answers the host's approval of its own pending
|
|
24405
|
+
action.
|
|
24406
|
+
|
|
24407
|
+
Persist the host's approval for exactly these four local tools, the private
|
|
24408
|
+
submit and retry actions:
|
|
24409
|
+
|
|
24410
|
+
${privateSubmissionToolList}
|
|
24411
|
+
|
|
24412
|
+
Hosted MCP exposes only \`submit_private_lesson_candidate\` of the four, so
|
|
24413
|
+
approve only that one there. Each approval lets the agent send to the
|
|
24414
|
+
organization's private review queue without asking. On a local server that is
|
|
24415
|
+
normally a draft that \`capture_learning\` already prepared, although the
|
|
24416
|
+
lesson submit also accepts a lesson candidate the agent writes into the call;
|
|
24417
|
+
on hosted MCP, which has no \`capture_learning\`, the approved submit sends the
|
|
24418
|
+
lesson candidate the agent writes. These actions cannot publish public content.
|
|
24419
|
+
Never pre-approve \`delete_private_lesson_candidate\` or
|
|
24420
|
+
\`delete_private_skill_candidate\`, a whole server (\`mcp__<server>\` or
|
|
24421
|
+
\`mcp__<server>__*\`), \`bypassPermissions\`, Gemini CLI \`trust: true\` or
|
|
24422
|
+
\`mcp.allowed\`, or any global auto-approve.
|
|
24423
|
+
|
|
24424
|
+
Every local private submission starts with \`capture_learning\`, which writes
|
|
24425
|
+
the encrypted draft. It is local only: it stays on this machine and sends
|
|
24426
|
+
nothing. On hosts that ask before it (Claude Code, which asks before every MCP
|
|
24427
|
+
tool; Gemini CLI; VS Code; and Cursor, depending on its Run Mode), the steps
|
|
24428
|
+
below add it as a labelled local-only entry, which is not one of the four
|
|
24429
|
+
submit and retry tools. Without it the capture prompts, and a headless run
|
|
24430
|
+
denies it before any draft exists. Codex under the managed \`writes\` mode also
|
|
24431
|
+
asks before it, but there approving it is an optional administrator decision:
|
|
24432
|
+
with it, Auto-review never sees the lesson content (see "Approve private
|
|
24433
|
+
repository contributions in managed Codex"). On these hosts a run that nobody
|
|
24434
|
+
can answer, such as a headless run, denies every tool that has no approval, so
|
|
24435
|
+
it also needs approvals for the other Remembrance tools it calls, such as
|
|
24436
|
+
\`query_skills\`; this step covers only private learning.
|
|
24437
|
+
|
|
24438
|
+
Check the step by behavior: capture one disposable private lesson and confirm
|
|
24439
|
+
that neither the capture nor its submission prompts. Where the organization
|
|
24440
|
+
leaves \`capture_learning\` to Auto-review or a person, as managed Codex may,
|
|
24441
|
+
only the capture is reviewed; its submission still must not prompt.
|
|
24442
|
+
\`run_connection_doctor\` cannot see a persisted approval; its \`host_approval\`
|
|
24443
|
+
field reports only recent denials.
|
|
24444
|
+
|
|
24445
|
+
### Claude Code
|
|
24446
|
+
|
|
24447
|
+
Merge these entries into \`permissions.allow\` in \`~/.claude/settings.json\`,
|
|
24448
|
+
which applies to every project. The first four are the plugin's private submit
|
|
24449
|
+
and retry tools; the last is the local-only \`capture_learning\` entry:
|
|
24450
|
+
|
|
24451
|
+
~~~json
|
|
24452
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.claudeCodePlugin}
|
|
24453
|
+
~~~
|
|
24454
|
+
|
|
24455
|
+
Choosing "Yes, and don't ask again" at the prompt saves the rule only for the
|
|
24456
|
+
current project, in \`.claude/settings.local.json\`. A local standalone server
|
|
24457
|
+
named \`remembrance\`, whether a user or the organization registers it, uses
|
|
24458
|
+
\`mcp__remembrance__<tool>\` names instead:
|
|
24459
|
+
|
|
24460
|
+
~~~json
|
|
24461
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.claudeCodeServer}
|
|
24462
|
+
~~~
|
|
24463
|
+
|
|
24464
|
+
Hosted MCP, including the \`managed-mcp.json\` path in "Approve Claude Code",
|
|
24465
|
+
exposes only \`submit_private_lesson_candidate\` of these and has no
|
|
24466
|
+
\`capture_learning\`, so a hosted server named \`remembrance\` needs only this
|
|
24467
|
+
entry:
|
|
24468
|
+
|
|
24469
|
+
~~~json
|
|
24470
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.claudeCodeHosted}
|
|
24471
|
+
~~~
|
|
24472
|
+
|
|
24473
|
+
Headless runs such as \`claude -p\` deny every tool without an allow rule, so
|
|
24474
|
+
they also need rules for the other Remembrance tools they call. Plan mode still
|
|
24475
|
+
asks before these tools even when a rule allows them. When managed settings set
|
|
24476
|
+
\`allowManagedPermissionRulesOnly\`, Claude Code ignores user rules, so an
|
|
24477
|
+
administrator must ship them (see "Approve Claude Code").
|
|
24478
|
+
|
|
24479
|
+
### Codex
|
|
24480
|
+
|
|
24481
|
+
Add one table per tool to the user-level \`~/.codex/config.toml\`, separate from
|
|
24482
|
+
the optional routine-feedback opt-in above:
|
|
24483
|
+
|
|
24484
|
+
~~~toml
|
|
24485
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.codexPlugin}
|
|
24486
|
+
~~~
|
|
24487
|
+
|
|
24488
|
+
Current Codex source does not prompt for these four tools, or for
|
|
24489
|
+
\`capture_learning\`, under the default \`auto\` tool approval mode, because
|
|
24490
|
+
Remembrance marks them non-destructive and closed-world; older releases and
|
|
24491
|
+
other modes can, so add the tables anyway. Under the managed
|
|
24492
|
+
\`default_tools_approval_mode = "writes"\`, Codex asks before every call, from a
|
|
24493
|
+
person or from Auto-review where it is the reviewer, and cannot remember the
|
|
24494
|
+
answer, so a per-tool \`approve\` entry is the only way to persist approval.
|
|
24495
|
+
\`approve\` also skips Auto-review for that tool, so in a managed organization
|
|
24496
|
+
add these tables only with your administrator ("Approve private repository
|
|
24497
|
+
contributions in managed Codex" covers the trade-off and \`capture_learning\`).
|
|
24498
|
+
For a manually registered server named \`remembrance\`, use the same tables
|
|
24499
|
+
under \`mcp_servers.remembrance\`:
|
|
24500
|
+
|
|
24501
|
+
~~~toml
|
|
24502
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.codexManualServer}
|
|
24503
|
+
~~~
|
|
24504
|
+
|
|
24505
|
+
### Cursor
|
|
24506
|
+
|
|
24507
|
+
In the IDE, merge these entries into the \`mcpAllowlist\` array of
|
|
24508
|
+
\`~/.cursor/permissions.json\` (create the file if it is missing); the last is
|
|
24509
|
+
the local-only \`capture_learning\` entry:
|
|
24510
|
+
|
|
24511
|
+
~~~json
|
|
24512
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.cursorIde}
|
|
24513
|
+
~~~
|
|
24514
|
+
|
|
24515
|
+
\`mcpAllowlist\` replaces the whole in-app MCP allowlist, so keep the entries
|
|
24516
|
+
you already rely on in the same array, keep the file's other keys such as
|
|
24517
|
+
\`terminalAllowlist\`, \`approvalMode\`, and \`autoReview\`, and use this
|
|
24518
|
+
user-level file. Cursor applies it under its Run Modes (Auto-review is the
|
|
24519
|
+
default); a team Run Mode configuration from an administrator overrides it. For
|
|
24520
|
+
the Cursor CLI, merge the same tools into \`permissions.allow\` in
|
|
24521
|
+
\`~/.cursor/cli-config.json\`:
|
|
24522
|
+
|
|
24523
|
+
~~~json
|
|
24524
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.cursorCli}
|
|
24525
|
+
~~~
|
|
24526
|
+
|
|
24527
|
+
If Cursor shows the plugin's server under a name other than \`remembrance\`, use
|
|
24528
|
+
that exact name instead. Do not replace the server name with \`*\`, which
|
|
24529
|
+
approves the tool on every server.
|
|
24530
|
+
|
|
24531
|
+
### VS Code
|
|
24532
|
+
|
|
24533
|
+
VS Code has no settings key or policy that pre-approves a single tool; use its
|
|
24534
|
+
interface. Run **Chat: Manage Tool Approval**, expand the Remembrance server,
|
|
24535
|
+
tick only the four tools and the local-only \`capture_learning\`, and turn off
|
|
24536
|
+
**Configure for this workspace only** so the approval applies in every
|
|
24537
|
+
workspace. Do not tick the server's own box or choose **Always Allow Tools
|
|
24538
|
+
from** the server: both approve the whole server. Alternatively, choose
|
|
24539
|
+
**Always Allow** in the prompt's Allow menu the first time each of those tools
|
|
24540
|
+
asks.
|
|
24541
|
+
|
|
24542
|
+
### OpenCode
|
|
24543
|
+
|
|
24544
|
+
OpenCode runs MCP tools without asking by default, so private submissions
|
|
24545
|
+
already complete. Add explicit entries to the \`permission\` map in
|
|
24546
|
+
\`~/.config/opencode/opencode.json\` so the four tools and the local-only
|
|
24547
|
+
\`capture_learning\` keep working under a broader ask rule that comes before
|
|
24548
|
+
them, which would otherwise stop every private lesson or skill submission:
|
|
24549
|
+
|
|
24550
|
+
~~~json
|
|
24551
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.openCode}
|
|
24552
|
+
~~~
|
|
24553
|
+
|
|
24554
|
+
Put them after any broader \`"*"\` or \`"remembrance_*"\` rule in the same
|
|
24555
|
+
\`permission\` map, because OpenCode applies the last matching rule. A broader ask
|
|
24556
|
+
rule set elsewhere, such as in an agent's own \`permission\` map or, depending on
|
|
24557
|
+
the OpenCode version, in another configuration file, can still take precedence;
|
|
24558
|
+
if the capture or its submission still prompts, find that rule and make sure the
|
|
24559
|
+
same entries come after it. In OpenCode 2.x, answering "always" at a prompt
|
|
24560
|
+
saves an allow rule for the current project across sessions (1.x keeps it until
|
|
24561
|
+
OpenCode restarts); never answer "always" on a \`delete_private_*\` prompt.
|
|
24562
|
+
|
|
24563
|
+
### OpenClaw
|
|
24564
|
+
|
|
24565
|
+
In native runs OpenClaw documents no prompt of its own for MCP tools; the
|
|
24566
|
+
Remembrance plugin asks before each private submission. To persist approval,
|
|
24567
|
+
answer **allow-always** once for each lane when it asks to "Submit private
|
|
24568
|
+
Remembrance lesson" or "Submit private Remembrance skill", for example with
|
|
24569
|
+
\`/approve <id> allow-always\` in chat or
|
|
24570
|
+
\`openclaw approvals resolve <id> allow-always\`. One decision covers that lane's
|
|
24571
|
+
submit and retry actions, and the plugin saves it in its config.
|
|
24572
|
+
|
|
24573
|
+
To pre-set both lanes instead, Remembrance for OpenClaw 0.2.3 or later accepts
|
|
24574
|
+
this in \`~/.openclaw/openclaw.json\`:
|
|
24575
|
+
|
|
24576
|
+
~~~json
|
|
24577
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.openClaw}
|
|
24578
|
+
~~~
|
|
24579
|
+
|
|
24580
|
+
Check the installed version first, for example with
|
|
24581
|
+
\`openclaw plugins inspect remembrance\`. Earlier versions reject the key: the
|
|
24582
|
+
Gateway then refuses to start until it is removed, and those versions cannot
|
|
24583
|
+
keep an allow-always decision across a restart either. On older or
|
|
24584
|
+
mixed-version installs, use allow-always.
|
|
24585
|
+
|
|
24586
|
+
### Gemini CLI
|
|
24587
|
+
|
|
24588
|
+
Create \`~/.gemini/policies/remembrance.toml\` with one rule per tool; the last
|
|
24589
|
+
rule is the local-only \`capture_learning\` entry:
|
|
24590
|
+
|
|
24591
|
+
~~~toml
|
|
24592
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.geminiCli}
|
|
24593
|
+
~~~
|
|
24594
|
+
|
|
24595
|
+
Gemini CLI asks before every MCP tool without an allow rule, and
|
|
24596
|
+
non-interactive runs treat that prompt as a denial. These rules cover private
|
|
24597
|
+
learning only, so a headless run also needs rules for the other Remembrance
|
|
24598
|
+
tools it calls, such as \`query_skills\`. Keep \`trust\` false and do not list
|
|
24599
|
+
the server in \`mcp.allowed\`: Gemini CLI turns \`trust: true\` and an
|
|
24600
|
+
\`mcp.allowed\` entry alike into an allow rule for every tool of the server.
|
|
24601
|
+
Administrators use the admin policy file in "Approve Gemini CLI" instead, which
|
|
24602
|
+
already contains these rules.
|
|
24603
|
+
|
|
24604
|
+
### Claude Desktop and other MCP clients
|
|
24605
|
+
|
|
24606
|
+
Claude Desktop offers a per-tool **Always allow**, in the approval prompt or in
|
|
24607
|
+
the connector's tool permissions, but it has no config key and users report
|
|
24608
|
+
that it resets when the app updates, so do not rely on it for unattended runs.
|
|
24609
|
+
For other MCP clients, use the client's per-tool approval for the four exact
|
|
24610
|
+
tool names (only \`submit_private_lesson_candidate\` on hosted MCP), plus the
|
|
24611
|
+
local-only \`capture_learning\` on a local server that asks before it. If a
|
|
24612
|
+
client can approve only a whole server, keep its prompts.
|
|
24199
24613
|
|
|
24200
24614
|
## Enterprise/org key setup
|
|
24201
24615
|
|
|
@@ -24282,8 +24696,10 @@ while malformed or privacy-sensitive tags hold the draft instead of being
|
|
|
24282
24696
|
silently removed.
|
|
24283
24697
|
|
|
24284
24698
|
The plugin then calls \`submit_private_lesson_candidate\` with that draft ID.
|
|
24285
|
-
This is the
|
|
24286
|
-
|
|
24699
|
+
This is the host-visible network action in the flow, and
|
|
24700
|
+
\`retry_private_lesson_candidate\` later resends a retained draft through the
|
|
24701
|
+
same lane. Persist approval for these exact actions, as in "Highly Recommended:
|
|
24702
|
+
approve private submissions", not for every Remembrance write. The server derives
|
|
24287
24703
|
the organization and private visibility from the authenticated key, verifies a
|
|
24288
24704
|
signed organization policy plus purpose-bound attestation, and returns a signed
|
|
24289
24705
|
content-free receipt. The action always submits privately and never falls back
|
|
@@ -24341,16 +24757,17 @@ agent task remain available when capture or submission is blocked.
|
|
|
24341
24757
|
### Approve private repository contributions in managed Codex
|
|
24342
24758
|
|
|
24343
24759
|
An API key authorizes Remembrance; it does not authorize Codex to export
|
|
24344
|
-
repository-derived content. Codex Auto-review
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
|
|
24760
|
+
repository-derived content. Codex Auto-review evaluates the approval requests
|
|
24761
|
+
that would otherwise pause for a person, including MCP calls that need approval
|
|
24762
|
+
under their annotations or configured approval mode; a tool set to \`approve\`
|
|
24763
|
+
never reaches it. A chat approval may not override an enterprise deny rule, and
|
|
24764
|
+
no Remembrance plugin setting can weaken that host boundary.
|
|
24348
24765
|
|
|
24349
24766
|
For an organization that has approved Remembrance as an operational-memory
|
|
24350
24767
|
processor, a Codex administrator should do all of the following:
|
|
24351
24768
|
|
|
24352
|
-
1. Allow the
|
|
24353
|
-
\`
|
|
24769
|
+
1. Allow the Remembrance marketplace source in managed Codex requirements and
|
|
24770
|
+
enable the plugin's bundled \`remembrance\` server in managed configuration.
|
|
24354
24771
|
2. Merge a narrow Remembrance destination rule into the existing
|
|
24355
24772
|
\`guardian_policy_config\`. Do not replace the rest of the tenant policy or
|
|
24356
24773
|
remove its credential, secret, raw-log, or unrelated-source-code denies.
|
|
@@ -24371,9 +24788,12 @@ key to force a public candidate. Submit privately, then use the reviewed public-
|
|
|
24371
24788
|
propagation flow for a redacted public-safe version when the organization wants
|
|
24372
24789
|
to share it.
|
|
24373
24790
|
|
|
24374
|
-
|
|
24375
|
-
|
|
24376
|
-
|
|
24791
|
+
Managed \`requirements.toml\` restricts the marketplace source; the tool
|
|
24792
|
+
allowlist and approval mode belong in managed configuration. The bundled server
|
|
24793
|
+
is a local stdio server, so never give it the hosted URL as its identity. If the
|
|
24794
|
+
requirements also carry an \`mcp_servers\` allowlist, approve this server by its
|
|
24795
|
+
configured command (\`sh\`): Codex disables a server whose name and identity do
|
|
24796
|
+
not match an approved entry.
|
|
24377
24797
|
|
|
24378
24798
|
Add these entries to \`requirements.toml\`:
|
|
24379
24799
|
|
|
@@ -24381,9 +24801,6 @@ Add these entries to \`requirements.toml\`:
|
|
|
24381
24801
|
[features]
|
|
24382
24802
|
hooks = true
|
|
24383
24803
|
|
|
24384
|
-
[plugins."remembrance@remembrance".mcp_servers.remembrance]
|
|
24385
|
-
identity = { url = "https://remembrance.dev/api/mcp" }
|
|
24386
|
-
|
|
24387
24804
|
[marketplaces]
|
|
24388
24805
|
restrict_to_allowed_sources = true
|
|
24389
24806
|
|
|
@@ -24401,8 +24818,37 @@ enabled_tools = [
|
|
|
24401
24818
|
${recommendedLocalOrganizationToolToml}
|
|
24402
24819
|
]
|
|
24403
24820
|
default_tools_approval_mode = "writes"
|
|
24821
|
+
|
|
24822
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.codexPlugin}
|
|
24404
24823
|
~~~
|
|
24405
24824
|
|
|
24825
|
+
\`default_tools_approval_mode = "writes"\` asks before every call of every tool
|
|
24826
|
+
that is not marked read-only, including \`query_skills\`, \`get_skill\`,
|
|
24827
|
+
\`get_resource\`, \`invoke_skill\`, \`capture_learning\`, and the feedback tools.
|
|
24828
|
+
The answer comes from a person, or from Auto-review where it is the reviewer;
|
|
24829
|
+
Codex cannot remember it, and a run that cannot ask denies the call.
|
|
24830
|
+
|
|
24831
|
+
The four \`approve\` tables are the Highly Recommended step: they let the
|
|
24832
|
+
private submit and retry calls run without that per-call review. The trade-off
|
|
24833
|
+
is that Auto-review never evaluates a tool set to \`approve\`, so the guardian
|
|
24834
|
+
policy's denies no longer apply to those four calls. They normally carry only a
|
|
24835
|
+
draft ID, so the lesson or skill content passes through \`capture_learning\`,
|
|
24836
|
+
which a person or Auto-review still reviews; but the lesson submit also accepts
|
|
24837
|
+
a lesson candidate written into the call, which then reaches the
|
|
24838
|
+
organization's private review queue without that review. Leave the tables out
|
|
24839
|
+
if the organization wants Auto-review to evaluate every private submission.
|
|
24840
|
+
|
|
24841
|
+
Runs that cannot ask can capture only if \`capture_learning\` is approved too.
|
|
24842
|
+
This optional table is local only, but with it Auto-review never sees the
|
|
24843
|
+
lesson content at all:
|
|
24844
|
+
|
|
24845
|
+
~~~toml
|
|
24846
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.codexPluginCapture}
|
|
24847
|
+
~~~
|
|
24848
|
+
|
|
24849
|
+
Those runs also need approval for every other tool they call, so unattended
|
|
24850
|
+
work under \`writes\` usually relies on Auto-review as the reviewer instead.
|
|
24851
|
+
|
|
24406
24852
|
If \`allow_managed_hooks_only = true\`, Codex skips plugin hooks. Either leave
|
|
24407
24853
|
the vetted Remembrance plugin hooks permitted or deploy equivalent managed
|
|
24408
24854
|
query/completion hooks; otherwise MCP calls may work while the query and
|
|
@@ -24512,10 +24958,45 @@ optional local-only tools and never belong in a hosted MCP allowlist.
|
|
|
24512
24958
|
### Approve Claude Code
|
|
24513
24959
|
|
|
24514
24960
|
Force-enable \`remembrance@remembrance\` in managed settings so its vetted hooks
|
|
24515
|
-
still run when \`allowManagedHooksOnly\` is enabled.
|
|
24516
|
-
|
|
24517
|
-
|
|
24518
|
-
|
|
24961
|
+
still run when \`allowManagedHooksOnly\` is enabled. Then choose one MCP path.
|
|
24962
|
+
|
|
24963
|
+
To keep the plugin's local server, with all four private submit and retry tools
|
|
24964
|
+
and the encrypted device outbox, deploy neither \`managed-mcp.json\` nor the
|
|
24965
|
+
URL-only \`allowedMcpServers\` list of the hosted path below. Exclusive managed
|
|
24966
|
+
MCP suppresses every plugin-provided server, and Claude Code also checks plugin
|
|
24967
|
+
servers against \`allowedMcpServers\`, where a list with only \`serverUrl\`
|
|
24968
|
+
entries blocks every stdio server. Merge this approval into managed settings;
|
|
24969
|
+
the plugin's tool names carry the \`mcp__plugin_remembrance_remembrance__\`
|
|
24970
|
+
prefix, and the last entry is the local-only \`capture_learning\`:
|
|
24971
|
+
|
|
24972
|
+
~~~json
|
|
24973
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.claudeCodeManagedPlugin}
|
|
24974
|
+
~~~
|
|
24975
|
+
|
|
24976
|
+
Managed rules also cover organizations that set
|
|
24977
|
+
\`allowManagedPermissionRulesOnly\`, which makes Claude Code ignore user rules.
|
|
24978
|
+
For command or REST fallbacks under a sandbox, also merge \`remembrance.dev\`
|
|
24979
|
+
into \`sandbox.network.allowedDomains\`.
|
|
24980
|
+
|
|
24981
|
+
Optional lockdown, separate from that approval: Remembrance needs neither of
|
|
24982
|
+
these keys, and both restrict much more than Remembrance.
|
|
24983
|
+
\`allowManagedHooksOnly\` makes Claude Code ignore every user, project, and
|
|
24984
|
+
local hook, and turns off \`/goal\` and command-sourced plugins.
|
|
24985
|
+
\`strictKnownMarketplaces\` blocks plugins from every marketplace it does not
|
|
24986
|
+
list, and also the \`~/.claude/skills\` auto-load unless the list includes
|
|
24987
|
+
\`{"source": "skills-dir"}\`. Add them only when the organization wants that
|
|
24988
|
+
lockdown; the hosted path below carries the same two keys:
|
|
24989
|
+
|
|
24990
|
+
~~~json
|
|
24991
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.claudeCodeManagedLockdown}
|
|
24992
|
+
~~~
|
|
24993
|
+
|
|
24994
|
+
To use hosted MCP instead, define Remembrance in \`managed-mcp.json\`, because
|
|
24995
|
+
exclusive managed MCP suppresses every plugin-provided MCP server. The plugin
|
|
24996
|
+
keeps its hooks and skills, but its tools then come from the hosted server named
|
|
24997
|
+
\`remembrance\`, which exposes only \`submit_private_lesson_candidate\` of the four
|
|
24998
|
+
private actions. Use the exact URL as the security boundary; a server name alone
|
|
24999
|
+
is not sufficient.
|
|
24519
25000
|
|
|
24520
25001
|
Do not put a real key directly in \`managed-mcp.json\`; every local user can read
|
|
24521
25002
|
that file. Reference each user's process environment instead:
|
|
@@ -24534,7 +25015,7 @@ that file. Reference each user's process environment instead:
|
|
|
24534
25015
|
}
|
|
24535
25016
|
~~~
|
|
24536
25017
|
|
|
24537
|
-
Merge this into managed settings:
|
|
25018
|
+
Merge this into managed settings for the hosted path:
|
|
24538
25019
|
|
|
24539
25020
|
~~~json
|
|
24540
25021
|
{
|
|
@@ -24575,13 +25056,11 @@ work. See the official
|
|
|
24575
25056
|
### Approve Gemini CLI
|
|
24576
25057
|
|
|
24577
25058
|
Define the canonical server and its tool allowlist in the system override
|
|
24578
|
-
settings, not only user or workspace settings.
|
|
24579
|
-
|
|
24580
|
-
narrow server/tool set:
|
|
25059
|
+
settings, not only user or workspace settings. Keep \`trust\` false;
|
|
25060
|
+
\`trust: true\` bypasses every confirmation for the server:
|
|
24581
25061
|
|
|
24582
25062
|
~~~json
|
|
24583
25063
|
{
|
|
24584
|
-
"mcp": { "allowed": ["remembrance"] },
|
|
24585
25064
|
"mcpServers": {
|
|
24586
25065
|
"remembrance": {
|
|
24587
25066
|
"command": "npx",
|
|
@@ -24591,7 +25070,7 @@ narrow server/tool set:
|
|
|
24591
25070
|
"REMEMBRANCE_API_KEY": "\${REMEMBRANCE_API_KEY}"
|
|
24592
25071
|
},
|
|
24593
25072
|
"includeTools": [
|
|
24594
|
-
${
|
|
25073
|
+
${geminiIncludeToolJson}
|
|
24595
25074
|
],
|
|
24596
25075
|
"trust": false
|
|
24597
25076
|
}
|
|
@@ -24599,14 +25078,54 @@ ${recommendedLocalOrganizationToolJson}
|
|
|
24599
25078
|
}
|
|
24600
25079
|
~~~
|
|
24601
25080
|
|
|
25081
|
+
Approve tools only with exact per-tool policy rules. Do not list the server in
|
|
25082
|
+
\`mcp.allowed\`: the server runs without it, and current Gemini CLI source turns
|
|
25083
|
+
each \`mcp.allowed\` entry into an allow rule for every tool of that server.
|
|
25084
|
+
Instead, save this file as \`remembrance.toml\` in the admin policy folder:
|
|
25085
|
+
\`/Library/Application Support/GeminiCli/policies\` on macOS,
|
|
25086
|
+
\`/etc/gemini-cli/policies\` on Linux, or \`C:\\ProgramData\\gemini-cli\\policies\`
|
|
25087
|
+
on Windows. Gemini CLI ignores admin policy files that are not root-owned.
|
|
25088
|
+
|
|
25089
|
+
~~~toml
|
|
25090
|
+
${PRIVATE_SUBMISSION_APPROVAL_SNIPPETS.geminiCliAdmin}
|
|
25091
|
+
~~~
|
|
25092
|
+
|
|
25093
|
+
The file has one exact rule for every tool in \`includeTools\`: an allow rule
|
|
25094
|
+
for each tool except the two confirmed-delete tools, whose admin \`ask_user\`
|
|
25095
|
+
rules keep them asking even where a user allowed them, so a headless run denies
|
|
25096
|
+
them. Apart from those two, this reproduces the earlier behavior of this
|
|
25097
|
+
recipe, whose \`mcp.allowed\` entry let every included tool run, with exact
|
|
25098
|
+
rules instead of a whole-server rule. The file already contains the rules from
|
|
25099
|
+
"Highly Recommended: approve private submissions" for the four private submit
|
|
25100
|
+
and retry tools and the local-only \`capture_learning\`, so do not add those
|
|
25101
|
+
again. To make a tool ask, change its rule to \`decision = "ask_user"\` instead
|
|
25102
|
+
of deleting the rule: an admin-tier ask outranks users' own allow rules, while
|
|
25103
|
+
without an admin rule a user's allow rule decides. A headless run then denies
|
|
25104
|
+
that tool.
|
|
25105
|
+
|
|
25106
|
+
If the organization already restricts servers with \`mcp.allowed\`, Remembrance
|
|
25107
|
+
must be listed there to run, and that entry creates the whole-server allow rule.
|
|
25108
|
+
Then also place this rule in the admin policy folder. It creates no allow rule:
|
|
25109
|
+
admin rules outrank the one \`mcp.allowed\` creates, so a Remembrance tool
|
|
25110
|
+
without its own admin rule asks again, while the per-tool rules above, at
|
|
25111
|
+
priority 200, still win over it for their tools:
|
|
25112
|
+
|
|
25113
|
+
~~~toml
|
|
25114
|
+
[[rule]]
|
|
25115
|
+
mcpName = "remembrance"
|
|
25116
|
+
decision = "ask_user"
|
|
25117
|
+
priority = 100
|
|
25118
|
+
~~~
|
|
25119
|
+
|
|
24602
25120
|
System settings live at \`/Library/Application Support/GeminiCli/settings.json\`
|
|
24603
25121
|
on macOS, \`/etc/gemini-cli/settings.json\` on Linux, and
|
|
24604
25122
|
\`C:\\ProgramData\\gemini-cli\\settings.json\` on Windows. Also allow
|
|
24605
25123
|
\`remembrance.dev\` in the organization's egress policy. Restart Gemini CLI,
|
|
24606
25124
|
inspect the registered server, then run \`run_connection_doctor\` and require
|
|
24607
25125
|
organization scope before contribution work. See the official
|
|
24608
|
-
[enterprise configuration](https://
|
|
24609
|
-
|
|
25126
|
+
[enterprise configuration](https://geminicli.com/docs/cli/enterprise/),
|
|
25127
|
+
[MCP settings](https://geminicli.com/docs/tools/mcp-server/), and
|
|
25128
|
+
[policy engine](https://geminicli.com/docs/reference/policy-engine/).
|
|
24610
25129
|
|
|
24611
25130
|
### Approve OpenClaw
|
|
24612
25131
|
|
|
@@ -24632,7 +25151,7 @@ MCP tools, and \`tools.deny: ["bundle-mcp"]\` disables them:
|
|
|
24632
25151
|
"remembrance": {
|
|
24633
25152
|
"toolFilter": {
|
|
24634
25153
|
"include": [
|
|
24635
|
-
${
|
|
25154
|
+
${openClawToolFilterJson}
|
|
24636
25155
|
]
|
|
24637
25156
|
}
|
|
24638
25157
|
}
|
|
@@ -24641,8 +25160,17 @@ ${recommendedLocalOrganizationToolJson}
|
|
|
24641
25160
|
}
|
|
24642
25161
|
~~~
|
|
24643
25162
|
|
|
24644
|
-
Use a normal \`coding\` or \`messaging\` tool profile
|
|
24645
|
-
the
|
|
25163
|
+
Use a normal \`coding\` or \`messaging\` tool profile; both already include
|
|
25164
|
+
\`bundle-mcp\`, so the MCP tools need no \`tools.allow\` or \`tools.alsoAllow\`
|
|
25165
|
+
entry. The plugin asks before each private submission. For unattended runs,
|
|
25166
|
+
have each user answer allow-always once per lane. On Remembrance for OpenClaw
|
|
25167
|
+
0.2.3 or later only, you can instead pre-set both private lanes by merging the
|
|
25168
|
+
\`privateLearningEgressApprovals\` object from "Highly Recommended: approve
|
|
25169
|
+
private submissions" into \`plugins.entries.remembrance.config\`. Earlier
|
|
25170
|
+
versions reject that key and the Gateway then refuses to start, so check the
|
|
25171
|
+
installed version first and keep allow-always on older or mixed-version
|
|
25172
|
+
fleets. Then verify cold config, the active Gateway plugin, and live MCP
|
|
25173
|
+
capabilities separately:
|
|
24646
25174
|
|
|
24647
25175
|
~~~bash
|
|
24648
25176
|
openclaw plugins inspect remembrance --runtime --json
|
|
@@ -24677,18 +25205,27 @@ approved secret source, not in \`policy.jsonc\`. After the probes, run
|
|
|
24677
25205
|
|
|
24678
25206
|
For local agents, publish Remembrance in the team marketplace and choose
|
|
24679
25207
|
\`Required\` or \`Default On\`. For cloud agents, also register the exact
|
|
24680
|
-
Remembrance endpoint under **Dashboard >
|
|
24681
|
-
MCP is distributed across cloud agents, the Agents window,
|
|
24682
|
-
\`remembrance.dev\` to the enterprise sandbox network
|
|
24683
|
-
based fallback paths.
|
|
25208
|
+
Remembrance endpoint as a Team MCP server under **Dashboard > Plugins & MCPs**
|
|
25209
|
+
so the same Team MCP is distributed across cloud agents, the Agents window,
|
|
25210
|
+
IDE, and CLI. Add \`remembrance.dev\` to the enterprise sandbox network
|
|
25211
|
+
allowlist for command-based fallback paths.
|
|
24684
25212
|
|
|
24685
|
-
Cursor's
|
|
24686
|
-
|
|
24687
|
-
|
|
24688
|
-
|
|
24689
|
-
|
|
24690
|
-
|
|
24691
|
-
|
|
25213
|
+
Cursor's managed per-tool allowlist is \`~/.cursor/permissions.json\`,
|
|
25214
|
+
distributed through MDM: ship the five \`mcpAllowlist\` entries from "Highly
|
|
25215
|
+
Recommended: approve private submissions", the four private submit and retry
|
|
25216
|
+
tools and the local-only \`capture_learning\`. A distributed file replaces each
|
|
25217
|
+
user's file and its in-app MCP allowlist, so merge these entries with every
|
|
25218
|
+
other entry and key the organization relies on, such as \`terminalAllowlist\`,
|
|
25219
|
+
\`approvalMode\`, and \`autoReview\`. A team Run Mode configuration overrides
|
|
25220
|
+
local \`permissions.json\` files, and the per-server tools field under
|
|
25221
|
+
**Team Settings > MCP Configuration** limits which tools may run but does not
|
|
25222
|
+
run them without asking. Keep the Auto-review or Allowlist Run Mode rather
|
|
25223
|
+
than Run Everything. Run \`run_connection_doctor\` and
|
|
25224
|
+
require organization scope on every enabled surface, then verify query,
|
|
25225
|
+
invocation, feedback, and private-contribution receipts; local plugin hooks and
|
|
25226
|
+
cloud-agent hooks can differ. See the official
|
|
25227
|
+
[permissions file](https://cursor.com/docs/reference/permissions),
|
|
25228
|
+
[Run Modes](https://cursor.com/docs/agent/security/run-modes),
|
|
24692
25229
|
[team plugin modes](https://cursor.com/changelog/05-01-26),
|
|
24693
25230
|
[Team MCP distribution](https://cursor.com/changelog/team-marketplace-updates),
|
|
24694
25231
|
[sandbox network controls](https://cursor.com/changelog/2-5), and
|
|
@@ -24698,12 +25235,15 @@ hooks can differ. See the official
|
|
|
24698
25235
|
|
|
24699
25236
|
Register exactly \`https://remembrance.dev/api/mcp\` or the exact local
|
|
24700
25237
|
\`npx @remembrance-ai/mcp-server\` command. Use the recommended organization
|
|
24701
|
-
tool list above when the client supports tool filtering.
|
|
24702
|
-
behavior for non-read-only calls unless unattended organization-private
|
|
24703
|
-
contribution is explicitly approved. A client with no server/tool policy must
|
|
24704
|
-
use its existing destination control or the zero-network handoff. Supply the
|
|
25238
|
+
tool list above when the client supports tool filtering. Supply the
|
|
24705
25239
|
organization key through the client's secret/header mechanism, then run
|
|
24706
25240
|
\`run_connection_doctor\` and require organization scope before private writes.
|
|
25241
|
+
Keep normal approval behavior for other non-read-only calls, and persist
|
|
25242
|
+
approval only for the four private submit and retry tools (on hosted MCP, the
|
|
25243
|
+
lesson submit), plus the local-only \`capture_learning\` on a local server that
|
|
25244
|
+
asks before it, as in the Highly Recommended step. A client with no
|
|
25245
|
+
server/tool policy must use its existing destination control or the
|
|
25246
|
+
zero-network handoff.
|
|
24707
25247
|
|
|
24708
25248
|
If any host still denies the export, that denial remains authoritative. The
|
|
24709
25249
|
portable local handoff and dashboard import work identically for Codex, Claude
|
|
@@ -24813,6 +25353,13 @@ not inherit shell exports:
|
|
|
24813
25353
|
}
|
|
24814
25354
|
~~~
|
|
24815
25355
|
|
|
25356
|
+
A server you register yourself under the name \`remembrance\`, local or hosted,
|
|
25357
|
+
takes the standalone approval forms from "Highly Recommended: approve private
|
|
25358
|
+
submissions": \`[mcp_servers.remembrance.tools.<tool>]\` tables in Codex,
|
|
25359
|
+
\`mcp__remembrance__<tool>\` rules in Claude Code (for example after
|
|
25360
|
+
\`claude mcp add\`), and \`remembrance:<tool>\` entries in Cursor. A hosted server
|
|
25361
|
+
needs only \`submit_private_lesson_candidate\`.
|
|
25362
|
+
|
|
24816
25363
|
## Skill-only install
|
|
24817
25364
|
|
|
24818
25365
|
For skills.sh-compatible runtimes (or any Agent Skills provider) that can load
|
|
@@ -24895,14 +25442,20 @@ session skills.
|
|
|
24895
25442
|
\`capture_learning.lesson\` followed by the exact returned action and a
|
|
24896
25443
|
private draft receipt. On hosted/legacy MCP, require a \`failure_report\`
|
|
24897
25444
|
through submit_remembrance. This validates both capability states without
|
|
24898
|
-
mixing their schemas.
|
|
25445
|
+
mixing their schemas. With an organization key and the Highly Recommended
|
|
25446
|
+
approval in place, neither the capture nor the private submission may
|
|
25447
|
+
prompt. A prompt for a submit or retry tool means its approval is missing or
|
|
25448
|
+
uses the wrong tool names; one for \`capture_learning\` means only that its
|
|
25449
|
+
local-only entry is missing, and is expected where the organization leaves
|
|
25450
|
+
the capture to Auto-review or a person, as managed Codex may.
|
|
24899
25451
|
12. If using an org key, list and invoke an org-only skill or private overlay
|
|
24900
25452
|
that should not appear anonymously.
|
|
24901
25453
|
13. With an organization submission key, submit one disposable redacted skill.
|
|
24902
25454
|
Current local MCP must use \`capture_learning.private_skill\` followed by
|
|
24903
25455
|
submit_private_skill_candidate; hosted/legacy MCP must use
|
|
24904
25456
|
propose_private_skill. Verify it appears only in that organization's review
|
|
24905
|
-
queue
|
|
25457
|
+
queue and, on local MCP with the approval in place, that it needed no host
|
|
25458
|
+
prompt. In a separate negative scenario, simulate a
|
|
24906
25459
|
host-policy denial and verify the plugin reports the fixed content-free alert
|
|
24907
25460
|
once, persists no blocked content, performs no retry, and creates no handoff.
|
|
24908
25461
|
Test queue_private_skill_import only as a separate administrator-requested
|
|
@@ -24962,6 +25515,27 @@ session skills.
|
|
|
24962
25515
|
--probe", and restart OpenClaw after plugin install/config changes.
|
|
24963
25516
|
- "Claude desktop ignores env vars": put env in the user-scoped Claude settings
|
|
24964
25517
|
that the desktop app reads, then fully quit and relaunch.
|
|
25518
|
+
- "Every private submission asks for approval" or "a headless run denies
|
|
25519
|
+
private submissions": report the blocked submission once as not submitted.
|
|
25520
|
+
Then ask the user (for managed settings, the administrator) to apply or fix
|
|
25521
|
+
the Highly Recommended approval; never change host settings or answer the
|
|
25522
|
+
host's approval yourself, and only after they confirm, send the retained
|
|
25523
|
+
draft through its exact submit or retry action.
|
|
25524
|
+
\`inspect_private_learning_outbox\` lists each draft with its \`state\`,
|
|
25525
|
+
\`attempts\`, and \`next_retry_at\`: a draft the host stopped before sending,
|
|
25526
|
+
a lesson still \`awaiting_authorization\` with 0 attempts or a skill still
|
|
25527
|
+
\`ready\`, needs its submit action, and a \`retry_scheduled\` draft its retry
|
|
25528
|
+
action once \`next_retry_at\` has passed. A prompt or denial naming a
|
|
25529
|
+
submit or retry tool means its approval is missing or names the wrong tools:
|
|
25530
|
+
a Claude Code plugin install needs
|
|
25531
|
+
\`mcp__plugin_remembrance_remembrance__<tool>\` rules, not
|
|
25532
|
+
\`mcp__remembrance__<tool>\`. One naming \`capture_learning\` means only that
|
|
25533
|
+
its local-only entry is missing, and is expected where the organization
|
|
25534
|
+
leaves the capture to Auto-review or a person, as managed Codex may: under
|
|
25535
|
+
managed Codex \`writes\`, approving \`capture_learning\` is an optional
|
|
25536
|
+
administrator decision (with it, Auto-review never sees the lesson content),
|
|
25537
|
+
not a fix to ask for. \`run_connection_doctor\` cannot see a persisted
|
|
25538
|
+
approval.
|
|
24965
25539
|
- "Host policy denied private repository export": this is not a Remembrance
|
|
24966
25540
|
API failure. An administrator must narrowly approve the Remembrance MCP
|
|
24967
25541
|
server, destination, and private contribution action. Otherwise use the
|
|
@@ -25946,6 +26520,34 @@ var verifierOutputSchema = external_exports.object({
|
|
|
25946
26520
|
topology_assessment: skillTopologyAssessmentSchema.nullable().default(null).catch(null)
|
|
25947
26521
|
});
|
|
25948
26522
|
|
|
26523
|
+
// src/private-skill-protection-recovery.ts
|
|
26524
|
+
var PRIVATE_SKILL_CONFIGURATION_REFUSAL = "private_admission_configuration_error";
|
|
26525
|
+
var PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL = "private_skill_permanent_service_refusal";
|
|
26526
|
+
function isPrivateSkillConfigurationHold(draft) {
|
|
26527
|
+
return draft.state === "held_validation" && draft.last_error_code === PRIVATE_SKILL_CONFIGURATION_REFUSAL;
|
|
26528
|
+
}
|
|
26529
|
+
function privateSkillPermanentRefusalGuidance(draft) {
|
|
26530
|
+
if (isPrivateSkillConfigurationHold(draft)) {
|
|
26531
|
+
return {
|
|
26532
|
+
next_action: null,
|
|
26533
|
+
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.",
|
|
26534
|
+
recovery_after_correction: {
|
|
26535
|
+
automatic_retry: false,
|
|
26536
|
+
condition: "organization_administrator_corrected_private_protection_configuration",
|
|
26537
|
+
tool: "retry_private_skill_candidate",
|
|
26538
|
+
arguments: { draft_id: draft.draft_id }
|
|
26539
|
+
}
|
|
26540
|
+
};
|
|
26541
|
+
}
|
|
26542
|
+
if (draft.state === "held_validation" && draft.last_error_code === PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL) {
|
|
26543
|
+
return {
|
|
26544
|
+
next_action: null,
|
|
26545
|
+
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."
|
|
26546
|
+
};
|
|
26547
|
+
}
|
|
26548
|
+
return {};
|
|
26549
|
+
}
|
|
26550
|
+
|
|
25949
26551
|
// src/server.ts
|
|
25950
26552
|
import { existsSync as existsSync6 } from "node:fs";
|
|
25951
26553
|
import { mkdir as mkdir5, writeFile as writeFile2 } from "node:fs/promises";
|
|
@@ -27658,7 +28260,8 @@ var pendingActionDeclineSchema = external_exports.object({
|
|
|
27658
28260
|
"not_observed_by_this_agent",
|
|
27659
28261
|
"agent_exited",
|
|
27660
28262
|
"not_reusable",
|
|
27661
|
-
"duplicate"
|
|
28263
|
+
"duplicate",
|
|
28264
|
+
"host_policy_denied"
|
|
27662
28265
|
]).describe("Why this agent cannot complete the action.")
|
|
27663
28266
|
}).strict();
|
|
27664
28267
|
var pendingActionPayloadSchema = external_exports.object({
|
|
@@ -27793,7 +28396,7 @@ var declaredToolDefinitions = [
|
|
|
27793
28396
|
),
|
|
27794
28397
|
localTool(
|
|
27795
28398
|
"decline_pending_action",
|
|
27796
|
-
"Decline one pending Remembrance action that a hook reminder listed and you cannot complete. Pass the action_id shown under it and one reason: not_observed_by_this_agent (you never received the result or payload it refers to), agent_exited (the subagent that earned it has exited), not_reusable (it holds nothing reusable), or duplicate (it was already completed another way). It is local-only: it sends nothing, stores nothing, grants no approval, and never counts as feedback. The local completion hook closes that action in your own pending list when it observes this call.",
|
|
28399
|
+
"Decline one pending Remembrance action that a hook reminder listed and you cannot complete. Pass the action_id shown under it and one reason: not_observed_by_this_agent (you never received the result or payload it refers to), agent_exited (the subagent that earned it has exited), not_reusable (it holds nothing reusable), or duplicate (it was already completed another way); host_policy_denied only for a private-learning line or notice whose exact action the host denied. It is local-only: it sends nothing, stores nothing, grants no approval, and never counts as feedback. The local completion hook closes that action in your own pending list when it observes this call; a declined private draft stays retained and returns later only as a user decision.",
|
|
27797
28400
|
"decline_pending_action",
|
|
27798
28401
|
pendingActionDeclineSchema
|
|
27799
28402
|
),
|
|
@@ -27862,7 +28465,7 @@ var declaredToolDefinitions = [
|
|
|
27862
28465
|
),
|
|
27863
28466
|
localNetworkTool(
|
|
27864
28467
|
"retry_private_skill_candidate",
|
|
27865
|
-
"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
|
|
28468
|
+
"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.",
|
|
27866
28469
|
"retry_private_skill_candidate",
|
|
27867
28470
|
privateSkillDraftReferenceSchema,
|
|
27868
28471
|
"content_write"
|
|
@@ -42844,27 +43447,27 @@ var require_stringifyString = __commonJS({
|
|
|
42844
43447
|
return true;
|
|
42845
43448
|
}
|
|
42846
43449
|
function doubleQuotedString(value, ctx) {
|
|
42847
|
-
const
|
|
43450
|
+
const json2 = JSON.stringify(value);
|
|
42848
43451
|
if (ctx.options.doubleQuotedAsJSON)
|
|
42849
|
-
return
|
|
43452
|
+
return json2;
|
|
42850
43453
|
const { implicitKey } = ctx;
|
|
42851
43454
|
const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
|
|
42852
43455
|
const indent = ctx.indent || (containsDocumentMarker(value) ? " " : "");
|
|
42853
43456
|
let str = "";
|
|
42854
43457
|
let start = 0;
|
|
42855
|
-
for (let i = 0, ch =
|
|
42856
|
-
if (ch === " " &&
|
|
42857
|
-
str +=
|
|
43458
|
+
for (let i = 0, ch = json2[i]; ch; ch = json2[++i]) {
|
|
43459
|
+
if (ch === " " && json2[i + 1] === "\\" && json2[i + 2] === "n") {
|
|
43460
|
+
str += json2.slice(start, i) + "\\ ";
|
|
42858
43461
|
i += 1;
|
|
42859
43462
|
start = i;
|
|
42860
43463
|
ch = "\\";
|
|
42861
43464
|
}
|
|
42862
43465
|
if (ch === "\\")
|
|
42863
|
-
switch (
|
|
43466
|
+
switch (json2[i + 1]) {
|
|
42864
43467
|
case "u":
|
|
42865
43468
|
{
|
|
42866
|
-
str +=
|
|
42867
|
-
const code =
|
|
43469
|
+
str += json2.slice(start, i);
|
|
43470
|
+
const code = json2.substr(i + 2, 4);
|
|
42868
43471
|
switch (code) {
|
|
42869
43472
|
case "0000":
|
|
42870
43473
|
str += "\\0";
|
|
@@ -42894,23 +43497,23 @@ var require_stringifyString = __commonJS({
|
|
|
42894
43497
|
if (code.substr(0, 2) === "00")
|
|
42895
43498
|
str += "\\x" + code.substr(2);
|
|
42896
43499
|
else
|
|
42897
|
-
str +=
|
|
43500
|
+
str += json2.substr(i, 6);
|
|
42898
43501
|
}
|
|
42899
43502
|
i += 5;
|
|
42900
43503
|
start = i + 1;
|
|
42901
43504
|
}
|
|
42902
43505
|
break;
|
|
42903
43506
|
case "n":
|
|
42904
|
-
if (implicitKey ||
|
|
43507
|
+
if (implicitKey || json2[i + 2] === '"' || json2.length < minMultiLineLength) {
|
|
42905
43508
|
i += 1;
|
|
42906
43509
|
} else {
|
|
42907
|
-
str +=
|
|
42908
|
-
while (
|
|
43510
|
+
str += json2.slice(start, i) + "\n\n";
|
|
43511
|
+
while (json2[i + 2] === "\\" && json2[i + 3] === "n" && json2[i + 4] !== '"') {
|
|
42909
43512
|
str += "\n";
|
|
42910
43513
|
i += 2;
|
|
42911
43514
|
}
|
|
42912
43515
|
str += indent;
|
|
42913
|
-
if (
|
|
43516
|
+
if (json2[i + 2] === " ")
|
|
42914
43517
|
str += "\\";
|
|
42915
43518
|
i += 1;
|
|
42916
43519
|
start = i + 1;
|
|
@@ -42920,7 +43523,7 @@ var require_stringifyString = __commonJS({
|
|
|
42920
43523
|
i += 1;
|
|
42921
43524
|
}
|
|
42922
43525
|
}
|
|
42923
|
-
str = start ? str +
|
|
43526
|
+
str = start ? str + json2.slice(start) : json2;
|
|
42924
43527
|
return implicitKey ? str : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false));
|
|
42925
43528
|
}
|
|
42926
43529
|
function singleQuotedString(value, ctx) {
|
|
@@ -45278,11 +45881,11 @@ var require_Document = __commonJS({
|
|
|
45278
45881
|
throw new Error(`With a null YAML version, the { schema: Schema } option is required`);
|
|
45279
45882
|
}
|
|
45280
45883
|
// json & jsonArg are only used from toJSON()
|
|
45281
|
-
toJS({ json, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
|
|
45884
|
+
toJS({ json: json2, jsonArg, mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
|
|
45282
45885
|
const ctx = {
|
|
45283
45886
|
anchors: /* @__PURE__ */ new Map(),
|
|
45284
45887
|
doc: this,
|
|
45285
|
-
keep: !
|
|
45888
|
+
keep: !json2,
|
|
45286
45889
|
mapAsMap: mapAsMap === true,
|
|
45287
45890
|
mapKeyWarned: false,
|
|
45288
45891
|
maxAliasCount: typeof maxAliasCount === "number" ? maxAliasCount : 100
|
|
@@ -61932,7 +62535,8 @@ async function reinspectPrivateSkillSubmissionCandidate(draftId, options = {}) {
|
|
|
61932
62535
|
const resumingReinspectionHold = isPrivateSkillSubmissionReinspectionHold(current);
|
|
61933
62536
|
const resumingDestinationHold = isPrivateSkillDestinationHold(current) && !isPrivateSkillDestinationRecoveryBlocked(current, destination);
|
|
61934
62537
|
const resumingResolution = current.delivery_resolution !== null;
|
|
61935
|
-
const
|
|
62538
|
+
const resumingConfigurationHold = options.resumeConfigurationHold === true && isPrivateSkillConfigurationHold(current);
|
|
62539
|
+
const resumingHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution || resumingConfigurationHold;
|
|
61936
62540
|
if (resumingReinspectionHold && !resumingResolution && current.inspection?.inspector_digest === PRIVATE_LEARNING_INSPECTOR_DIGEST && current.inspection.outcome !== "unchanged" && current.inspection.outcome !== "redacted") {
|
|
61937
62541
|
return Object.freeze({ status: "held", draft: current });
|
|
61938
62542
|
}
|
|
@@ -64799,6 +65403,7 @@ async function inspectPrivateLearningOutbox(input, persistence) {
|
|
|
64799
65403
|
status: skillResult.value.recovery_items.length > 0 ? "recovery_required" : "ok",
|
|
64800
65404
|
drafts: skillResult.value.drafts.map((draft) => ({
|
|
64801
65405
|
...draft,
|
|
65406
|
+
...privateSkillPermanentRefusalGuidance(draft),
|
|
64802
65407
|
recovery_context: { status: "context_unavailable" },
|
|
64803
65408
|
agent_recovery: privateSkillExactInspectionRecovery(draft)
|
|
64804
65409
|
})),
|
|
@@ -65104,6 +65709,7 @@ function privateSkillSelectedDraftResult(draft) {
|
|
|
65104
65709
|
draft,
|
|
65105
65710
|
PRIVATE_LEARNING_CAPTURE_VERSION
|
|
65106
65711
|
),
|
|
65712
|
+
...privateSkillPermanentRefusalGuidance(draft),
|
|
65107
65713
|
recovery_context: recoveryContext,
|
|
65108
65714
|
native_recovery_context: nativeContext ? {
|
|
65109
65715
|
...nativeContext,
|
|
@@ -67339,8 +67945,8 @@ function inspectPrivateLearningOutbox2(input, dependencies = {}) {
|
|
|
67339
67945
|
}
|
|
67340
67946
|
var MAX_REMOTE_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
67341
67947
|
var DOCTOR_PROBE_TIMEOUT_MS = 7500;
|
|
67342
|
-
var SERVER_VERSION = true ? "0.2.
|
|
67343
|
-
var
|
|
67948
|
+
var SERVER_VERSION = true ? "0.2.4" : "0.0.0-dev";
|
|
67949
|
+
var tools2 = toolDefinitions;
|
|
67344
67950
|
var doctorCliRequested = process.argv[2] === "doctor";
|
|
67345
67951
|
var nativeContextCliRequested = process.argv[2] === "--native-context";
|
|
67346
67952
|
function legacyBroadWritesEnabled(env = process.env) {
|
|
@@ -68041,6 +68647,10 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
|
|
|
68041
68647
|
});
|
|
68042
68648
|
}
|
|
68043
68649
|
let draft = await readPrivateSkillDraft(draftId);
|
|
68650
|
+
const resumingConfigurationHold = mode === "retry" && isPrivateSkillConfigurationHold(draft);
|
|
68651
|
+
if (isPrivateSkillConfigurationHold(draft) && !resumingConfigurationHold) {
|
|
68652
|
+
return privateSkillDraftActionResult2(draft, { status: "not_submitted" });
|
|
68653
|
+
}
|
|
68044
68654
|
const destination = privateSkillDestinationForAccess(access);
|
|
68045
68655
|
const resumingReinspectionHold = isPrivateSkillSubmissionReinspectionHold(draft);
|
|
68046
68656
|
const resumingDestinationHold = isPrivateSkillDestinationHold(draft) && !isPrivateSkillDestinationRecoveryBlocked(draft, destination);
|
|
@@ -68053,10 +68663,10 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
|
|
|
68053
68663
|
next_action: null
|
|
68054
68664
|
});
|
|
68055
68665
|
}
|
|
68056
|
-
const resumingLocalHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution;
|
|
68666
|
+
const resumingLocalHold = resumingReinspectionHold || resumingDestinationHold || resumingResolution || resumingConfigurationHold;
|
|
68057
68667
|
const deferredDestinationProof = draft.state === "retry_scheduled" && draft.last_error_code === "private_skill_destination_audience_proof_unavailable";
|
|
68058
68668
|
const awaitingDestinationCapability = isPrivateSkillDestinationCapabilityHold(draft) && !resumingResolution;
|
|
68059
|
-
if ((mode === "retry" && !resumingResolution || deferredDestinationProof || resumingResolution && draft.state === "retry_scheduled") && !resumingReinspectionHold && !resumingDestinationHold && !awaitingDestinationCapability) {
|
|
68669
|
+
if ((mode === "retry" && !resumingResolution || deferredDestinationProof || resumingResolution && draft.state === "retry_scheduled") && !resumingReinspectionHold && !resumingDestinationHold && !resumingConfigurationHold && !awaitingDestinationCapability) {
|
|
68060
68670
|
const retryGate = privateSkillRetryGate(draft);
|
|
68061
68671
|
if (retryGate) {
|
|
68062
68672
|
return privateSkillDraftActionResult2(draft, retryGate);
|
|
@@ -68085,7 +68695,8 @@ async function deliverPrivateSkillDraft(draftId, access, mode, transport) {
|
|
|
68085
68695
|
});
|
|
68086
68696
|
}
|
|
68087
68697
|
const reinspection = await reinspectPrivateSkillSubmissionCandidate(draftId, {
|
|
68088
|
-
destination
|
|
68698
|
+
destination,
|
|
68699
|
+
resumeConfigurationHold: resumingConfigurationHold
|
|
68089
68700
|
});
|
|
68090
68701
|
draft = reinspection.draft;
|
|
68091
68702
|
if (reinspection.status === "held") {
|
|
@@ -68398,6 +69009,16 @@ async function holdPrivateSkillDestination(draft, errorCode) {
|
|
|
68398
69009
|
async function persistPrivateSkillFailure(draft, result, destinationBodyLimit) {
|
|
68399
69010
|
return updatePrivateSkillDraft(draft.draft_id, (current) => {
|
|
68400
69011
|
const attempts = current.attempts;
|
|
69012
|
+
const failure = remembranceMcpToolFailure(result, "propose_private_skill");
|
|
69013
|
+
if (failure && failure.http_status >= 500 && failure.http_status <= 599 && !failure.retryable) {
|
|
69014
|
+
return {
|
|
69015
|
+
...current,
|
|
69016
|
+
state: "held_validation",
|
|
69017
|
+
next_retry_at: null,
|
|
69018
|
+
last_error_code: failure.code === PRIVATE_SKILL_CONFIGURATION_REFUSAL ? PRIVATE_SKILL_CONFIGURATION_REFUSAL : PRIVATE_SKILL_PERMANENT_SERVICE_REFUSAL,
|
|
69019
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
69020
|
+
};
|
|
69021
|
+
}
|
|
68401
69022
|
if (destinationBodyLimit !== null) {
|
|
68402
69023
|
const nextRetryAt = privateSkillRetryAt(attempts);
|
|
68403
69024
|
return {
|
|
@@ -68726,7 +69347,8 @@ function privateSkillDraftActionResult2(draft, extra = {}) {
|
|
|
68726
69347
|
last_error_code: draft.last_error_code,
|
|
68727
69348
|
retained_locally: true,
|
|
68728
69349
|
next_action: privateSkillDraftNextAction(draft),
|
|
68729
|
-
...extra
|
|
69350
|
+
...extra,
|
|
69351
|
+
...privateSkillPermanentRefusalGuidance(draft)
|
|
68730
69352
|
};
|
|
68731
69353
|
}
|
|
68732
69354
|
function privateSkillDraftNextAction(draft) {
|
|
@@ -71183,7 +71805,7 @@ function boundedLocalProfileField(value) {
|
|
|
71183
71805
|
return normalized2 ? normalized2.slice(0, 512) : null;
|
|
71184
71806
|
}
|
|
71185
71807
|
function mustFindTool(name) {
|
|
71186
|
-
const tool =
|
|
71808
|
+
const tool = tools2.find((item) => item.name === name);
|
|
71187
71809
|
if (!tool) {
|
|
71188
71810
|
throw new Error(`Missing internal tool definition: ${name}`);
|
|
71189
71811
|
}
|