@hobocode/thought-layer 0.5.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.
@@ -214,20 +214,24 @@ export default function (pi: ExtensionAPI) {
214
214
  name: "deploy",
215
215
  label: "Thought Layer: deploy",
216
216
  description:
217
- "Take the built site live to a user-owned URL. Reads build.json (publishDir/entry) next to the state file, then deploys to Netlify. " +
217
+ "Take the built site live to a user-owned URL. Reads build.json (publishDir/entry, and the backend block when present) next to the state file, then deploys to Netlify. " +
218
218
  "Two models, both BYOK with no lock-in: with NETLIFY_AUTH_TOKEN set (read from the environment only, never a parameter) it deploys into the user's OWN account via the file-digest API (no zip); with no token it uses the Netlify CLI's --allow-anonymous flow for an instant live URL plus a one-hour claim link. " +
219
- "Run the build first (thought-layer-build / tl_scaffold). Use dryRun:true to preview the file plan with no network call. Static-first: if build.json has hasBackend:true it warns that only the front end ships this way.",
219
+ "When build.json declares a backend it ships automatically: the functions go up via the user's Netlify CLI and the declared env var names are set on the site (values read only from the environment, BYOK). DATABASE_URL is bring-your-own by default; provisionDb and applySchema are opt in. staticOnly ships just the front end. " +
220
+ "Run the build first (thought-layer-build / tl_scaffold). Use dryRun:true to preview the file and backend plan with no network call.",
220
221
  parameters: Type.Object({
221
222
  path: Type.Optional(Type.String({ description: "State file (or project dir) whose build.json to deploy. Defaults to ./.thought-layer/state.json; honors a named file." })),
222
- dryRun: Type.Optional(Type.Boolean({ description: "Plan only: walk the publish dir and report the files + target, with no network call or CLI spawn." })),
223
+ dryRun: Type.Optional(Type.Boolean({ description: "Plan only: walk the publish dir and report the files, target, and backend plan, with no network call or CLI spawn." })),
223
224
  anonymous: Type.Optional(Type.Boolean({ description: "Force the no-account path (Netlify CLI --allow-anonymous) even if a token is set. Default: token path when NETLIFY_AUTH_TOKEN is set, else anonymous." })),
224
- siteName: Type.Optional(Type.String({ description: "Token path only: create the site under this name (a-z0-9-). Omit to let Netlify assign a random subdomain." })),
225
- siteId: Type.Optional(Type.String({ description: "Token path only: re-deploy to an existing site id instead of creating a new one." })),
225
+ siteName: Type.Optional(Type.String({ description: "Create the site under this name (a-z0-9-). Omit to let Netlify assign a random subdomain." })),
226
+ siteId: Type.Optional(Type.String({ description: "Re-deploy to an existing site id instead of creating a new one." })),
227
+ staticOnly: Type.Optional(Type.Boolean({ description: "Ship only the front end even when build.json declares a backend." })),
228
+ provisionDb: Type.Optional(Type.Boolean({ description: "Opt in: provision Neon with the user's own NEON_API_KEY (read from the environment). Default off, which uses a bring-your-own DATABASE_URL." })),
229
+ applySchema: Type.Optional(Type.Boolean({ description: "Opt in: apply schema.sql with psql once the database is reachable. Default off." })),
226
230
  }),
227
231
  async execute(_id, params): Promise<ToolResult> {
228
- const p = params as { path?: string; dryRun?: boolean; anonymous?: boolean; siteName?: string; siteId?: string };
232
+ const p = params as { path?: string; dryRun?: boolean; anonymous?: boolean; siteName?: string; siteId?: string; staticOnly?: boolean; provisionDb?: boolean; applySchema?: boolean };
229
233
  const r = await runDeploy(
230
- { path: p.path, dryRun: p.dryRun, anonymous: p.anonymous, siteName: p.siteName, siteId: p.siteId },
234
+ { path: p.path, dryRun: p.dryRun, anonymous: p.anonymous, siteName: p.siteName, siteId: p.siteId, staticOnly: p.staticOnly, provisionDb: p.provisionDb, applySchema: p.applySchema },
231
235
  { deployedAt: new Date().toISOString() },
232
236
  );
233
237
  return text(r.message, r.details);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hobocode/thought-layer",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "The Thought Layer: rigor for building. Validate an idea, grill it into a buildable spec, then build and deploy it, inside the agent you already use. BYOK, no telemetry.",
5
5
  "license": "MIT",
6
6
  "author": "Hobocode LLC <jerm@hobocode.net>",
@@ -65,6 +65,7 @@
65
65
  "core/state-file.ts",
66
66
  "core/state-ops.ts",
67
67
  "core/backend.ts",
68
+ "core/backend-io.ts",
68
69
  "core/scaffold.ts",
69
70
  "core/scaffold-io.ts",
70
71
  "core/deploy.ts",
@@ -2,6 +2,6 @@ Apply the **thought-layer-deploy** skill. Take the built site live to a URL I ow
2
2
 
3
3
  Read `.thought-layer/build.json` (next to the state file; honor `--path` / `THOUGHT_LAYER_STATE` if a named file is in use) for the publish directory and entry. If there is no `build.json`, say so and point me to `/tl-build` (or the `tl_scaffold` tool) rather than guessing - the build has to run first.
4
4
 
5
- Default to a dry run first so I can see exactly which files would ship and where. Then deploy: if `NETLIFY_AUTH_TOKEN` is set, deploy into my own Netlify account (owned immediately); otherwise delegate to my Netlify CLI - logged in it creates a site in my account, logged out it deploys anonymously with a one-hour claim link. Read the token only from the environment, never ask me to paste it. If `build.json` says `hasBackend: true`, tell me plainly that this static deploy ships only the front end for now (backend deploy automation is a follow-up), and point me at `BACKEND.md` for the one-time steps to run the backend (provision Neon, set `DATABASE_URL`, then `netlify deploy` with the functions present).
5
+ Default to a dry run first so I can see exactly which files would ship and where. Then deploy: if `NETLIFY_AUTH_TOKEN` is set, deploy into my own Netlify account (owned immediately); otherwise delegate to my Netlify CLI - logged in it creates a site in my account, logged out it deploys anonymously with a one-hour claim link. Read the token only from the environment, never ask me to paste it. If `build.json` declares a backend, ship it automatically alongside the front end: the functions go up via my Netlify CLI and the declared env var names are set on the site (read the values from my environment, BYOK; tell me by name any that are missing). `DATABASE_URL` is bring-your-own by default; only provision Neon (`--provision-db`) or apply `schema.sql` (`--apply-schema`) if I ask. Use `--static-only` if I want just the front end. Tell me plainly which functions shipped and which env names were set versus missing, and never claim a backend is running when only the front end went live.
6
6
 
7
7
  After it is live, tell me the URL and (anonymous only) the claim link, and that a `.thought-layer/deploy.json` record was written.
@@ -57,9 +57,9 @@ If all three are no, build **static, full stop.** localStorage, static data file
57
57
  - **A names-only `.env.example`** at the project root listing every variable the backend reads (`DATABASE_URL` plus any others), each as a bare `NAME=` under a one-line comment. Never write a real value; real values live only in the host environment.
58
58
  - **An updated `netlify.toml`.** Extend the existing publish + redirect block (do not replace it) with a `[functions]` table declaring `directory = "netlify/functions"`. Keep the static publish dir and the SPA redirect intact.
59
59
  - **A `BACKEND.md` deploy guide** at the project root: what is in the repo, the honest status (automated backend deploy is a follow-up, so `tl deploy` ships only the front end today), how to provision Neon, the env-var table, the function-to-R-ID table, and the manual `netlify deploy` steps. The kit's `renderBackendGuide` and `renderEnvExample` helpers (in `core/backend.ts`) produce a dash-free skeleton if you have the core available; otherwise write the same content by hand.
60
- - **A project `.gitignore`** that ignores `.env` and `.env.*` but un-ignores the contract with `!.env.example`. Without that line the env contract is silently un-committable, and the deploy follow-up cannot read it.
60
+ - **A project `.gitignore`** that ignores `.env` and `.env.*` but un-ignores the contract with `!.env.example`. Without that line the env contract is silently un-committable, and the deploy step cannot read it.
61
61
 
62
- Then record the backend in the manifest's `backend` block (shape below). Do **not** attempt to deploy the backend in this step: `tl deploy` publishes the static front end, and backend deploy automation is the explicit follow-up. Say so plainly in chat and point the user at `BACKEND.md`.
62
+ Then record the backend in the manifest's `backend` block (shape below). Do **not** attempt to deploy in this step. The deploy is the next step: `tl deploy` (or the **thought-layer-deploy** skill) reads this `backend` block and ships the functions plus the declared env var names via the user's Netlify CLI into their own account, with `DATABASE_URL` bring-your-own by default. Point the user at `BACKEND.md` for the details and the opt-in database steps.
63
63
 
64
64
  ## SEO and discoverability (build all of it, do not skip it)
65
65
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: thought-layer-deploy
3
- description: "Take the built site live to a user-owned URL with no lock-in, the last step after the build. Reads .thought-layer/build.json (the publish dir + entry) next to the state file, then deploys to Netlify by one of two BYOK models: with NETLIFY_AUTH_TOKEN set it deploys into the user's OWN account via the file-digest API (owned immediately, no claim), and with no token it delegates to the user's Netlify CLI (logged in: a new site in their account; logged out: an anonymous, claimable URL with a one-hour claim link). Static-first: if build.json says hasBackend, the build also emitted a backend (functions, schema.sql, a names-only .env.example, BACKEND.md), but backend deploy automation is a follow-up, so this step ships only the front end for now and points at BACKEND.md. Prefers the deploy tool (Pi) or the tl deploy CLI (any shell agent) so the deploy is one mechanical, honest step, never hand-rolled. Run it after thought-layer-build (or tl_scaffold) has produced build.json."
3
+ description: "Take the built site live to a user-owned URL with no lock-in, the last step after the build. Reads .thought-layer/build.json (publish dir + entry) next to the state file, then deploys to Netlify by one of two BYOK models: with NETLIFY_AUTH_TOKEN set it deploys into the user's OWN account via the file-digest API (owned immediately, no claim); with no token it uses the user's Netlify CLI (logged in: a site in their account; logged out: an anonymous, claimable URL with a one-hour claim link). When build.json declares a backend it ships automatically: functions go up via the user's Netlify CLI and the declared env var names are set on the site (values read only from the environment, BYOK). DATABASE_URL is bring-your-own by default; provisionDb and applySchema are opt in; staticOnly ships just the front end. Prefers the deploy tool (Pi) or the tl deploy CLI. Run it after thought-layer-build (or tl_scaffold) has produced build.json."
4
4
  ---
5
5
 
6
6
  # Deploy it: the build goes live to a URL you own
@@ -33,9 +33,15 @@ The tool picks automatically; explain which one ran.
33
33
 
34
34
  If neither a token nor a usable CLI is available, relay the tool's guidance honestly (set a token, install/update the CLI, or drag the publish dir onto https://app.netlify.com/drop) instead of pretending it deployed. If the user explicitly asked for an anonymous deploy but the CLI is logged in, the tool says it went to their account instead and that `netlify logout` first would make it anonymous - pass that on.
35
35
 
36
- ## Static-first honesty
36
+ ## Backend deploy (automatic; static stays the floor)
37
37
 
38
- The default deploy publishes a **static** publish directory. If `build.json.hasBackend` is `true`, the build also emitted a real backend (serverless functions, a `schema.sql`, a names-only `.env.example`, an updated `netlify.toml`, and a `BACKEND.md` guide), but **backend deploy automation is a follow-up**, so this step ships only the front end for now. The tool warns; repeat its guidance plainly and point the user at `BACKEND.md`. To run the backend they provision Neon Postgres, set `DATABASE_URL` (and the other names from `.env.example`) in their host environment, then run `netlify deploy` with the functions present. Do not imply a backend is running when it is not.
38
+ If `build.json.hasBackend` is `true` and the build declared a serverless backend, the tool ships it **automatically** alongside the static front end:
39
+ - **Functions** go up via the user's **Netlify CLI** (it bundles the TypeScript). The CLI is required to ship functions; if it is missing but a token is set, the tool takes the front end live, sets the env vars, and tells the user plainly that functions need the CLI (it does not pretend they shipped).
40
+ - **Env vars**: the declared names are set on the site. Values are read **only from the environment** (BYOK), set via the Netlify API when a token is present (secret-capable) or imported via the CLI otherwise. A declared name that is absent from the environment is reported by name so the user can set it and re-run. Never ask the user to paste a value into the chat.
41
+ - **Database**: `DATABASE_URL` is **bring-your-own** by default (the tool also reads `NETLIFY_DATABASE_URL` / `NETLIFY_DATABASE_URL_UNPOOLED`). Two opt-in flags go further: `--provision-db` / `provisionDb` provisions Neon with the user's own `NEON_API_KEY`, and `--apply-schema` / `applySchema` applies `schema.sql` with `psql`. Both are off by default.
42
+ - **`--static-only` / `staticOnly`** ships just the front end even when a backend is present; the tool then points at `BACKEND.md` for the manual steps.
43
+
44
+ Relay what actually happened: which site got the backend, which functions shipped, which env names were set versus missing. Do not imply a backend is running when it is not (for example, when only the front end shipped because the CLI was absent).
39
45
 
40
46
  ## After it is live
41
47