senkani authorship
Manage knowledge-base authorship tags. The backfill subcommand bulk-tags legacy rows whose authorship column is NULL — the operator-triggered path for healing pre-V.5 KB state.
Syntax
Behavior
Walks knowledge_entities rows whose authorship column is literally NULL and whose created_at >= since, then writes the chosen tag. The in-band .unset sentinel (an explicit operator deferral from the V.5b prompt path) and the three explicit tags are never overwritten.
Without --yes, the command prints a dry-run preview (project root, count, tag) and exits without writing. With --yes, it writes inside a single SQL transaction and is idempotent — a second pass with the same args matches zero rows because the predicate (authorship IS NULL) no longer holds.
Each non-empty batch records one row in the chain-participating commands table (Phase T.5 round 3) with tool_name="authorship.backfill". The row carries a 64-char SHA-256 entry_hash — that is the "self-audited row in the chain" required by V.5c.
Cavoukian invariant: bulk operations are operator-triggered, never automatic. The CLI rejects --tag unset because backfill exists to record an explicit decision.
Example
$ senkani authorship backfill --since 2026-01-01 --tag humanAuthored Project: /Users/op/code/myproj Found 14 legacy row(s) with NULL authorship created on/after 2026-01-01. Would tag as: Human (human-authored). DRY RUN — nothing written. Re-run with --yes to apply. $ senkani authorship backfill --since 2026-01-01 --tag humanAuthored --yes Tagged 14 row(s) as Human (human-authored). Audit-chain row recorded (commands table, session=8a3f0c9e…).
Flags
created_at (UTC). Rows older than this are left alone.aiAuthored, humanAuthored, mixed. The unset sentinel is rejected.<root>/.senkani/vault.db).See also
Sources/CLI/AuthorshipCommand.swift, Sources/Core/AuthorshipBackfillRunner.swift, Sources/Core/KnowledgeStore/EntityStore.swift (backfillNullAuthorship)