Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 0.2.99

- Add bounded exact binding-state readback and receipt-backed guarded adoption
for legacy Knowledge rows. Adoption requires the full ID, expected version,
and raw-content SHA-256; changes only the FCAME-1 binding/provenance fields;
replays deterministically; and can be rolled back only from its immutable
adoption receipt while the adopted row still matches.
- Preserve ordinary SQLite, hosted PostgreSQL/API, guarded-write, versioning,
and CLI behavior, including hosted deployments whose `tenant_id` column is
UUID rather than text.

## 0.2.98

- Ship the hosted guarded-write authority fix from #78: the authority trigger now
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,42 @@ zero or one terminal receipt. The producer disables blind transport retry:
after an ambiguous submission it reconciles the deterministic key first and
never replays the mutation without terminal evidence.

Rows created before FCAME-1 remain readable through ordinary exact-ID access,
but the guarded writer will not treat an unbound row as already guarded. Adopt
one only through the explicit bounded sequence:

```ts
const state = await guarded.readBindingState(fullId);
if (state.state !== 'legacy_unbound') throw new Error(state.state);

const adoption = await guarded.adoptLegacy({
operation_id: 'legacy-doctrine-adoption',
step_id: 'adopt-one',
target_id: fullId,
expected_version: state.item_version!,
expected_content_sha256: state.content_sha256!,
});

// Optional, conditional rollback. It succeeds only while this exact immutable
// adoption receipt is still the row's current provenance and version/content
// still match; a later adoption or content edit makes the receipt stale.
await guarded.rollbackLegacyAdoption({
operation_id: 'legacy-doctrine-adoption',
step_id: 'rollback-one',
adoption_receipt: adoption.receipt,
});
```

Binding-state reads use a full ID and return one of `legacy_unbound`,
`bound_to_requested`, or `bound_elsewhere`. The last state is limited to the
authenticated tenant and omits version/content hash. Adoption compares the
exact stored version and raw UTF-8 content SHA-256, changes only binding and
provenance columns, and preserves content, timestamps, version, and history.
The same deterministic operation returns the same immutable receipt with no
second effect. Ordinary `/v1/notes`, `knowledge update --if-version`, SQLite,
and raw SQL do not create an adoption claim and cannot substitute for this
path.

For any workflow touching multiple records or authorities, construct all
descriptors first. Derive the manifest ID with
`computeKnowledgeGuardedManifestId(maintainerBinding, workflowOperationId)`;
Expand Down
2 changes: 1 addition & 1 deletion bin/knowledge-mcp.js
Original file line number Diff line number Diff line change
Expand Up @@ -14997,7 +14997,7 @@ import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSy
// package.json
var package_default = {
name: "@hasna/knowledge",
version: "0.2.98",
version: "0.2.99",
description: "Agent-friendly local knowledge CLI with JSON output, pagination, and safe destructive actions",
type: "module",
exports: {
Expand Down
Loading
Loading