@finchip.ai/foga 0.0.0-stage → 0.6.0-alpha.4

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.
Files changed (131) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +216 -2
  4. package/artifacts/bundle.json +74250 -0
  5. package/artifacts/bundle.sha256 +1 -0
  6. package/bin/foga.js +14 -0
  7. package/build/known-interface-ids.json +18 -0
  8. package/build/profiles.json +120 -0
  9. package/dist/build/bundle.js +417 -0
  10. package/dist/build/vendor.js +74 -0
  11. package/dist/bundle/load.js +24 -0
  12. package/dist/bundle/types.js +1 -0
  13. package/dist/cli-cell.js +395 -0
  14. package/dist/cli.js +505 -0
  15. package/dist/core/acdf.js +162 -0
  16. package/dist/core/adrf.js +273 -0
  17. package/dist/core/aid.js +83 -0
  18. package/dist/core/ard.js +146 -0
  19. package/dist/core/asf.js +157 -0
  20. package/dist/core/canonical.js +79 -0
  21. package/dist/core/erc8004.js +52 -0
  22. package/dist/core/kya.js +225 -0
  23. package/dist/core/measure.js +96 -0
  24. package/dist/core/pack/cbor.js +130 -0
  25. package/dist/core/pack/skillpack.js +142 -0
  26. package/dist/core/skills.js +40 -0
  27. package/dist/core/swarm.js +206 -0
  28. package/dist/core/tenders.js +121 -0
  29. package/dist/core/units.js +122 -0
  30. package/dist/core/world.js +104 -0
  31. package/dist/demo/demander.js +76 -0
  32. package/dist/demo/evidence.js +1 -0
  33. package/dist/demo/loop-d.js +449 -0
  34. package/dist/doctor/checks.js +51 -0
  35. package/dist/doctor/doctor.js +385 -0
  36. package/dist/doctor/loop-d.js +103 -0
  37. package/dist/doctor/probe.js +97 -0
  38. package/dist/doctor/semantic.js +83 -0
  39. package/dist/genesis/extract.js +64 -0
  40. package/dist/genesis/funding.js +126 -0
  41. package/dist/genesis/operator-scope.js +90 -0
  42. package/dist/genesis/preflight.js +54 -0
  43. package/dist/genesis/probe.js +164 -0
  44. package/dist/genesis/roles.js +96 -0
  45. package/dist/genesis/run.js +71 -0
  46. package/dist/genesis/scenario.js +765 -0
  47. package/dist/genesis/skill-runner.js +103 -0
  48. package/dist/genesis/skill-worker.js +41 -0
  49. package/dist/genesis/t1-zk.js +62 -0
  50. package/dist/genesis/t3-zk.js +105 -0
  51. package/dist/genesis/t4.js +259 -0
  52. package/dist/genesis/t5.js +168 -0
  53. package/dist/genesis/t6.js +222 -0
  54. package/dist/genesis/t7.js +198 -0
  55. package/dist/genesis/t8.js +189 -0
  56. package/dist/genesis/t9.js +188 -0
  57. package/dist/genesis/zk.js +128 -0
  58. package/dist/http/server.js +276 -0
  59. package/dist/kernel/cell.js +104 -0
  60. package/dist/kernel/errors.js +78 -0
  61. package/dist/kernel/kernel.js +251 -0
  62. package/dist/kernel/provider.js +125 -0
  63. package/dist/kernel/store.js +470 -0
  64. package/dist/kernel/tx.js +385 -0
  65. package/dist/mcp/server.js +170 -0
  66. package/dist/node/config.js +195 -0
  67. package/dist/node/init.js +200 -0
  68. package/dist/node/keys.js +95 -0
  69. package/dist/node/migrate.js +173 -0
  70. package/dist/node/model/anthropic.js +97 -0
  71. package/dist/node/model/stub.js +129 -0
  72. package/dist/node/model/types.js +9 -0
  73. package/dist/node/node.js +198 -0
  74. package/dist/node/policy.js +95 -0
  75. package/dist/node/runner.js +256 -0
  76. package/dist/node/watchers.js +88 -0
  77. package/dist/tools/admin.js +184 -0
  78. package/dist/tools/catalog.js +261 -0
  79. package/dist/tools/common.js +143 -0
  80. package/dist/tools/identity.js +107 -0
  81. package/dist/tools/index.js +14 -0
  82. package/dist/tools/read.js +471 -0
  83. package/dist/tools/tenders.js +400 -0
  84. package/dist/tools/types.js +4 -0
  85. package/dist/util/bytecode.js +123 -0
  86. package/dist/util/fs.js +58 -0
  87. package/dist/util/hash.js +4 -0
  88. package/dist/util/log.js +11 -0
  89. package/dist/util/version.js +12 -0
  90. package/dist/world/deploy.js +277 -0
  91. package/dist/world/plan.js +93 -0
  92. package/dist/world/types.js +1 -0
  93. package/docs/build.md +45 -0
  94. package/docs/cell-account.md +58 -0
  95. package/docs/compatibility-matrix.md +38 -0
  96. package/docs/design-memo.md +113 -0
  97. package/docs/doctor.md +53 -0
  98. package/docs/examples/README.md +11 -0
  99. package/docs/examples/claude-code-mcp.json +13 -0
  100. package/docs/examples/claude_desktop_config.json +12 -0
  101. package/docs/examples/cursor-mcp.json +11 -0
  102. package/docs/genesis.md +312 -0
  103. package/docs/kernel.md +101 -0
  104. package/docs/loop-d.md +90 -0
  105. package/docs/mcp.md +105 -0
  106. package/docs/node.md +66 -0
  107. package/docs/version-lock.md +67 -0
  108. package/docs/world.md +50 -0
  109. package/docs/zk.md +48 -0
  110. package/package.json +82 -4
  111. package/prover/README.md +26 -0
  112. package/prover/build-predicate.mjs +77 -0
  113. package/prover/package-lock.json +1837 -0
  114. package/prover/package.json +15 -0
  115. package/prover/run.cjs +199 -0
  116. package/scenarios/fixtures/sample-filing.txt +16 -0
  117. package/scenarios/skills/finch-extract-verify/LICENSE +2 -0
  118. package/scenarios/skills/finch-extract-verify/SKILL.md +34 -0
  119. package/scenarios/skills/finch-extract-verify/fields.json +56 -0
  120. package/scenarios/skills/finch-extract-verify/manifest.json +16 -0
  121. package/scenarios/skills/foga-probe/LICENSE +2 -0
  122. package/scenarios/skills/foga-probe/SKILL.md +35 -0
  123. package/scenarios/skills/foga-probe/manifest.json +16 -0
  124. package/scenarios/skills/foga-probe/probe.schema.json +40 -0
  125. package/server.json +79 -0
  126. package/vendor/LOCK.json +107 -0
  127. package/vendor/README.md +13 -0
  128. package/worlds/local.json +34 -0
  129. package/worlds/sepolia.json +314 -0
  130. package/zk/build/verification_key.json +174 -0
  131. package/zk/circuits/kya_predicate_count_v1.circom +231 -0
@@ -0,0 +1,231 @@
1
+ pragma circom 2.1.6;
2
+
3
+ // FOGA predicate-pattern ZK-KYA circuit, revision 1: `kya-predicate-count-v1`.
4
+ //
5
+ // Statement proved (the SUBJECT is public; the records and their source are not):
6
+ // "Among at most N task-completion records signed by one source whose key is a member of the source set
7
+ // committed to by `sourceSetRoot`, at least K concern `subjectKey`, carry status Accepted (1) and a
8
+ // timestamp inside [t0, t1]; the records are distinct. result = 1 when the count reaches K. My nullifier
9
+ // for (schemeId, admissionDomain, epoch, challenge) is Poseidon(secret, schemeId, admissionDomain, epoch,
10
+ // challenge)."
11
+ //
12
+ // This is the predicate pattern of ZK-KYA (ERC-8419 section 5): the scheme is the decision rule, and the
13
+ // prover evaluates it over data authenticated by its source. The chain learns the subject, the rule's
14
+ // parameters (window, K, source set) and the result bit; never which records, how many, or their content.
15
+ // It proves a fact about a range of records, not that the agent is trustworthy.
16
+ //
17
+ // Conventions shared with the upstream `kya_public_v1` circuit: 256-bit values travel as (hi128, lo128);
18
+ // `schemeId` and `admissionDomain` are fed by the on-chain adapter from its own arguments, never chosen by
19
+ // the prover; `epoch` is enforced by the adapter against block time within a grace window.
20
+ //
21
+ // Public signals (snarkjs order: outputs first, then public inputs in declaration order):
22
+ // [0] nullifierHi (output) [1] nullifierLo (output) [2] result (output)
23
+ // [3] subjectKeyHi [4] subjectKeyLo [5] challengeHi [6] challengeLo
24
+ // [7] t0 [8] t1 [9] k [10] sourceSetRootHi [11] sourceSetRootLo
25
+ // [12] schemeIdHi [13] schemeIdLo [14] epoch [15] admissionDomainHi [16] admissionDomainLo
26
+ //
27
+ // The committed build instantiates N = 8 record slots and a source set of depth 16 (about 87k constraints,
28
+ // powers of tau 2^17); N and the depth are template parameters.
29
+ //
30
+ // A record is (subjectKeyHi, subjectKeyLo, taskRef, status, timestamp) with taskRef a 128-bit identifier of
31
+ // the completion (the source's own hash of chain, task contract, token and submission); the source signs
32
+ // Poseidon(5) of those fields with EdDSA over Baby Jubjub. Slots are filled from index 0 without gaps;
33
+ // present records carry strictly increasing taskRefs, so no record counts twice.
34
+
35
+ include "circomlib/circuits/poseidon.circom";
36
+ include "circomlib/circuits/eddsaposeidon.circom";
37
+ include "circomlib/circuits/bitify.circom";
38
+ include "circomlib/circuits/comparators.circom";
39
+ include "circomlib/circuits/mux1.circom";
40
+
41
+ template Split128() {
42
+ signal input in;
43
+ signal output hi;
44
+ signal output lo;
45
+ component n2b = Num2Bits_strict();
46
+ n2b.in <== in;
47
+ component loB = Bits2Num(128);
48
+ component hiB = Bits2Num(126);
49
+ for (var i = 0; i < 128; i++) loB.in[i] <== n2b.out[i];
50
+ for (var i = 0; i < 126; i++) hiB.in[i] <== n2b.out[128 + i];
51
+ hi <== hiB.out;
52
+ lo <== loB.out;
53
+ }
54
+
55
+ template MerkleInclusion(levels) {
56
+ signal input leaf;
57
+ signal input pathElements[levels];
58
+ signal input pathIndices[levels];
59
+ signal output root;
60
+
61
+ component hashers[levels];
62
+ component mux[levels];
63
+ signal cur[levels + 1];
64
+ cur[0] <== leaf;
65
+ for (var i = 0; i < levels; i++) {
66
+ pathIndices[i] * (1 - pathIndices[i]) === 0;
67
+ mux[i] = MultiMux1(2);
68
+ mux[i].c[0][0] <== cur[i];
69
+ mux[i].c[0][1] <== pathElements[i];
70
+ mux[i].c[1][0] <== pathElements[i];
71
+ mux[i].c[1][1] <== cur[i];
72
+ mux[i].s <== pathIndices[i];
73
+ hashers[i] = Poseidon(2);
74
+ hashers[i].inputs[0] <== mux[i].out[0];
75
+ hashers[i].inputs[1] <== mux[i].out[1];
76
+ cur[i + 1] <== hashers[i].out;
77
+ }
78
+ root <== cur[levels];
79
+ }
80
+
81
+ template KYAPredicateCountV1(n, depth) {
82
+ // ---- public inputs ----
83
+ signal input subjectKeyHi;
84
+ signal input subjectKeyLo;
85
+ signal input challengeHi;
86
+ signal input challengeLo;
87
+ signal input t0;
88
+ signal input t1;
89
+ signal input k;
90
+ signal input sourceSetRootHi;
91
+ signal input sourceSetRootLo;
92
+ signal input schemeIdHi;
93
+ signal input schemeIdLo;
94
+ signal input epoch;
95
+ signal input admissionDomainHi;
96
+ signal input admissionDomainLo;
97
+
98
+ // ---- private inputs ----
99
+ signal input secret;
100
+ signal input Ax; // the source's EdDSA (Baby Jubjub) public key
101
+ signal input Ay;
102
+ signal input pathElements[depth]; // the source's membership in the source set
103
+ signal input pathIndices[depth];
104
+ signal input present[n]; // 1 for a filled slot, 0 for an empty one; filled slots first
105
+ signal input taskRef[n]; // 128-bit record identifiers, strictly increasing over filled slots
106
+ signal input status[n]; // 1 = Accepted
107
+ signal input timestamp[n]; // seconds, 64-bit
108
+ signal input S[n]; // the source's signature over each record
109
+ signal input R8x[n];
110
+ signal input R8y[n];
111
+
112
+ // ---- outputs ----
113
+ signal output nullifierHi;
114
+ signal output nullifierLo;
115
+ signal output result;
116
+
117
+ // range sanity on public fields
118
+ component skh = Num2Bits(128); skh.in <== subjectKeyHi;
119
+ component skl = Num2Bits(128); skl.in <== subjectKeyLo;
120
+ component chh = Num2Bits(128); chh.in <== challengeHi;
121
+ component chl = Num2Bits(128); chl.in <== challengeLo;
122
+ component sih = Num2Bits(128); sih.in <== schemeIdHi;
123
+ component sil = Num2Bits(128); sil.in <== schemeIdLo;
124
+ component adh = Num2Bits(128); adh.in <== admissionDomainHi;
125
+ component adl = Num2Bits(128); adl.in <== admissionDomainLo;
126
+ component t0b = Num2Bits(64); t0b.in <== t0;
127
+ component t1b = Num2Bits(64); t1b.in <== t1;
128
+ component kb = Num2Bits(16); kb.in <== k;
129
+ component epb = Num2Bits(64); epb.in <== epoch;
130
+
131
+ // the source is a member of the source set
132
+ component leaf = Poseidon(2);
133
+ leaf.inputs[0] <== Ax;
134
+ leaf.inputs[1] <== Ay;
135
+ component inc = MerkleInclusion(depth);
136
+ inc.leaf <== leaf.out;
137
+ for (var i = 0; i < depth; i++) {
138
+ inc.pathElements[i] <== pathElements[i];
139
+ inc.pathIndices[i] <== pathIndices[i];
140
+ }
141
+ component rootSplit = Split128();
142
+ rootSplit.in <== inc.root;
143
+ rootSplit.hi === sourceSetRootHi;
144
+ rootSplit.lo === sourceSetRootLo;
145
+
146
+ // the records: signed by the source, about the subject, counted when Accepted inside the window
147
+ component msg[n];
148
+ component sig[n];
149
+ component refBits[n];
150
+ component tsBits[n];
151
+ component geT0[n];
152
+ component leT1[n];
153
+ component isAccepted[n];
154
+ component increasing[n];
155
+ signal counted[n];
156
+ signal inWindow[n];
157
+ signal acceptedPresent[n];
158
+ signal acc[n + 1];
159
+ acc[0] <== 0;
160
+
161
+ for (var i = 0; i < n; i++) {
162
+ present[i] * (1 - present[i]) === 0;
163
+ if (i > 0) {
164
+ // filled slots come first: present[i] <= present[i-1]
165
+ present[i] * (1 - present[i - 1]) === 0;
166
+ }
167
+ refBits[i] = Num2Bits(128); refBits[i].in <== taskRef[i];
168
+ tsBits[i] = Num2Bits(64); tsBits[i].in <== timestamp[i];
169
+
170
+ msg[i] = Poseidon(5);
171
+ msg[i].inputs[0] <== subjectKeyHi;
172
+ msg[i].inputs[1] <== subjectKeyLo;
173
+ msg[i].inputs[2] <== taskRef[i];
174
+ msg[i].inputs[3] <== status[i];
175
+ msg[i].inputs[4] <== timestamp[i];
176
+
177
+ sig[i] = EdDSAPoseidonVerifier();
178
+ sig[i].enabled <== present[i];
179
+ sig[i].Ax <== Ax;
180
+ sig[i].Ay <== Ay;
181
+ sig[i].S <== S[i];
182
+ sig[i].R8x <== R8x[i];
183
+ sig[i].R8y <== R8y[i];
184
+ sig[i].M <== msg[i].out;
185
+
186
+ // distinct records: strictly increasing taskRef over the filled prefix
187
+ if (i > 0) {
188
+ increasing[i] = LessThan(128);
189
+ increasing[i].in[0] <== taskRef[i - 1];
190
+ increasing[i].in[1] <== taskRef[i];
191
+ present[i] * (1 - increasing[i].out) === 0;
192
+ }
193
+
194
+ isAccepted[i] = IsEqual();
195
+ isAccepted[i].in[0] <== status[i];
196
+ isAccepted[i].in[1] <== 1;
197
+ geT0[i] = LessEqThan(64);
198
+ geT0[i].in[0] <== t0;
199
+ geT0[i].in[1] <== timestamp[i];
200
+ leT1[i] = LessEqThan(64);
201
+ leT1[i].in[0] <== timestamp[i];
202
+ leT1[i].in[1] <== t1;
203
+ inWindow[i] <== geT0[i].out * leT1[i].out;
204
+ acceptedPresent[i] <== present[i] * isAccepted[i].out;
205
+ counted[i] <== acceptedPresent[i] * inWindow[i];
206
+ acc[i + 1] <== acc[i] + counted[i];
207
+ }
208
+
209
+ // result = (count >= k)
210
+ component reach = GreaterEqThan(16);
211
+ reach.in[0] <== acc[n];
212
+ reach.in[1] <== k;
213
+ result <== reach.out;
214
+
215
+ // nullifier scoped to (schemeId, admissionDomain, epoch, challenge)
216
+ component nul = Poseidon(8);
217
+ nul.inputs[0] <== secret;
218
+ nul.inputs[1] <== schemeIdHi;
219
+ nul.inputs[2] <== schemeIdLo;
220
+ nul.inputs[3] <== admissionDomainHi;
221
+ nul.inputs[4] <== admissionDomainLo;
222
+ nul.inputs[5] <== epoch;
223
+ nul.inputs[6] <== challengeHi;
224
+ nul.inputs[7] <== challengeLo;
225
+ component nulSplit = Split128();
226
+ nulSplit.in <== nul.out;
227
+ nullifierHi <== nulSplit.hi;
228
+ nullifierLo <== nulSplit.lo;
229
+ }
230
+
231
+ component main { public [subjectKeyHi, subjectKeyLo, challengeHi, challengeLo, t0, t1, k, sourceSetRootHi, sourceSetRootLo, schemeIdHi, schemeIdLo, epoch, admissionDomainHi, admissionDomainLo] } = KYAPredicateCountV1(8, 16);