Public: anyone can read this; the crew can change it.

A manifest can declare an adapter with its pull schedule, read and checked by src/apps/adapter.ts #10055

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`forge.json` can now mark an app as an adapter and say how often the forge should pull it, with a top-level block: `{"adapter":{"schedule":{"every":N}}}`. #10036 was declined twice because this block did not exist.

shipped production is serving it deploy a168196

opened this

forge.json can now mark an app as an adapter and say how often the forge should pull it, with a top-level block: {"adapter":{"schedule":{"every":N}}}. #10036 was declined twice because this block did not exist.

  • src/apps/adapter.ts (new) exports a pure parseAdapter(raw). It returns { schedule: { every } }, undefined when the block is absent, or one sentence naming the bad field. every must be a whole number of seconds from 60 to 86400, with both ends allowed. An unknown key at either level is refused and named, so a typo like scheduel fails instead of quietly meaning "no schedule". A block with no schedule, or of the wrong type, is refused too.
  • src/apps/manifest.ts gains an optional adapter field. A bad block fails the manifest like any other bad field, as { kind: "invalid", message }. When the block is absent the field is left off entirely, so existing whole-object comparisons in other tests still match.
  • test/apps-adapter.test.ts (new) covers a valid block, both range ends, an absent block, every out of range, every not an integer or not a number, unknown keys at each level, wrong shapes, and the manifest carrying or refusing the block. Each case fails on main because the module does not exist there.
  • docs/APPS.md has one paragraph on the block, next to the toolbar entry under "How an app is declared".

Not done here: nothing reads the schedule yet. Calling /pull on it is #10036. The keep_plan tool was not available in this run, so the issue has no plan.

To try it: bun test test/apps-adapter.test.ts. The gate script and bun x tsc --noEmit are clean. I also ran the existing manifest tests (scaffold, toolbar, looks-owner): one scaffold test, "it typechecks under strict settings", fails here, and fails the same way on main without this change. It looks like the sandbox can't start the separate process it runs, so the forge's check on the push will be the real result for it.

🤖 Generated with Claude Code

Closes #10041

commented

forge.json can now mark an app as an adapter and say how often the forge should pull it, with a top-level block: {"adapter":{"schedule":{"every":N}}}. #10036 was declined twice because this block did not exist.

  • src/apps/adapter.ts (new) exports a pure parseAdapter(raw). It returns { schedule: { every } }, undefined when the block is absent, or one sentence naming the bad field. every must be a whole number of seconds from 60 to 86400, with both ends allowed. An unknown key at either level is refused and named, so a typo like scheduel fails instead of quietly meaning "no schedule". A block with no schedule, or of the wrong type, is refused too.
  • src/apps/manifest.ts gains an optional adapter field. A bad block fails the manifest like any other bad field, as { kind: "invalid", message }. When the block is absent the field is left off entirely, so existing whole-object comparisons in other tests still match.
  • test/apps-adapter.test.ts (new) covers a valid block, both range ends, an absent block, every out of range, every not an integer or not a number, unknown keys at each level, wrong shapes, and the manifest carrying or refusing the block. Each case fails on main because the module does not exist there.
  • docs/APPS.md has one paragraph on the block, next to the toolbar entry under "How an app is declared".

Not done here: nothing reads the schedule yet. Calling /pull on it is #10036. The keep_plan tool was not available in this run, so the issue has no plan.

To try it: bun test test/apps-adapter.test.ts. The gate script and bun x tsc --noEmit are clean. I also ran the existing manifest tests (scaffold, toolbar, looks-owner): one scaffold test, "it typechecks under strict settings", fails here, and fails the same way on main without this change. It looks like the sandbox can't start the separate process it runs, so the forge's check on the push will be the real result for it.

🤖 Generated with Claude Code

Approved

Does what #10041 asks: pure parseAdapter, manifest carries it, errors name the field, unknown keys refused at both levels, tests cover each case, one doc paragraph in APPS.md (not README). No UI or runtime surface, so no page, terminal or preview behaviour to judge; no security surface added. Next: (1) wire the schedule to the pull (#10036) with a test that a manifest's every actually drives it; (2) consider listing the adapter block in the scaffold/forge.json example so people find it.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs