File size: 4,623 Bytes
518343a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Two-level commit — NSA's coarse/fine pair, re-expressed against
// Lutar-Lambda Λ-floor gating. The coarse step (`scoreIndex`) makes a
// `sparse.index.score.v1` claim naming eligible blocks; the fine step
// (`executeSparse`) refuses to run without a valid, fresh parent claim
// and emits `sparse.execute.v1`. The top-k commit between them is a
// budget primitive — exhausting it without escalating is a fail-closed
// event (`sparse.budget.exhausted.v1`).

import type { SparseReceiptCommon } from "./receipts.js";

export interface SparseIndexScoreReceipt extends SparseReceiptCommon {
  readonly receiptClass: "sparse.index.score.v1";
  readonly regimeRef: string;
  readonly eligibleBlocks: ReadonlyArray<{ blockId: number; score: number }>;
}

export interface SparseTopKCommitReceipt extends SparseReceiptCommon {
  readonly receiptClass: "sparse.topk.commit.v1";
  readonly regimeRef: string;
  readonly indexReceiptRef: string;
  readonly committedBlocks: ReadonlyArray<number>;
  readonly budgetK: number;
}

export interface SparseExecuteReceipt extends SparseReceiptCommon {
  readonly receiptClass: "sparse.execute.v1";
  readonly regimeRef: string;
  readonly commitReceiptRef: string;
  readonly attendedBlocks: ReadonlyArray<number>;
}

export interface SparseBudgetExhaustedReceipt extends SparseReceiptCommon {
  readonly receiptClass: "sparse.budget.exhausted.v1";
  readonly regimeRef: string;
  readonly requested: number;
  readonly available: number;
}

export interface ScoreIndexInput {
  readonly regimeRef: string;
  readonly tenant: string;
  readonly nonce: string;
  readonly candidates: ReadonlyArray<{ blockId: number; score: number }>;
  readonly issuedAt?: string;
}

export function scoreIndex(input: ScoreIndexInput): SparseIndexScoreReceipt {
  const issuedAt = input.issuedAt ?? new Date().toISOString();
  return {
    receiptClass: "sparse.index.score.v1",
    freshnessNonce: input.nonce,
    issuedAt,
    tenant: input.tenant,
    parentRef: input.regimeRef,
    regimeRef: input.regimeRef,
    eligibleBlocks: [...input.candidates].sort((a, b) => b.score - a.score),
  };
}

export interface TopKCommitInput {
  readonly regimeRef: string;
  readonly indexReceipt: SparseIndexScoreReceipt;
  readonly budgetK: number;
  readonly tenant: string;
  readonly nonce: string;
  readonly issuedAt?: string;
}

export type TopKCommitOutput =
  | { ok: true; receipt: SparseTopKCommitReceipt }
  | { ok: false; receipt: SparseBudgetExhaustedReceipt };

export function topKCommit(input: TopKCommitInput): TopKCommitOutput {
  const issuedAt = input.issuedAt ?? new Date().toISOString();
  if (input.budgetK <= 0) {
    return {
      ok: false,
      receipt: {
        receiptClass: "sparse.budget.exhausted.v1",
        freshnessNonce: input.nonce,
        issuedAt,
        tenant: input.tenant,
        parentRef: input.regimeRef,
        regimeRef: input.regimeRef,
        requested: input.budgetK,
        available: 0,
      },
    };
  }
  const top = input.indexReceipt.eligibleBlocks.slice(0, input.budgetK).map((b) => b.blockId);
  if (top.length < input.budgetK) {
    return {
      ok: false,
      receipt: {
        receiptClass: "sparse.budget.exhausted.v1",
        freshnessNonce: input.nonce,
        issuedAt,
        tenant: input.tenant,
        parentRef: input.regimeRef,
        regimeRef: input.regimeRef,
        requested: input.budgetK,
        available: top.length,
      },
    };
  }
  return {
    ok: true,
    receipt: {
      receiptClass: "sparse.topk.commit.v1",
      freshnessNonce: input.nonce,
      issuedAt,
      tenant: input.tenant,
      parentRef: input.regimeRef,
      regimeRef: input.regimeRef,
      indexReceiptRef: `${input.indexReceipt.regimeRef}:${input.indexReceipt.freshnessNonce}`,
      committedBlocks: top,
      budgetK: input.budgetK,
    },
  };
}

export interface ExecuteSparseInput {
  readonly regimeRef: string;
  readonly commitReceipt: SparseTopKCommitReceipt;
  readonly attendedBlocks: ReadonlyArray<number>;
  readonly tenant: string;
  readonly nonce: string;
  readonly issuedAt?: string;
}

export function executeSparse(input: ExecuteSparseInput): SparseExecuteReceipt {
  const issuedAt = input.issuedAt ?? new Date().toISOString();
  return {
    receiptClass: "sparse.execute.v1",
    freshnessNonce: input.nonce,
    issuedAt,
    tenant: input.tenant,
    parentRef: input.regimeRef,
    regimeRef: input.regimeRef,
    commitReceiptRef: `${input.commitReceipt.regimeRef}:${input.commitReceipt.freshnessNonce}`,
    attendedBlocks: [...input.attendedBlocks].sort((a, b) => a - b),
  };
}