@remembrance-ai/opencode-plugin 0.1.55 → 0.1.60

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.
@@ -13,10 +13,13 @@ The presence of this filesystem skill does not, by itself, prove that the
13
13
  native plugin is fully active. The first time Remembrance is relevant in a host
14
14
  session, call `run_connection_doctor` before relying on plugin automation. A
15
15
  healthy native install reports its MCP transport, authenticated scope, and the
16
- observed startup and prompt lifecycle after a safe catalog read. Local MCP also reports
17
- `local_signing_identity` without exposing its subject or private key. A missing
18
- identity initializes automatically on the first signed contribution; an
19
- invalid identity requires explicit restore or rotation. Follow the returned
16
+ observed startup and prompt lifecycle after a safe catalog read. Local MCP also
17
+ reports `local_signing_identity` without exposing its subject or private key. A
18
+ missing identity initializes automatically and is reused as the installation
19
+ principal; an invalid identity requires explicit restore or rotation. Local MCP
20
+ and native plugins obtain a revocable 24-hour principal session in the
21
+ background and register a privacy-bounded runtime profile. They never transmit
22
+ the hostname, username, config path, or repository path. Follow the returned
20
23
  machine-readable `next_action` rather than asking the user to invent an
21
24
  identity. Tool-observer and completion timestamps appear after those events
22
25
  become eligible; their absence during the first prompt is not, by itself, a
@@ -116,13 +119,30 @@ Do not use this skill when:
116
119
  plugin-instruction compliance loop and never affects ranking or trust.
117
120
  3. Use `match_tier` as a decision aid, not rank alone. First compare `why_matched` (bounded matched terms and capabilities, satisfied and missed constraints, exact-domain agreement, and qualitative lexical/semantic evidence) with `applicability` (likely/conditional/unlikely/unknown fit, general/specialized/corner-case scope, and declared `use_when`/`avoid_when` conditions). Raw numerical ranking scores are intentionally not exposed. Unknown applicability never means general applicability. Rule out an `unlikely` or irrelevant corner-case result and report query fit `poor`; do not force its use. A remaining `high` match is a required next step: open it with `get_skill` or `get_resource` and pass the returned `query_id` plus that candidate's `result_id` before doing custom work. `possible` and `exploratory` matches remain optional. Use `match_reason`, tags, capabilities, required permissions, dependencies, contraindications, `estimated_tokens`, verified uses, risk, freshness, confidence, and the bounded failure-mode digest to decide whether to proceed. A qualified `potential_savings` field is a conservative token-only estimate backed by a signed grade A/B proof for the exact skill version, model revision, reasoning effort, and bounded task cohort; it is omitted when those gates do not pass.
118
121
  4. Read `skill_access` on every query response. When its policy is `org_only`, use only returned organization skills and never fall back to bundled or live public references. Otherwise, if a selected public skill is bundled locally, `references/<slug>.md` remains the offline fallback. During a correlated online query, prefer the live `get_skill` call so Remembrance can observe surfaced -> opened and return current content. See "Specialized skills" below.
119
- 5. Use the selected skill or resource. When delegating, pass its slug, `query_id`, and `result_id` to the subagent; the subagent must open that result or run its own full-context query before custom work.
120
- 6. After meaningful use, report task completion or abandonment with `report_task_outcome`. Remembrance accepts one terminal outcome per query or direct invocation; retry the same report with the same idempotency key instead of submitting a different later outcome. Use only result IDs from `task_outcome.eligible_result_ids`. Each result and bundle also carries `task_outcome_eligible`; `task_outcome.available` is true only when at least one result is eligible. One result ID attributes the outcome to that result. When two or three selected query results exactly match a returned bundle, include its `bundle_id` to attribute the outcome only to that bundle. Other multi-result combinations are accepted as funnel telemetry without proof or cohort attribution. Include success, latency, and detailed token totals only when the runtime exposes them. For Vercel AI Gateway work, include every `gen_` generation ID in `metering_reference`; Remembrance retrieves the authoritative records asynchronously, so caller totals never establish proof trust. Never include prompts, transcripts, outputs, source paths, or private URLs. Then submit quick feedback with the same `query_id` and `result_id`; if the feedback response includes `next_step.submit_remembrance_payload`, submit that full remembrance when the lesson should become reusable evidence. If it includes `feedback_pattern_suggestion`, Remembrance has already created a reviewable candidate update from repeated feedback; do not submit a duplicate suggestion. Direct selections use post-use feedback only and are excluded from query-fit and reranker training.
121
- 7. Before finishing, self-check both halves of the loop: confirm that a relevant query actually happened, then check for high-value failure lessons. If the query was missed, run it from the full conversation before concluding. If a high match was surfaced but not opened, open it now or submit `fit: "poor"` query feedback with an explicit reason. If you caught your own mistake, the user caught one, CI/deploy failed, a security issue surfaced, or you fixed a release/versioning miss, submit a `failure_report` remembrance even if no skill was used. Native plugins prompt once for an unopened high match and reusable evidence at completion; raw MCP, REST, and skill-only installs must do these checks proactively.
122
- 8. If no suitable skill exists and the query response includes `no_results.propose_skill_idea_payload`, verify it, then choose the proposal route by asking one question: **could this content be harmful or unwanted as a public candidate?** If yes — anything repository-derived or organization-specific — use `propose_private_skill`, which cannot create a public candidate under any credential state. Use `propose_skill_idea` only when a public candidate is an acceptable outcome: an active organization key keeps it private, while intentionally omitting a key creates a PUBLIC candidate. A supplied invalid/inactive key fails with 401 and an insufficient key fails with 403; neither failure creates a candidate. Either route, read `visibility` in the successful response (`organization_private` or `public_candidate`) and state where the candidate landed. Never remove, hide, or bypass an organization key to force a public candidate; submit privately, then use the reviewed public-propagation flow when the organization wants to share it.
123
- 9. If no suitable skill exists and you create a reusable method, submit it through the same explicit private-versus-public boundary.
124
- 10. If you discover a reusable API, MPP endpoint, MCP server, docs site, package, dataset, service, or tool, submit it as a resource.
125
- 11. If a skill or resource seems duplicated, stale, unsafe, or incomplete, submit a suggestion instead of silently changing it.
122
+ 5. Apply any returned `effective_preferences` through the sibling
123
+ `preference_application`. A preference may steer among already-relevant
124
+ skills inside the same match tier or surgically alter a discretionary
125
+ presentation, workflow, or strategy choice. It never changes the underlying
126
+ relevance evidence, tier, or applicability. Required organization guidance
127
+ is authoritative; an explicit task or opaque project-context preference
128
+ outranks personal and skill defaults only when it does not conflict with that
129
+ guidance. Preserve safety, authorization, privacy, applicability, required
130
+ skill steps, validation, and review. When the user states a durable working
131
+ preference, call `record_preference`: built-ins need key/value; another
132
+ preference needs a stable `<effect>.<concept>` key, stable value, short label,
133
+ normalized behavior, `presentation|workflow|strategy_selection` effect,
134
+ `prefer|avoid` strength, and definition version. Use `scope: "auto"` unless
135
+ the user explicitly limited it to a project, skill, or domain. Send only
136
+ redacted hashes, never raw prompt or feedback text. A missing principal
137
+ session means personal preferences are unavailable, not that the query
138
+ failed.
139
+ 6. Use the selected skill or resource. When delegating, pass its slug, `query_id`, and `result_id` to the subagent; the subagent must open that result or run its own full-context query before custom work.
140
+ 7. After meaningful use, report task completion or abandonment with `report_task_outcome`. Remembrance accepts one terminal outcome per query or direct invocation; retry the same report with the same idempotency key instead of submitting a different later outcome. Use only result IDs from `task_outcome.eligible_result_ids`. Each result and bundle also carries `task_outcome_eligible`; `task_outcome.available` is true only when at least one result is eligible. One result ID attributes the outcome to that result. When two or three selected query results exactly match a returned bundle, include its `bundle_id` to attribute the outcome only to that bundle. Other multi-result combinations are accepted as funnel telemetry without proof or cohort attribution. Include success, latency, and detailed token totals only when the runtime exposes them. For Vercel AI Gateway work, include every `gen_` generation ID in `metering_reference`; Remembrance retrieves the authoritative records asynchronously, so caller totals never establish proof trust. Never include prompts, transcripts, outputs, source paths, or private URLs. Then submit quick feedback with the same `query_id` and `result_id`; if the feedback response includes `next_step.submit_remembrance_payload`, submit that full remembrance when the lesson should become reusable evidence. If it includes `feedback_pattern_suggestion`, Remembrance has already created a reviewable evidence candidate; do not submit a duplicate suggestion. Direct selections use post-use feedback only and are excluded from query-fit and reranker training.
141
+ 8. Before finishing, self-check both halves of the loop: confirm that a relevant query actually happened, then check for high-value failure lessons. If the query was missed, run it from the full conversation before concluding. If a high match was surfaced but not opened, open it now or submit `fit: "poor"` query feedback with an explicit reason. If you caught your own mistake, the user caught one, CI/deploy failed, a security issue surfaced, or you fixed a release/versioning miss, submit a `failure_report` remembrance even if no skill was used. Native plugins prompt once for an unopened high match and reusable evidence at completion; raw MCP, REST, and skill-only installs must do these checks proactively.
142
+ 9. If no suitable skill exists and the query response includes `no_results.propose_skill_idea_payload`, verify it, then choose the proposal route by asking one question: **could this content be harmful or unwanted as a public candidate?** If yes — anything repository-derived or organization-specific — use `propose_private_skill`, which cannot create a public candidate under any credential state. Use `propose_skill_idea` only when a public candidate is an acceptable outcome: an active organization key keeps it private, while intentionally omitting a key creates a PUBLIC candidate. A supplied invalid/inactive key fails with 401 and an insufficient key fails with 403; neither failure creates a candidate. Either route, read `visibility` in the successful response (`organization_private` or `public_candidate`) and state where the candidate landed. Never remove, hide, or bypass an organization key to force a public candidate; submit privately, then use the reviewed public-propagation flow when the organization wants to share it.
143
+ 10. If no suitable skill exists and you create a reusable method, submit it through the same explicit private-versus-public boundary.
144
+ 11. If you discover a reusable API, MPP endpoint, MCP server, docs site, package, dataset, service, or tool, submit it as a resource.
145
+ 12. If a skill or resource seems duplicated, stale, unsafe, or incomplete, submit evidence or a suggestion. You may include an advisory `routing_hint`, but do not decide or promise whether Remembrance will amend, specialize, fork, or create a skill.
126
146
 
127
147
  ## Token savings and value proof
128
148
 
@@ -160,30 +180,34 @@ task content: report only opaque IDs, categorical task features, bounded scope
160
180
  counts, token totals, timing, success, model/reasoning identifiers, and the
161
181
  measurement source.
162
182
 
163
- ## Evolve, create new, or fork
164
-
165
- Split on WORKFLOW identity, not on data agreement:
166
-
167
- - **Same task, same approach, new facts** (an extra failure mode, a better
168
- step, a version note): EVOLVE the existing skill. Submit a remembrance tied
169
- to the skill and attach `suggested_update` (`amend_skill`,
170
- `metadata_update`, or `deprecate_skill`) when the skill text itself should
171
- change — if your evidence survives verification, Remembrance promotes it
172
- into a reviewed suggestion automatically.
173
- - **Same task, same approach, contradictory result** where both the skill's
174
- guidance and your evidence are valid under different conditions (version,
175
- platform, configuration, scale): still EVOLVE. Name the condition
176
- explicitly in the lesson. Contradicting well-supported evidence is never
177
- rejected for disagreeing — it recalibrates confidence in the old guidance
178
- and becomes a reviewed caveat.
179
- - **Same task, genuinely different approach** (different tool or strategy):
180
- propose a NEW skill idea with a title scoped to the approach. Overlap is
181
- expected — Remembrance links siblings (`related_skills`, `forked_from`),
182
- reviewers can fork instead of merging, and queries return both so callers
183
- decide.
184
- - **Never create a near-duplicate just to record disagreement**: a duplicate
185
- at high similarity is auto-merged or held, and splitting evidence between
186
- twin skills drops BOTH to low confidence.
183
+ ## Submit evidence; Remembrance chooses the topology
184
+
185
+ Do not force yourself to decide whether a lesson should amend, specialize,
186
+ fork, or create a skill. Submit immutable evidence with the stable conditions
187
+ that made it true. An optional `routing_hint` is useful context but is never
188
+ authoritative.
189
+
190
+ Remembrance independently classifies the evidence after static safety,
191
+ duplicate search, target existence, risk, verifier, and organization-policy
192
+ checks:
193
+
194
+ - a universal correction or reusable detail can **amend** the target;
195
+ - a stable runtime, version, platform, framework, scale, or task-stage
196
+ condition can become a scoped **specialization**;
197
+ - a genuinely different approach can become a **strategy fork**;
198
+ - a distinct reusable job can become an **independent skill**;
199
+ - a subjective but reusable presentation, workflow, or strategy choice becomes
200
+ a typed **preference** rather than canonical instructions;
201
+ - a one-off incident or insufficient pattern remains **evidence only**; and
202
+ - uncertainty, missing targets, or safety concerns **hold** for review.
203
+
204
+ Missing or malformed topology output never mutates a skill. Organization
205
+ evidence can create only private organization artifacts. A specialization is a
206
+ complete reviewed version pinned to the exact parent version with structured
207
+ conditions and readable `use_when`/`avoid_when`; later parent changes produce a
208
+ reviewed compatibility/rebase candidate rather than silently rewriting it. See
209
+ `references/identity-preferences-topology.md` for identity, preference, and
210
+ lineage details.
187
211
 
188
212
  ## Specialized skills
189
213
 
@@ -201,7 +225,7 @@ workflow at `references/<slug>.md`.
201
225
  references for every public seeded skill at install time. Today these are
202
226
  `remembrance-setup.md`, `mpp.md`, `web-ui-ux-qa.md`, and
203
227
  `resource-scout.md`, plus the topical references `remembrance-payloads.md`
204
- and `attestation-rest.md`.
228
+ `attestation-rest.md`, and `identity-preferences-topology.md`.
205
229
  2. **Live detail (preferred after an online query):** call `get_skill` with the
206
230
  candidate slug, `query_id`, and `result_id`. REST clients use
207
231
  `GET /api/v1/skills/<slug>?query_id=<rq_...>&result_id=<qres_...>`. This
@@ -381,9 +405,10 @@ them up. Evidence-backed submissions verify faster and rank higher.
381
405
 
382
406
  Repeated substantive feedback for the same skill may also return
383
407
  `feedback_pattern_suggestion`. That means Remembrance synthesized a reviewable
384
- `metadata_update` suggestion from the recent pattern and queued it for normal
385
- verification, quality gates, versioning, and admin/enterprise review. Treat it
386
- as a receipt; it does not mean the live skill changed.
408
+ evidence candidate from the recent pattern and queued it for topology routing,
409
+ normal verification, quality gates, versioning, and admin/enterprise review.
410
+ Treat it as a receipt; it does not mean the live skill changed or predetermine
411
+ whether the result will amend, specialize, fork, create, or remain evidence.
387
412
 
388
413
  `suggested_update` on a remembrance is honored: when the remembrance itself is
389
414
  accepted, Remembrance promotes it into a reviewed suggestion (`amend_skill`,
@@ -45,11 +45,22 @@ If this file is lost, rerun this REST bootstrap recipe. The new key starts a new
45
45
  TOFU subject trust history; the previous verified-tier history is not
46
46
  recoverable without the old private key.
47
47
 
48
- ## Key registration signing payload v1
48
+ ## Key registration signing payload v2
49
49
 
50
- Register a TOFU public key with:
50
+ First fetch the opaque owner binding with the same credential that will own the
51
+ installation, then register the TOFU public key:
51
52
 
52
- `POST https://remembrance.dev/api/v1/agent/keys/register`
53
+ ```text
54
+ GET https://remembrance.dev/api/v1/agent/keys/register
55
+ POST https://remembrance.dev/api/v1/agent/keys/register
56
+ ```
57
+
58
+ The GET response is private and non-cacheable. Include its `owner_binding` in
59
+ both the canonical payload and `proof`. This prevents an anonymous registration
60
+ signature from being replayed to claim the installation for an organization.
61
+ Legacy v1 signatures remain valid only for anonymous registration and an
62
+ already-owned same-scope key; new organization claims and anonymous-to-org
63
+ upgrades require v2.
53
64
 
54
65
  If `key_id` is omitted, compute:
55
66
 
@@ -65,10 +76,11 @@ Sign this canonical object:
65
76
 
66
77
  ```json
67
78
  {
68
- "version": "v1",
79
+ "version": "v2",
69
80
  "purpose": "remembrance-agent-key-registration",
70
81
  "provider": "other",
71
82
  "key_id": "tofu_...",
83
+ "owner_binding": "areg_...",
72
84
  "public_key_hash": "sha256:<hex>",
73
85
  "subject": "claude:local-install-stable-id",
74
86
  "signed_at": "2026-05-06T12:00:00.000Z"
@@ -85,6 +97,7 @@ Submit:
85
97
  "subject": "claude:local-install-stable-id",
86
98
  "proof": {
87
99
  "algorithm": "ed25519",
100
+ "owner_binding": "areg_...",
88
101
  "signed_at": "2026-05-06T12:00:00.000Z",
89
102
  "signature": "base64url-ed25519-signature"
90
103
  },
@@ -291,6 +304,23 @@ async function post(path, body, idempotencyKey) {
291
304
  return parsed;
292
305
  }
293
306
 
307
+ async function get(path) {
308
+ const response = await fetch(`${api}${path}`, {
309
+ headers: {
310
+ ...(process.env.REMEMBRANCE_API_KEY
311
+ ? { "x-remembrance-api-key": process.env.REMEMBRANCE_API_KEY }
312
+ : {}),
313
+ },
314
+ });
315
+ const parsed = await response.json().catch(() => ({}));
316
+ if (!response.ok) {
317
+ throw new Error(
318
+ `${path} failed with ${response.status}: ${JSON.stringify(parsed)}`,
319
+ );
320
+ }
321
+ return parsed;
322
+ }
323
+
294
324
  async function readOrCreateIdentity() {
295
325
  if (existsSync(keyPath)) {
296
326
  return JSON.parse(await readFile(keyPath, "utf8"));
@@ -315,12 +345,19 @@ async function readOrCreateIdentity() {
315
345
  }
316
346
 
317
347
  const identity = await readOrCreateIdentity();
348
+ const { owner_binding: ownerBinding } = await get(
349
+ "/api/v1/agent/keys/register",
350
+ );
351
+ if (!/^areg_[A-Za-z0-9_-]{24,120}$/.test(String(ownerBinding ?? ""))) {
352
+ throw new Error("Remembrance returned an invalid registration binding");
353
+ }
318
354
  const signedAt = new Date().toISOString();
319
355
  const registrationPayload = canonicalJson({
320
- version: "v1",
356
+ version: "v2",
321
357
  purpose: "remembrance-agent-key-registration",
322
358
  provider: identity.provider,
323
359
  key_id: identity.key_id,
360
+ owner_binding: ownerBinding,
324
361
  public_key_hash: hashValue(identity.public_key),
325
362
  subject: identity.subject,
326
363
  signed_at: signedAt,
@@ -332,6 +369,7 @@ await post("/api/v1/agent/keys/register", {
332
369
  subject: identity.subject,
333
370
  proof: {
334
371
  algorithm: "ed25519",
372
+ owner_binding: ownerBinding,
335
373
  signed_at: signedAt,
336
374
  signature: signBase64Url(identity.private_key, registrationPayload),
337
375
  },
@@ -0,0 +1,221 @@
1
+ # Installation identity, preferences, and skill topology
2
+
3
+ Use this reference when an organization shares one API key across engineers or
4
+ agent surfaces, when an agent needs to record a durable presentation
5
+ preference, or when evidence may be too specific to amend a general skill.
6
+
7
+ ## Identity model
8
+
9
+ The organization API key establishes the tenant and allowed API operations. It
10
+ does not identify a person or an individual runtime. `agent_id` remains
11
+ descriptive metadata and never establishes identity.
12
+
13
+ Local plugins and stdio MCP use the existing Ed25519 TOFU key as one stable
14
+ **installation principal** per OS/config profile. Registration happens
15
+ automatically and is retried without blocking query or invocation. The local
16
+ client signs a one-time challenge at:
17
+
18
+ ```text
19
+ POST /api/v1/agent/principal-sessions
20
+ ```
21
+
22
+ The exchange returns an opaque, revocable 24-hour token sent as:
23
+
24
+ ```text
25
+ X-Remembrance-Principal-Session: psess_...
26
+ ```
27
+
28
+ `POST /api/v1/agent/economics/session` and
29
+ `X-Remembrance-Economics-Session` remain backward-compatible aliases. Query
30
+ and explicit skill invocation ignore unusable or expired session context and
31
+ continue under the already established API-key or anonymous scope; identity,
32
+ member-link, and preference mutations reject that context.
33
+ An organization-owned principal session is an identity supplement, not a
34
+ tenant credential: every request using it must also send a valid API key for
35
+ the same organization. Without that key, retrieval drops the session and
36
+ continues anonymously; identity and preference mutations reject it.
37
+ Send one session header. If a legacy client sends both, the principal-session
38
+ header takes precedence.
39
+
40
+ Each installation may have child **runtime profiles** for Codex Desktop, Codex
41
+ CLI, Claude Code, Cursor, OpenClaw, VS Code, OpenCode, raw MCP, or another
42
+ surface. A profile sends only normalized runtime/surface labels, bounded
43
+ versions, and a locally derived opaque profile key. Never send hostnames,
44
+ usernames, config paths, repository paths, or project names. Runtime profiles
45
+ and ephemeral subagents inherit the installation billing principal and do not
46
+ consume additional agent slots.
47
+
48
+ ## Optional member link
49
+
50
+ An unlinked installation is fully functional and may keep installation-local
51
+ preferences. To let preferences follow an engineer across machines and
52
+ runtimes, use **Dashboard > Agents > Instances > Install on this device**. That
53
+ flow creates a single-use token that expires after ten minutes. The token may be
54
+ included in the principal-session challenge or consumed with the MCP tool
55
+ `link_current_installation` / REST endpoint:
56
+
57
+ ```text
58
+ POST /api/v1/agent/member-links
59
+ ```
60
+
61
+ Reusable organization-key distribution commands must never include a member
62
+ token. Linking does not rotate the organization key or create another billed
63
+ agent. Members can rename their linked installations; organization admins can
64
+ assign, reassign, activate, or deactivate installations and label child runtime
65
+ profiles independently. Automatic runtime check-ins preserve custom profile
66
+ labels. Agent responses never contain member email addresses, Clerk IDs, or
67
+ internal organization IDs.
68
+
69
+ ## Preference contract
70
+
71
+ Preferences are bounded organization-local working choices, not edits to
72
+ canonical skill instructions. These built-in controls are convenient presets,
73
+ not a closed vocabulary:
74
+
75
+ - `comment_density`: `sparse`, `balanced`, `detailed`
76
+ - `comment_focus`: `intent_only`, `tricky_logic`, `api_contracts`,
77
+ `comprehensive`
78
+ - `explanation_depth`: `concise`, `balanced`, `detailed`
79
+ - `output_organization`: `compact`, `structured`, `step_by_step`
80
+
81
+ Use `get_effective_preferences` or
82
+ `POST /api/v1/agent/preferences/effective` to resolve task-relevant values.
83
+ Normal query and invocation responses also include
84
+ `preference_definition_version`, `effective_preferences`, and, for a selected
85
+ skill, `preference_application`. Extensible settings use a stable dotted key,
86
+ stable value, short label, concise normalized behavior, effect
87
+ (`presentation`, `workflow`, or `strategy_selection`), direction (`prefer` or
88
+ `avoid`), and definition version. Native hooks record recognized built-ins
89
+ silently. For another explicit durable preference, the hook asks the agent to
90
+ call `record_preference` with opaque hashes and `scope: "auto"`; the server binds
91
+ it to the linked member when present and otherwise to the installation.
92
+
93
+ Resolution order is:
94
+
95
+ 1. universal safety, authorization, privacy, applicability, required skill
96
+ steps, validation, and review requirements (hard constraints, not
97
+ preferences);
98
+ 2. required organization guidance;
99
+ 3. the current explicit task instruction;
100
+ 4. an explicit project-context preference;
101
+ 5. explicit member + runtime profile;
102
+ 6. explicit member;
103
+ 7. learned member + runtime profile;
104
+ 8. learned member;
105
+ 9. explicit installation fallback;
106
+ 10. learned installation;
107
+ 11. recommended organization guidance;
108
+ 12. declared skill default.
109
+
110
+ Organization admins choose Required or Recommended under \*\*Dashboard > Agents
111
+
112
+ > Preferences\*\*. Required applies to every organization agent. Recommended is a
113
+ > default that a clear task or personal preference may replace. The API field
114
+ > `project_key` is an opaque local project-context hash, not an administrator
115
+ > policy scope.
116
+
117
+ Use `record_preference` or `POST /api/v1/agent/preferences` only for an
118
+ built-in or complete bounded extensible setting. Submit an `evidence_hash`,
119
+ `task_hash`, scope, and confidence. Never upload the raw prompt, feedback text,
120
+ source path, or private task content.
121
+
122
+ Relevance and preference influence remain separate. The normal ranker first
123
+ establishes applicability and the stable `high`, `possible`, or `exploratory`
124
+ tier. Declared skill preference traits can then reorder candidates only inside
125
+ the same tier. The response reports qualitative matched/conflicted traits plus
126
+ `relevance_rank` and `personalized_rank`; it never exposes the internal bounded
127
+ adjustment. A single selected skill still receives a surgical preference
128
+ sidecar for discretionary behavior. A locked skill requirement blocks an
129
+ incompatible personal preference. A locked conflict with Required organization
130
+ guidance makes the skill ineligible. No preference weakens a hard constraint.
131
+
132
+ - An explicit durable user correction applies immediately.
133
+ - Inferred member or installation values require at least three consistent
134
+ observations across two tasks and two days with confidence at least `0.85`.
135
+ - A learned member + runtime residual requires four observations across three
136
+ tasks with confidence at least `0.85`.
137
+ - Learned values stop applying after 180 inactive days.
138
+ - Explicit values persist until changed.
139
+ - Each activation creates a reversible profile revision; the dashboard supports
140
+ undo and reset.
141
+
142
+ ## Evidence topology
143
+
144
+ The agent's job is to submit accurate, privacy-safe evidence. It does not need
145
+ to decide the final skill graph operation. `routing_hint` is optional and
146
+ non-authoritative:
147
+
148
+ ```json
149
+ {
150
+ "routing_hint": {
151
+ "suggested_action": "specialize",
152
+ "conditions": [
153
+ {
154
+ "dimension": "runtime_version",
155
+ "operator": "at_least",
156
+ "value": "2.0"
157
+ }
158
+ ]
159
+ }
160
+ }
161
+ ```
162
+
163
+ Remembrance runs static safety, duplicate search, target existence, risk,
164
+ verifier, and review-policy guards before selecting one route:
165
+
166
+ - `amend`: a universal correction or reusable detail for an existing skill;
167
+ - `specialize`: guidance that is valid under stable environment/task
168
+ conditions;
169
+ - `strategy_fork`: a genuinely different approach to the same job;
170
+ - `independent_skill`: a distinct reusable job;
171
+ - `preference`: a subjective but reusable presentation, workflow, or strategy
172
+ choice represented by a typed preference;
173
+ - `evidence_only`: a one-off incident or pattern that is not ready to shape a
174
+ skill; or
175
+ - `hold`: uncertainty, missing target, low confidence, or a safety/review gate.
176
+
177
+ Missing or malformed model topology output falls back to evidence-only or human
178
+ review. It never authorizes an automatic mutation. Organization evidence can
179
+ route only to private organization artifacts; public evidence follows the
180
+ public review pipeline. The public classifier learns only from global-admin
181
+ corrections, while each organization's adapter learns only from that
182
+ organization's admins.
183
+
184
+ ## Specialization lineage and rebase
185
+
186
+ A specialization is not a patch fragment. It is a complete reviewed version
187
+ with:
188
+
189
+ - `specialized_from` lineage;
190
+ - the exact parent version used during review;
191
+ - structured scope predicates;
192
+ - readable `use_when` and `avoid_when` guidance; and
193
+ - normal safety, quality, version, and rollback records.
194
+
195
+ When the parent advances, Remembrance creates a reviewed compatibility/rebase
196
+ candidate. It does not silently rewrite the child. Review cards state the
197
+ proposed operation, exact target or parent, stable conditions, consequence, and
198
+ either the complete new/specialized skill or the exact existing-skill diff.
199
+
200
+ Operators may temporarily disable preference recording/application with
201
+ `AGENT_PREFERENCES_ENABLED=false` or learned topology routing with
202
+ `SKILL_TOPOLOGY_AUTOMATION_ENABLED=false`. Query and invocation continue; the
203
+ latter control leaves the existing verified review/materialization path in
204
+ place.
205
+
206
+ ## Dashboard and APIs
207
+
208
+ - **Dashboard > Agents > Instances** lists privacy-safe installation/runtime
209
+ inventory and member assignments.
210
+ - **Dashboard > Agents > Preferences** lists effective values, confidence,
211
+ provenance, revisions, undo, and reset.
212
+ - **Dashboard > Verification > Topology** shows proposed routes, targets,
213
+ stable conditions, classifier versions, and reviewer overrides.
214
+ - `GET/PATCH /api/v1/enterprise/agent-instances` manages visible instances.
215
+ - `POST /api/v1/enterprise/agent-member-link` creates a one-time member token.
216
+ - `GET/PATCH /api/v1/enterprise/agent-preferences` manages dashboard preference
217
+ revisions.
218
+
219
+ Hosted MCP cannot read a local TOFU key or invent a human identity. Without a
220
+ client-held principal session it remains organization-level, while normal
221
+ query/invocation behavior continues.
@@ -35,12 +35,15 @@
35
35
 
36
36
  Legacy `attestation_token_hash` is no longer accepted. Verified trust uses `POST /api/v1/agent/attest/challenge` followed by a plugin-signed `evidence.attestation` object.
37
37
 
38
- `suggested_update` is honored when the remembrance itself is ACCEPTED: the
39
- update is promoted into a reviewed suggestion (`amend_skill`,
40
- `metadata_update`, `deprecate_skill`) or a new skill idea (`new_skill`), riding
41
- the normal verification and review pipeline — the live skill changes only
42
- after review. `score_adjustment` is ignored (scoring is deterministic); use
43
- `kind: "none"` when no change is proposed.
38
+ `suggested_update` describes a requested content operation; it does not decide
39
+ the final skill topology. When the remembrance itself is accepted, Remembrance
40
+ creates reviewable evidence through the normal verification pipeline. The
41
+ topology router may amend the target, create a scoped specialization, create a
42
+ strategy fork or independent skill, record a typed preference, retain evidence
43
+ without mutation, or hold for review. The live skill changes only after the
44
+ selected route clears its safety, quality, target, policy, and version guards.
45
+ `score_adjustment` is ignored (scoring is deterministic); use `kind: "none"`
46
+ when no content operation is proposed.
44
47
 
45
48
  Provider fields are intentionally split:
46
49
 
@@ -180,7 +183,8 @@ not discard valid post-use feedback or alter ranking by itself.
180
183
 
181
184
  The same response may also include `feedback_pattern_suggestion` when repeated
182
185
  substantive feedback for the same skill crosses the configured synthesis
183
- threshold. This is a reviewable candidate update, not a live mutation:
186
+ threshold. This is a reviewable evidence candidate for topology routing, not a
187
+ predetermined metadata update or a live mutation:
184
188
 
185
189
  ```json
186
190
  {
@@ -199,7 +203,8 @@ threshold. This is a reviewable candidate update, not a live mutation:
199
203
  ```
200
204
 
201
205
  Do not submit a duplicate suggestion for the same pattern. Wait for the
202
- verification/review/versioning result before assuming the active skill changed.
206
+ topology, verification, review, and versioning result before assuming the
207
+ active skill changed.
203
208
 
204
209
  Local identity recovery: the persisted key file
205
210
  `~/.config/remembrance/agent-key.json` is a private key. Back it up like an
@@ -329,6 +329,7 @@ enabled_tools = [
329
329
  "query_skills",
330
330
  "list_skills",
331
331
  "invoke_skill",
332
+ "get_effective_preferences",
332
333
  "get_skill",
333
334
  "get_resource",
334
335
  "get_value_proof",
@@ -338,6 +339,8 @@ enabled_tools = [
338
339
  "submit_remembrance",
339
340
  "propose_private_skill",
340
341
  "submit_suggestion",
342
+ "record_preference",
343
+ "link_current_installation",
341
344
  ]
342
345
  default_tools_approval_mode = "writes"
343
346
  ~~~
@@ -430,6 +433,7 @@ run_connection_doctor
430
433
  query_skills
431
434
  list_skills
432
435
  invoke_skill
436
+ get_effective_preferences
433
437
  get_skill
434
438
  get_resource
435
439
  get_value_proof
@@ -439,6 +443,8 @@ report_task_outcome
439
443
  submit_remembrance
440
444
  propose_private_skill
441
445
  submit_suggestion
446
+ record_preference
447
+ link_current_installation
442
448
  ~~~
443
449
 
444
450
  It intentionally omits `propose_skill_idea`, `submit_resource`,
@@ -496,6 +502,7 @@ Merge this into managed settings:
496
502
  "mcp__remembrance__query_skills",
497
503
  "mcp__remembrance__list_skills",
498
504
  "mcp__remembrance__invoke_skill",
505
+ "mcp__remembrance__get_effective_preferences",
499
506
  "mcp__remembrance__get_skill",
500
507
  "mcp__remembrance__get_resource",
501
508
  "mcp__remembrance__get_value_proof",
@@ -505,6 +512,8 @@ Merge this into managed settings:
505
512
  "mcp__remembrance__submit_remembrance",
506
513
  "mcp__remembrance__propose_private_skill",
507
514
  "mcp__remembrance__submit_suggestion",
515
+ "mcp__remembrance__record_preference",
516
+ "mcp__remembrance__link_current_installation",
508
517
  ]
509
518
  },
510
519
  "sandbox": {
@@ -551,6 +560,7 @@ narrow server/tool set:
551
560
  "query_skills",
552
561
  "list_skills",
553
562
  "invoke_skill",
563
+ "get_effective_preferences",
554
564
  "get_skill",
555
565
  "get_resource",
556
566
  "get_value_proof",
@@ -560,6 +570,8 @@ narrow server/tool set:
560
570
  "submit_remembrance",
561
571
  "propose_private_skill",
562
572
  "submit_suggestion",
573
+ "record_preference",
574
+ "link_current_installation",
563
575
  ],
564
576
  "trust": false
565
577
  }
@@ -604,6 +616,7 @@ tool profile hides MCP tools, and `tools.deny: ["bundle-mcp"]` disables them:
604
616
  "query_skills",
605
617
  "list_skills",
606
618
  "invoke_skill",
619
+ "get_effective_preferences",
607
620
  "get_skill",
608
621
  "get_resource",
609
622
  "get_value_proof",
@@ -613,6 +626,8 @@ tool profile hides MCP tools, and `tools.deny: ["bundle-mcp"]` disables them:
613
626
  "submit_remembrance",
614
627
  "propose_private_skill",
615
628
  "submit_suggestion",
629
+ "record_preference",
630
+ "link_current_installation",
616
631
  ]
617
632
  }
618
633
  }
package/src/index.mjs CHANGED
@@ -65,6 +65,7 @@ import {
65
65
  toolResponseIndicatesFailure,
66
66
  valueEpisodeFromResponse,
67
67
  writePromptedCount,
68
+ warmPrincipalSession,
68
69
  } from "../scripts/hook-core.mjs";
69
70
 
70
71
  const SURFACE = "opencode";
@@ -300,15 +301,24 @@ export const Remembrance = async (context = {}) => {
300
301
  try {
301
302
  const sessionId = sessionIdFromEvent(event, event);
302
303
  recordLifecycle("session_start", sessionId);
303
- const clientUpdate = await (
304
- context.clientUpdateCheck ?? checkForClientUpdate
305
- )(
306
- {
307
- surface: SURFACE,
308
- currentVersion: version,
309
- },
310
- env,
311
- ).catch(() => null);
304
+ const [, clientUpdate] = await Promise.all([
305
+ (context.warmSession ?? warmPrincipalSession)(
306
+ {
307
+ runtime: SURFACE,
308
+ hostSurface: "cli",
309
+ clientVersion: version,
310
+ hostVersion: "",
311
+ },
312
+ env,
313
+ ).catch(() => null),
314
+ (context.clientUpdateCheck ?? checkForClientUpdate)(
315
+ {
316
+ surface: SURFACE,
317
+ currentVersion: version,
318
+ },
319
+ env,
320
+ ).catch(() => null),
321
+ ]);
312
322
  if (clientUpdate?.notice) {
313
323
  pendingClientUpdates.set(sessionId, clientUpdate.notice);
314
324
  }