@zq-silk/yui 0.12.1 → 0.12.3

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.
@@ -37,6 +37,10 @@ export const TELEMETRY_RUN_CAP = 50_000;
37
37
  * `synchronous`/`foreign_keys`/`busy_timeout` are per-connection PRAGMAs set by
38
38
  * the store; `journal_mode=WAL` is a persistent database property set on open.
39
39
  * The migration itself only contains schema objects.
40
+ *
41
+ * This released SQL string, including its comments, is checksummed persistent
42
+ * history and must remain byte-for-byte unchanged. The `operator-notification`
43
+ * projection kind it creates is retained only for old layout-7 Homes.
40
44
  */
41
45
  const MIGRATION_1_SQL = `
42
46
  -- Global catalog and coordination (§4.1) -------------------------------------
@@ -327,8 +331,7 @@ CREATE TABLE IF NOT EXISTS events (
327
331
  );
328
332
  CREATE INDEX IF NOT EXISTS idx_events_type_time ON events(task_id, type, occurred_at);
329
333
 
330
- -- Per-task scheduler projections. operator-notification is a retired legacy
331
- -- kind retained only so old layout-7 Homes can be read by the upgrade path.
334
+ -- Per-task scheduler projections (leaderFailure, operatorNotification).
332
335
  CREATE TABLE IF NOT EXISTS task_projections (
333
336
  task_id TEXT NOT NULL,
334
337
  kind TEXT NOT NULL CHECK (kind IN ('leader-failure','operator-notification')),
@@ -535,6 +535,24 @@ export class SqliteTaskStore {
535
535
  ON CONFLICT(task_id, kind) DO UPDATE SET high_water = MAX(high_water, ?)`).run(taskId, kind, highWater, highWater);
536
536
  });
537
537
  }
538
+ /** Restore one validated historical grant into a disposable migration output. */
539
+ migrationRestoreCapabilityGrant(taskId, grant) {
540
+ if (!this.#migration) {
541
+ throw new StorageRecordError("Historical capability grants may only be restored into a migration sidecar.");
542
+ }
543
+ const stored = storedCapabilityGrant(grant);
544
+ if (stored.taskId !== taskId) {
545
+ throw new StorageRecordError(`Capability grant belongs to another Task: ${stored.taskId}`);
546
+ }
547
+ this.#requireTask(taskId);
548
+ this.#mutate(() => {
549
+ const existing = this.#getPayload("capability_grants", "task_id = ? AND grant_id = ?", [taskId, stored.id]);
550
+ if (existing !== null) {
551
+ throw new StorageRecordError(`Migration cannot overwrite capability grant: ${taskId}/${stored.id}`);
552
+ }
553
+ this.#db.prepare("INSERT INTO capability_grants (task_id, grant_id, payload, updated_at) VALUES (?, ?, ?, ?)").run(taskId, stored.id, this.#json(stored), this.#now());
554
+ });
555
+ }
538
556
  // -- generic payload helpers ------------------------------------------------
539
557
  #getPayload(table, where, params) {
540
558
  const row = this.#db.prepare(`SELECT payload FROM ${table} WHERE ${where}`).get(...params);
@@ -404,7 +404,7 @@ export function populateSqliteFromState(home, state, databaseFilename) {
404
404
  }
405
405
  // Capability grants and release workflows (task-15 record families).
406
406
  for (const grant of Object.values(stored.capabilityGrants)) {
407
- store.saveCapabilityGrant(taskId, grant);
407
+ store.migrationRestoreCapabilityGrant(taskId, grant);
408
408
  }
409
409
  for (const workflow of Object.values(stored.releaseWorkflows)) {
410
410
  store.saveReleaseWorkflow(taskId, workflow);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zq-silk/yui",
3
- "version": "0.12.1",
3
+ "version": "0.12.3",
4
4
  "description": "Local control plane for long-running native agent CLI sessions backed by tmux.",
5
5
  "license": "MIT",
6
6
  "private": false,