@hobocode/thought-layer 0.5.0 → 0.6.0
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 +1 -1
- package/SECURITY.md +7 -1
- package/core/backend-io.ts +231 -0
- package/core/backend.ts +46 -0
- package/core/deploy-io.ts +266 -9
- package/core/deploy.ts +10 -2
- package/core/index.ts +1 -0
- package/dist/tl.js +489 -25
- package/extensions/thought-layer.ts +11 -7
- package/package.json +2 -1
- package/prompts/tl-deploy.md +1 -1
- package/skills/thought-layer-build/SKILL.md +2 -2
- package/skills/thought-layer-deploy/SKILL.md +9 -3
|
@@ -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
|
-
"
|
|
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
|
|
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: "
|
|
225
|
-
siteId: Type.Optional(Type.String({ description: "
|
|
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.
|
|
3
|
+
"version": "0.6.0",
|
|
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",
|
package/prompts/tl-deploy.md
CHANGED
|
@@ -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`
|
|
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
|
|
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
|
|
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).
|
|
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). 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 (Neon provisioning and psql schema apply) are opt in; staticOnly ships just the front end. 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."
|
|
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
|
-
##
|
|
36
|
+
## Backend deploy (automatic; static stays the floor)
|
|
37
37
|
|
|
38
|
-
|
|
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
|
|