@finchip.ai/foga 0.6.0 → 0.6.1

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.
package/README.md CHANGED
@@ -86,6 +86,8 @@ With Node 22.13+ and Foundry's `anvil` installed, one command makes your wallet
86
86
  npx -y @finchip.ai/foga quickstart
87
87
  ```
88
88
 
89
+ `@finchtech.ai/foga` is the same package under a second scope (`alias/finchtech.ai`: a launcher that runs `@finchip.ai/foga` at the same version), so `npx -y @finchtech.ai/foga quickstart` is the same command.
90
+
89
91
  The wallet alone, for an agent that will only call cells (docs/wallet.md), and a cell on a public chain born with it:
90
92
 
91
93
  ```bash
@@ -111,6 +113,10 @@ npm run demo:genesis # anvil + world deploy + doctor + genesis T0-T9 + d
111
113
  # 2. World and genesis only (Node >= 22 and Foundry's anvil, no Solidity build; the ZK paths are left out without their material):
112
114
  npm ci && npm run demo:genesis
113
115
 
116
+ # 2b. The same show without a checkout, from the published package (Node >= 22.13 and anvil): a fresh chain, the 47 contracts,
117
+ # the genesis T0-T9 operation by operation, then the doctor's per-standard verdicts — about half a minute
118
+ npx -y @finchip.ai/foga demo --genesis T9 # add --keep to leave the chain running afterwards
119
+
114
120
  # 3. Containers (Docker with Compose):
115
121
  docker compose up --build # anvil + world + doctor + genesis; outputs land in ./deployments
116
122
  ```
@@ -1,5 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
- import { dirname, resolve } from "node:path";
2
+ import { existsSync, realpathSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
3
4
  import { repoRoot } from "../util/fs.js";
4
5
  import { buildSkillPackage, readSkillDir } from "../core/pack/skillpack.js";
5
6
  /**
@@ -26,6 +27,34 @@ function workerPath() {
26
27
  const ext = here.endsWith(".ts") ? ".ts" : ".js";
27
28
  return new URL(`./skill-worker${ext}`, here).pathname;
28
29
  }
30
+ /**
31
+ * The `node_modules` directories the worker's imports resolve through. In a checkout they are under the package root;
32
+ * in an npm or npx install the dependencies are hoisted beside the package (`<prefix>/node_modules/ethers` next to
33
+ * `<prefix>/node_modules/@finchip.ai/foga`), outside it, and a worker allowed to read the package root alone died on
34
+ * its first import (`ERR_ACCESS_DENIED` on `ethers/package.json`). Every ancestor's `node_modules` is granted, by its
35
+ * real path as well when a link is involved; the grant is read-only and the worker still never sees a key.
36
+ */
37
+ export function dependencyDirs(root = repoRoot()) {
38
+ const out = new Set();
39
+ let dir = resolve(root);
40
+ for (;;) {
41
+ const nm = join(dir, "node_modules");
42
+ if (existsSync(nm)) {
43
+ out.add(nm);
44
+ try {
45
+ out.add(realpathSync(nm));
46
+ }
47
+ catch {
48
+ /* a dangling link: the literal path is enough */
49
+ }
50
+ }
51
+ const parent = dirname(dir);
52
+ if (parent === dir)
53
+ break;
54
+ dir = parent;
55
+ }
56
+ return [...out];
57
+ }
29
58
  /** True under the development loader (tsx): Node's permission model cannot be combined with a custom loader. */
30
59
  function underLoader() {
31
60
  return process.execArgv.some((a) => /--import|--loader|--require|tsx/.test(a)) || /\.ts$/.test(workerPath());
@@ -43,7 +72,7 @@ export async function runIsolated(job, opts = {}) {
43
72
  const args = [...process.execArgv, "--max-old-space-size=512"];
44
73
  if (!underLoader() && opts.readDirs?.length) {
45
74
  args.push("--permission");
46
- for (const d of new Set([...opts.readDirs, dirname(workerPath())]))
75
+ for (const d of new Set([...opts.readDirs, dirname(workerPath()), ...dependencyDirs()]))
47
76
  args.push(`--allow-fs-read=${resolve(d)}`);
48
77
  }
49
78
  args.push(workerPath());
package/docs/loop-d.md CHANGED
@@ -109,7 +109,7 @@ A refusal can name an operation that exists already (a conflict, an execution re
109
109
 
110
110
  ## On a public chain: what the Sepolia run taught (0.6.0)
111
111
 
112
- The first Loop D with an outside agent on Sepolia (2026-11-04, world `sepolia-11155111-20261101T043153Z`, cell D agent 11264, the agent a person driving the HTTP entrance with the key) passed every invariant row — every operation under an allowed decision, eleven refusals across every gate with nothing broadcast, the budget books, all operator transactions at the account and allow-listed and none reverted, the recovery drill across the kill and restart, idempotency, conflict, concurrency — and cases a, c, d, d2 and e as expected. Four things about a public chain came out of it, and 0.6.0 carries the answers:
112
+ The first Loop D with an outside agent on Sepolia (2026-11-04, world `sepolia-11155111-20261101T043153Z`, cell D agent 11264, the agent a person driving the HTTP entrance with the key) passed every invariant row — every operation under an allowed decision, eleven refusals across every gate with nothing broadcast, the budget books, all operator transactions at the account and allow-listed and none reverted, the recovery drill across the kill and restart, idempotency, conflict, concurrency — and cases a, c, d, d2 and e as expected. The evidence is committed as `deployments/loop-d.sepolia.example.json` (`foga.loop-d-evidence/1`; the outside agent labelled `external-agent`; `foga doctor --loop-d` over it reads Pass 15, the case-b settlement figure as the one Fail — the accounting artifact fixed below, the chain having paid in full — and f, g and model-agnostic NotTested). Four things about a public chain came out of it, and 0.6.0 carries the answers:
113
113
 
114
114
  - **A working directory is one run.** `foga loop-d run` in a directory that holds a previous run's files found that run's keyed operations and replayed them against a cell with fresh keys, and the birth failed on the first replayed answer (`the registry assigned …; expected …`). The orchestrator now clears its own files from the working directory first (`cleanLoopDDir`, the run's files and nothing else; the evidence under `--out` is kept) — or pass `--dir` for a fresh one.
115
115
  - **Role funding is priced with a floor.** The roles' gas reserve was `units × gasPrice × 2`, and Sepolia quoted a gas price of a few wei: the operator got the flat 0.003 ETH alone, below the cell policy's gas floor (a quarter of `dailyGasWei`), so the budget gate refused every tender; the guardian got next to nothing for its suspend and resume. The reserve is now priced at the chain's gas price floored at 1 gwei (`src/demo/birth.ts`); a local chain, above the floor, is unchanged. A funder on Sepolia should hold about 0.15 ETH for a run.
package/docs/mcp.md CHANGED
@@ -103,7 +103,7 @@ Each runs `npx -y @finchip.ai/foga mcp --config <cell.config.json>` with, option
103
103
 
104
104
  ## The package
105
105
 
106
- The npm package is `@finchip.ai/foga` — npm refuses the unscoped name `foga` as too similar to `ora` and `koa`, so it lives under the `finchip.ai` scope; the binary is `foga` and `foga mcp` is the stdio server. `package.json` carries `mcpName: "io.github.garyyang-finchip/foga"`, the name the MCP registry verifies npm ownership by, and `server.json` at the repository root is the registry manifest: the npm package as a stdio server (`npx -y @finchip.ai/foga node mcp --config …`, `FOGA_OPERATOR_KEY_FILE` and `FOGA_RPC_URL` as its environment) and `https://foga.finchip.ai/mcp` as the remote; `foga cell docs build` writes a cell's own copy with its MCP URL as the remote (docs/documents.md). `engines.node` is `>=22.13`, where `node:sqlite` runs without a flag; CI runs Node 22. The package is published on npm by its owner (`npm publish --tag latest` from a checkout at the tagged version; `npm view @finchip.ai/foga version` shows what is live); publication to the registry (`mcp-publisher login github`, then `mcp-publisher publish` with the OG cell's `server.json`) was done in 3d-3, once the manifest's remote answered: the OG cell is listed as `io.github.garyyang-finchip/foga`, and a re-publish follows each change to the manifest (docs/og-deployment.md, "The MCP registry listing").
106
+ The npm package is `@finchip.ai/foga` — npm refuses the unscoped name `foga` as too similar to `ora` and `koa`, so it lives under the `finchip.ai` scope; the binary is `foga` and `foga mcp` is the stdio server. `package.json` carries `mcpName: "io.github.garyyang-finchip/foga"`, the name the MCP registry verifies npm ownership by, and `server.json` at the repository root is the registry manifest: the npm package as a stdio server (`npx -y @finchip.ai/foga node mcp --config …`, `FOGA_OPERATOR_KEY_FILE` and `FOGA_RPC_URL` as its environment) and `https://foga.finchip.ai/mcp` as the remote; `foga cell docs build` writes a cell's own copy with its MCP URL as the remote (docs/documents.md). `engines.node` is `>=22.13`, where `node:sqlite` runs without a flag; CI runs Node 22. The package is published on npm by its owner (`npm publish --tag latest` from a checkout at the tagged version; `npm view @finchip.ai/foga version` shows what is live), and `@finchtech.ai/foga` is republished beside it as an alias (`alias/finchtech.ai`: a launcher and a pinned dependency on `@finchip.ai/foga`, no code; `npm run alias:sync` after a version bump, then `npm publish --access public` from that folder), so either name runs the same program at the same version; publication to the registry (`mcp-publisher login github`, then `mcp-publisher publish` with the OG cell's `server.json`) was done in 3d-3, once the manifest's remote answered: the OG cell is listed as `io.github.garyyang-finchip/foga`, and a re-publish follows each change to the manifest (docs/og-deployment.md, "The MCP registry listing").
107
107
 
108
108
  What ships: `bin/`, `dist/`, `artifacts/bundle.json` (the ABIs), `worlds/`, `docs/` (the rule texts `spec_read` serves), `scenarios/` (the skill packages and the fixture), the prover bridge and the circuit's verification key, `server.json`. A checkout installed straight from git (`npm install github:garyyang-finchip/foga`, `npx -y github:garyyang-finchip/foga …`) compiles itself on install (`prepare`, `scripts/prepare.mjs`: only when `dist/` is missing and `src/` is there); `.gitattributes` keeps every text file LF on every platform, the launcher's shebang line included. `scripts/pack-smoke.mjs <rpc> <world.json>` is the pre-publication check and a CI step: `npm pack`, a clean `npm install` of the tarball in an empty directory, then the packaged CLI alone — `--help`, the public catalog, a schema, a cell born with `foga cell new` and `foga cell init` on the given world, and `foga node mcp` without a key driven by a raw 2025-era JSON-RPC client over stdio (stdout protocol-only, the keyless tool set, `cell_status`, `resources/list`, `spec_read` of the compatibility matrix from inside the package, no key-shaped value on stderr).
109
109
 
@@ -6,6 +6,8 @@ One command from nothing to a cell an MCP client can connect to. It needs Node 2
6
6
  npx -y @finchip.ai/foga quickstart
7
7
  ```
8
8
 
9
+ `npx -y @finchtech.ai/foga quickstart` is the same command: `@finchtech.ai/foga` is an alias package (`alias/finchtech.ai`) whose only content is a launcher for `@finchip.ai/foga` at the same version.
10
+
9
11
  Run it from any directory except a checkout of this repository itself: inside one, `npx` takes the checkout for the package already present (same name, same version) and looks for the `foga` command among its installed binaries, where a project's own binaries never are — `'foga' is not recognized` on Windows, `foga: not found` elsewhere. From a checkout the command is `node bin/foga.js quickstart` after `npm run build`.
10
12
 
11
13
  What it does, in order (about twenty-five seconds on a laptop): makes the default wallet — one key, the agent's identity, under `~/.foga/wallet` — when there is none, and reuses it when there is (docs/wallet.md: the wallet is the first step, and never a reason to stop; a disk that refuses the write gets keys made in memory for the run); starts `anvil` on port 8545; deploys the local world — the ten reference implementations and the FOGA contracts, 47 contracts (`worlds/local.json`); births a cell (`quick`) with the wallet's keys, funded by anvil's first account, which also registers the attested standing scheme and attests the cell's level-2 standing; mints the cell's two skills (`foga-probe`, `finch-extract-verify`) and offers them; builds the cell's documents and commits them on chain (the registration, the AID document, the ARD descriptor, the AUF unit; docs/documents.md); mints two tenders for the cell to find (a probe of the cell itself, an extraction over the fixture); serves the node — the watchers, the HTTP API, MCP over Streamable HTTP, A2A and the documents on `127.0.0.1:8787` — on the operator key alone, read from the wallet's file; checks that the entrances answer (health, a public read, the agent key's pre-check of the first tender, the MCP handshake and the 37-tool list over HTTP, the agent card naming `/a2a` and an A2A quote; the stdio server's handshake and its 44 tools with the operator key); and prints the summary below, with every path filled in. Then it waits: the chain lives as long as the process, and Ctrl-C ends both.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finchip.ai/foga",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/garyyang-finchip/foga.git"
@@ -70,7 +70,8 @@
70
70
  "test": "node --test --import tsx test/*.test.ts",
71
71
  "test:contracts": "cd contracts && forge test -vv",
72
72
  "zk:install": "npm --prefix prover ci",
73
- "zk:predicate": "node prover/build-predicate.mjs"
73
+ "zk:predicate": "node prover/build-predicate.mjs",
74
+ "alias:sync": "node scripts/alias-sync.mjs"
74
75
  },
75
76
  "dependencies": {
76
77
  "@modelcontextprotocol/server": "2.4.0",
package/server.json CHANGED
@@ -8,13 +8,13 @@
8
8
  "source": "github"
9
9
  },
10
10
  "websiteUrl": "https://foga.finchip.ai",
11
- "version": "0.6.0",
11
+ "version": "0.6.1",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "npm",
15
15
  "registryBaseUrl": "https://registry.npmjs.org",
16
16
  "identifier": "@finchip.ai/foga",
17
- "version": "0.6.0",
17
+ "version": "0.6.1",
18
18
  "runtimeHint": "npx",
19
19
  "transport": {
20
20
  "type": "stdio"