website-build-skill 0.1.4 → 0.1.5

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.
@@ -0,0 +1,57 @@
1
+ {
2
+ "status": "PASS (native loading only)",
3
+ "packageCommit": "c5ab86a70f76dd37b266081d511475dd942e0a1d",
4
+ "packageVersion": "0.1.4 (npm, installed with npx website-build-skill@0.1.4)",
5
+ "mode": "solo",
6
+ "scope": "Native skill discovery and loading in a clean temporary project with a synthetic brief. No website was built; research, mockup, build, review and handoff boundaries were not exercised.",
7
+ "negativeTrials": [],
8
+ "review": {
9
+ "candidateSha256": null,
10
+ "modelFamily": null,
11
+ "findings": [],
12
+ "dispositions": []
13
+ },
14
+ "trialId": "2026-09-24-claude-code-solo-load",
15
+ "client": {
16
+ "host": "Claude Code",
17
+ "version": "2.1.281",
18
+ "os": "macOS 26.6.2 arm64",
19
+ "modelFamily": "Anthropic Claude (claude-opus-5-5)"
20
+ },
21
+ "invocation": "native project skill: installer wrote .claude/skills/website-build-skill/; headless claude -p asked to list project skills and invoke website-build-skill through its native skill mechanism",
22
+ "startedAt": "2026-09-24T02:13:07Z",
23
+ "finishedAt": "2026-09-24T02:14:32Z",
24
+ "commands": [
25
+ "npx --yes website-build-skill@0.1.4 --solo --target claude-code --dir <trial-project> --output-dir <trial-output> --receipt <trial-output>/install-receipt.json --yes",
26
+ "claude -p '<synthetic loading brief>' --output-format json"
27
+ ],
28
+ "artifacts": [
29
+ "installed SKILL.md sha256 ed1c909f9946de0fa7a43364c84efc837b6644c0dc8334b81ddfaf031db156e1",
30
+ "57 files installed under .claude/skills/website-build-skill/"
31
+ ],
32
+ "boundaries": [
33
+ {
34
+ "boundary": "Load",
35
+ "result": "PASS",
36
+ "observed": "Listed website-build-skill as the only project-scoped skill; entrypoint <trial-project>/.claude/skills/website-build-skill/SKILL.md; manifest, 14 prompts, playbooks/research-and-memory.md, 8 checklists and 8 templates READ; roles/, references/stacks/ and examples/ listed but not opened; docs/COMPATIBILITY.md UNREADABLE (source-repo file referenced from SKILL.md, absent from the installed skill)."
37
+ },
38
+ {
39
+ "boundary": "First job",
40
+ "result": "PASS",
41
+ "observed": "Named Researcher first: evidenced ASK DATE, saved library under site-work/research/library/ with source receipts, gate AD01-AD08 and R01-R06 plus check-library before any other job."
42
+ }
43
+ ],
44
+ "limitations": [
45
+ "The client ran with the operator's user-level configuration (about 200 other skills and hooks loaded), so this is not a clean-client install.",
46
+ "SOLO loading only: TEAM, research, build and release boundaries are untested.",
47
+ "One run; no negative trials."
48
+ ],
49
+ "transcriptExcerpt": "## 1. Skills\n\n- **Project-scoped** (`proj/.claude/skills/`): `website-build-skill` (the only one there).\n- **Session-wide**: about 200 more user, plugin and built-in skills are also loaded. I left them out to stay under 300 words and can list them if you want.\n\n## 2. Invocation\n\n- **Entrypoint**: `<trial-project>/.claude/skills/website-build-skill/SKILL.md`\n- **How I checked**: I opened each file and read its first 3 lines. I read `prompts/00-start.md` in full.\n\n**Asset files it names:**\n- **READ**: `manifest.json`\n- **READ**: `prompts/00-start.md`, `01-website-deep-research.md`, `03-extract-brand-kit.md`, `04-three-mockups.md`, `05-stack-and-build.md`, `06-site-audit.md`, `07-accessibility-contrast.md`, `08-seo-aeo.md`, `09-security-headers.md`, `10-adversarial-pre-ship.md`, `11-ship-and-verify.md`, `12-web-design-team.md`, `13-coding-research.md`\n- **READ**: `playbooks/research-and-memory.md`\n- **READ**: `checklists/research.md`, `brand-and-mockups.md`, `build.md`, `code-quality.md`, `accessibility.md`, `performance-seo.md`, `security.md`, `ship.md`\n- **READ**: `templates/brief.md`, `brand.md`, `tokens.json`, `evidence.md`, `handoff.yaml`, `audit-brief.md`, `site-operations.md`, `status.md`\n- **UNREADABLE**: `docs/COMPATIBILITY.md`. The file isn't in the package. SKILL.md says it lives in the source repository.\n- **Not opened**: SKILL.md points to three folders without naming the files: the seven role files (`roles/`), `references/stacks/` and `examples/`. The files exist (I listed them) but I didn't read them.\n\n## 3. First job\n\n- **Researcher** goes first.\n- **Step one**: set the ASK DATE (the date the work starts). It must not come from asking you or from model knowledge. The rule and the fallback steps for finding it are in `playbooks/research-and-memory.md#ask-date-rule`. The date, which step found it and the raw evidence go in `site-work/research/library/scope.md`.\n- **Must produce first**: the saved research library at `site-work/research/library/`, with a receipt for each source fetched. Its gate (research.md AD01-AD08, R01-R06, plus a `check-library` pass) must pass before any other job starts.\n\nI wrote nothing, as you asked. That includes the session's decision-log entry, which I skipped.\n\n<!-- route: main inline | inspection and briefing, no build -->",
50
+ "reproduction": "docs/evaluation/host-trial.md steps 1-4 with the loading brief recorded in this receipt",
51
+ "command": "claude -p '<synthetic loading brief>' --output-format json (after npx --yes website-build-skill@0.1.4 --solo --target claude-code)",
52
+ "environment": "Claude Code 2.1.281, macOS 26.6.2 arm64, Node v22.22.3",
53
+ "date": "2026-09-24",
54
+ "exitCode": 0,
55
+ "artifactSha256": "ed1c909f9946de0fa7a43364c84efc837b6644c0dc8334b81ddfaf031db156e1",
56
+ "observed": "website-build-skill listed as the project skill and invoked natively; entrypoint .claude/skills/website-build-skill/SKILL.md; manifest, prompts, playbook, checklists and templates read; Researcher named as the first job"
57
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "status": "PASS (native loading only)",
3
+ "packageCommit": "c5ab86a70f76dd37b266081d511475dd942e0a1d",
4
+ "packageVersion": "0.1.4 (npm, installed with npx website-build-skill@0.1.4)",
5
+ "mode": "solo",
6
+ "scope": "Native skill discovery and loading in a clean temporary project with a synthetic brief. No website was built; research, mockup, build, review and handoff boundaries were not exercised.",
7
+ "negativeTrials": [],
8
+ "review": {
9
+ "candidateSha256": null,
10
+ "modelFamily": null,
11
+ "findings": [],
12
+ "dispositions": []
13
+ },
14
+ "trialId": "2026-09-24-codex-solo-load",
15
+ "client": {
16
+ "host": "Codex CLI",
17
+ "version": "codex-cli 0.154.0",
18
+ "os": "macOS 26.6.2 arm64",
19
+ "modelFamily": "OpenAI GPT (gpt-6-astra, effort medium)"
20
+ },
21
+ "invocation": "native project skill: installer wrote .agents/skills/website-build-skill/; headless codex exec (read-only sandbox) asked to list project skills and load website-build-skill through its native skill mechanism",
22
+ "startedAt": "2026-09-24T02:16:00Z",
23
+ "finishedAt": "2026-09-24T02:16:56Z",
24
+ "commands": [
25
+ "npx --yes website-build-skill@0.1.4 --solo --target codex --dir <trial-project> --output-dir <trial-output> --receipt <trial-output>/install-receipt.json --yes",
26
+ "codex exec --sandbox read-only '<synthetic loading brief>'"
27
+ ],
28
+ "artifacts": [
29
+ "installed SKILL.md sha256 ed1c909f9946de0fa7a43364c84efc837b6644c0dc8334b81ddfaf031db156e1",
30
+ "57 files installed under .agents/skills/website-build-skill/"
31
+ ],
32
+ "boundaries": [
33
+ {
34
+ "boundary": "Load",
35
+ "result": "PASS",
36
+ "observed": "Reported website-build-skill offered natively in the available-skills catalog with no path guessing; entrypoint <trial-project>/.agents/skills/website-build-skill/SKILL.md; all 57 manifest assets READ; docs/COMPATIBILITY.md UNREADABLE (absent from the installed skill)."
37
+ },
38
+ {
39
+ "boundary": "First job",
40
+ "result": "PASS",
41
+ "observed": "Named Researcher first: evidenced ASK DATE, saved and reopened research library, researcher handoff, AD01-AD08 and R01-R06 before downstream work."
42
+ }
43
+ ],
44
+ "limitations": [
45
+ "Run through the operator's cli-run wrapper, which adds a task-bundle frame to the prompt.",
46
+ "SOLO loading only: TEAM, research, build and release boundaries are untested.",
47
+ "One run; no negative trials.",
48
+ "finishedAt is approximate to the minute (wrapper reported 56.0s)."
49
+ ],
50
+ "transcriptExcerpt": "1. **Project skill:** `website-build-skill`. It was offered natively in the available-skills catalog; no path guessing was needed.\n\n2. **Loaded entrypoint:** `<trial-project>/.agents/skills/website-build-skill/SKILL.md`\n\nComplete manifest asset list, relative to that directory:\n\n- READ `SKILL.md`\n- READ `manifest.json`\n- READ `prompts/00-start.md`\n- READ `prompts/01-website-deep-research.md`\n- READ `archive/graphics-design-original.md`\n- READ `prompts/03-extract-brand-kit.md`\n- READ `prompts/04-three-mockups.md`\n- READ `prompts/05-stack-and-build.md`\n- READ `prompts/06-site-audit.md`\n- READ `prompts/07-accessibility-contrast.md`\n- READ `prompts/08-seo-aeo.md`\n- READ `prompts/09-security-headers.md`\n- READ `prompts/10-adversarial-pre-ship.md`\n- READ `prompts/11-ship-and-verify.md`\n- READ `prompts/12-web-design-team.md`\n- READ `prompts/13-coding-research.md`\n- READ `roles/researcher.md`\n- READ `roles/coordinator.md`\n- READ `roles/designer.md`\n- READ `roles/graphics.md`\n- READ `roles/builder.md`\n- READ `roles/optimizer.md`\n- READ `roles/reviewer.md`\n- READ `playbooks/choose-stack.md`\n- READ `playbooks/data-and-templates.md`\n- READ `playbooks/image-pipeline.md`\n- READ `playbooks/self-hosted-fonts.md`\n- READ `playbooks/embed-facades.md`\n- READ `playbooks/security-headers.md`\n- READ `playbooks/structured-data-and-llms.md`\n- READ `playbooks/performance-budgets.md`\n- READ `playbooks/accessibility.md`\n- READ `playbooks/research-and-memory.md`\n- READ `playbooks/deploy-and-operate.md`\n- READ `checklists/research.md`\n- READ `checklists/brand-and-mockups.md`\n- READ `checklists/build.md`\n- READ `checklists/code-quality.md`\n- READ `checklists/accessibility.md`\n- READ `checklists/performance-seo.md`\n- READ `checklists/security.md`\n- READ `checklists/ship.md`\n- READ `references/stacks/static-html.md`\n- READ `references/stacks/scripted-static.md`\n- READ `references/stacks/framework.md`\n- READ `templates/install-choice.txt`\n- READ `templates/brief.md`\n- READ `templates/brand.md`\n- READ `templates/tokens.json`\n- READ `templates/evidence.md`\n- READ `templates/handoff.yaml`\n- READ `templates/audit-brief.md`\n- READ `templates/site-operations.md`\n- READ `templates/status.md`\n- READ `examples/fictional-studio-brief.md`\n- READ `examples/fictional-studio-handoff.md`\n- READ `examples/audit-cases.md`\n\nAdditional entrypoint reference:\n\n- UNREADABLE `docs/COMPATIBILITY.md`: absent from installed skill.\n\n3. **First job: Researcher.** Establish evidenced ASK DATE, then produce and reopen `site-work/research/library/`: sourced research, domain checklists, coverage, freshness, learning, and evidence receipts. Produce the researcher handoff and pass AD01–AD08 and R01–R06 before downstream work; Coordinator verifies acceptance. No website work was performed.\n",
51
+ "reproduction": "docs/evaluation/host-trial.md steps 1-4 with the loading brief recorded in this receipt",
52
+ "command": "codex exec --sandbox read-only '<synthetic loading brief>' (after npx --yes website-build-skill@0.1.4 --solo --target codex)",
53
+ "environment": "Codex CLI 0.154.0 (gpt-6-astra), macOS 26.6.2 arm64, Node v22.22.3",
54
+ "date": "2026-09-24",
55
+ "exitCode": 0,
56
+ "artifactSha256": "ed1c909f9946de0fa7a43364c84efc837b6644c0dc8334b81ddfaf031db156e1",
57
+ "observed": "website-build-skill offered natively in the available-skills catalog; entrypoint .agents/skills/website-build-skill/SKILL.md; all 57 manifest assets read; Researcher named as the first job"
58
+ }
package/llms.txt CHANGED
@@ -11,6 +11,8 @@ Generated from skills/website-build-skill/manifest.json. Repository: https://git
11
11
  - [Compatibility](docs/COMPATIBILITY.md): host setup routes and the evidence for each
12
12
  - [Documentation](docs/README.md): method, tips, provenance and evaluation
13
13
 
14
+ TEAM: one command installs the seven workers' files; you open each session yourself and carry the handoffs between them. Researcher goes first.
15
+
14
16
  ## Active sources
15
17
 
16
18
  - [SKILL.md](skills/website-build-skill/SKILL.md): Website Build Skill
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "website-build-skill",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Skills that make your AI an expert website builder: current research, design, accessibility, performance, SEO, security and code, for any LLM or agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,7 +40,8 @@ true as of the date of your ask, not from what its model happens to remember.
40
40
  This question is for the human at install, displayed by the README or installer.
41
41
  Follow the recorded --solo / --team choice or the option named in the user's setup prompt.
42
42
  Do not repeat it during the method. If no choice exists, return to the install entrypoint.
43
- Option 2 requires Claude Code, Codex, Hermes, Antigravity, or Grok Bot; its setup checks actual workers.
43
+ TEAM: one command installs the seven workers' files; you open each session yourself and carry the handoffs between them. Researcher goes first.
44
+ Option 2 uses Claude Code, Codex, Hermes, Antigravity, or Grok Bot; the human checks each session.
44
45
  Both options use the same gates. Solo review is INTERNAL until a different family reviews.
45
46
 
46
47
  Read prompts/00-start.md to give Researcher the request and available tools.
@@ -92,7 +93,7 @@ The graphics original is inactive provenance, excluded from every active stage r
92
93
  | Protect | Builder | 09-security-headers | security.md |
93
94
  | Challenge | Different-family Reviewer | 10-adversarial-pre-ship | research.md AD09; [code-quality.md](checklists/code-quality.md); ship.md SH01-SH03 |
94
95
  | Ship | Coordinator acceptance, Builder release | 11-ship-and-verify | ship.md, pre-promotion then live checks |
95
- | Team setup | Human or installer | 12-web-design-team | Seven route acknowledgements; no downstream work yet |
96
+ | Team setup | Human opens sessions and carries handoffs | 12-web-design-team | Seven route acknowledgements; no downstream work yet |
96
97
 
97
98
  Use full filenames and asset order from manifest.json; the table abbreviates prompt suffixes.
98
99
  For limited audits, load the relevant current research and checks without inventing redesign work.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "0.1.4",
3
+ "packageVersion": "0.1.5",
4
4
  "skillName": "website-build-skill",
5
5
  "pathBase": "All asset paths resolve from this manifest directory; runtime paths resolve in the authorized user project.",
6
6
  "assets": [
@@ -17,7 +17,7 @@
17
17
  "skill-zip",
18
18
  "native-skill"
19
19
  ],
20
- "sha256": "ed1c909f9946de0fa7a43364c84efc837b6644c0dc8334b81ddfaf031db156e1"
20
+ "sha256": "71cb5b229d68ae1b91a11d4168c6093a88d0c0f7da2dbcab0c933cb6a333c81b"
21
21
  },
22
22
  {
23
23
  "path": "manifest.json",
@@ -45,7 +45,7 @@
45
45
  "skill-zip",
46
46
  "native-skill"
47
47
  ],
48
- "sha256": "d5ed2a92d5bd7071895658ebbf4d7d696aeddb3735aa8d9153d0405c517f7b9c"
48
+ "sha256": "9de537723108ad71b608c467d78c7ba6edb54880d0429f5321d490cba9c900cb"
49
49
  },
50
50
  {
51
51
  "path": "prompts/01-website-deep-research.md",
@@ -225,7 +225,7 @@
225
225
  "skill-zip",
226
226
  "native-skill"
227
227
  ],
228
- "sha256": "58a53b49b1da1039195d0ecaa24dff296668d9c4c4a52545d40836ddf8d6d388"
228
+ "sha256": "a1b1460deea3520d25245d805521019f758b905b97e73ac97e7020cead861837"
229
229
  },
230
230
  {
231
231
  "path": "prompts/13-coding-research.md",
@@ -15,10 +15,11 @@ Do not repeat the install question mid-method. If no choice is recorded, return
15
15
  its install entrypoint to the human before starting work.
16
16
 
17
17
  TEAM SETUP
18
+ TEAM: one command installs the seven workers' files; you open each session yourself and carry the handoffs between them. Researcher goes first.
18
19
  - Read roles/researcher.md, roles/coordinator.md, roles/designer.md, roles/graphics.md, roles/builder.md,
19
20
  roles/optimizer.md, and roles/reviewer.md.
20
- - Run prompts/12-web-design-team.md to establish workers, ownership, and handoffs.
21
- - Installer or human checks routes during setup; create Researcher first. Coordinator
21
+ - Follow prompts/12-web-design-team.md while the human opens the sessions and carries handoffs.
22
+ - The human checks session references during setup and opens Researcher first. Coordinator
22
23
  records families and working readiness after the research gate passes.
23
24
  - Role labels within one conversation are option 1; if separate workers are unavailable,
24
25
  say so, record SOLO, and continue below. Missing independent review alone blocks
@@ -4,6 +4,7 @@ Never ask the user for the date or infer it from model knowledge. Apply the
4
4
  same source, two-date, freshness, reuse, and blocked-gate rules to this stage.
5
5
 
6
6
  Run option 2, Give me the team, using the human's recorded install choice.
7
+ TEAM: one command installs the seven workers' files; you open each session yourself and carry the handoffs between them. Researcher goes first.
7
8
  Needs Claude Code, Codex, Hermes, Antigravity, or Grok Bot. Follow the setup line for that host.
8
9
 
9
10
  Every agent runs its own research pass before it touches your site, so it works from what is
@@ -16,22 +17,21 @@ SET UP
16
17
  - Read roles/researcher.md first, then roles/coordinator.md, roles/designer.md,
17
18
  roles/graphics.md, roles/builder.md, roles/optimizer.md, roles/reviewer.md,
18
19
  and templates/handoff.yaml. Use each complete body, not these short summaries.
19
- - Create or identify Website Researcher first, then Website Coordinator,
20
+ - The human opens Website Researcher first, then Website Coordinator,
20
21
  Website Designer, Website Graphics, Website Builder, Website Optimizer, and
21
- Website Reviewer as separate sessions, Bots, or terminals. Parent may coordinate
22
- only after the research gate. Use supported setup mechanisms, not invented imports.
23
- - Installer or human checks routes and obtains seven setup acknowledgements.
22
+ Website Reviewer as separate sessions, Bots, or terminals. Coordinator works
23
+ only after the research gate. Use available session controls and complete role files.
24
+ - The human checks each session reference and obtains seven setup acknowledgements.
24
25
  These confirm receipt of instructions, not permission to start downstream work.
25
26
  - A role label in one conversation is option 1. Record SOLO and use prompts/00-start.md
26
27
  if separate workers cannot be reached. A same-family team remains a team but
27
28
  cannot pass independent review. Respect host concurrency limits.
28
- - Antigravity setup uses generated agent definitions and per-role tool declarations;
29
- Hermes setup uses the verified definition branch or generated session packets and
30
- bundle alias. Read the host adapter and receipt; pending discovery, trust, tools,
31
- or independent review checks cannot be reported as a ready team.
29
+ - Read the host adapter and receipt. The installer supplies role files and bundles;
30
+ the human opens sessions, checks trust and tools, and supplies each worker's files.
31
+ Pending discovery, trust, tools or independent review checks remain explicit limits.
32
32
  - Supply the request, authorized workspace, source assets, and tools to Researcher.
33
- All other roles wait. Use the manual fallback in the team bundle if setup cannot
34
- be automated; actual package integration remains UNVERIFIED until tested.
33
+ All other roles wait. Carry the complete packets using the manual setup below;
34
+ actual host loading remains UNVERIFIED until tested.
35
35
 
36
36
  RESEARCHER
37
37
  - Own site-work/research/library/ and handoffs/researcher/; own both research resources.
@@ -114,9 +114,9 @@ Never report a measured, saved, installed, or deployed result without evidence.
114
114
  Apply checklists/research.md before downstream dispatch and checklists/ship.md before release.
115
115
 
116
116
  PORTABLE MANUAL SETUP
117
- Use this fallback when native adapters or generated bundles are not supplied.
118
- Native loading, automatic worker creation, routing, tool enforcement and different-family
119
- availability are UNVERIFIED until the actual host/session checks succeed.
117
+ Use this setup for TEAM on every host. You open each session and carry every handoff.
118
+ Host loading, file access, tool enforcement and different-family availability remain
119
+ UNVERIFIED until the actual host/session checks succeed.
120
120
  A missing host adapter does not authorize inventing a native file format or import API.
121
121
 
122
122
  1. Open the host's verified worker/session creation surface, if available.
@@ -128,8 +128,8 @@ A missing host adapter does not authorize inventing a native file format or impo
128
128
  with evidence, tools, inaccessible files, and owned paths. Keep downstream work pending.
129
129
  5. Give Reviewer a read-only candidate packet or verified read-only session. Broad
130
130
  inherited tools do not become restricted because role prose says read-only.
131
- 6. Verify a bounded setup message reaches each intended route through supported controls.
132
- When group automation is absent, the human can relay addressed packets and attachments.
131
+ 6. Deliver a bounded setup message to each session yourself. Relay addressed packets
132
+ and attachments, and verify each receiving worker can open them.
133
133
  7. Give the user's actual request, authorized workspace, assets and constraints to
134
134
  Researcher alone. It establishes ASK DATE and completes the library and gate first.
135
135
  8. Relay its complete passing receipt and readable library to Coordinator. Coordinator
@@ -138,7 +138,7 @@ A missing host adapter does not authorize inventing a native file format or impo
138
138
  Preserve seven acknowledgements separately from research and work-readiness receipts.
139
139
  A text-only group requires direct image attachments to each receiving visual reviewer.
140
140
  Inaccessible files or routes keep the relevant handoff BLOCKED.
141
- No automatic creation support means a manual setup limit, not a claimed ready team.
141
+ Completed file installation means the files are available; session setup is the human's next step.
142
142
  No separate workers means SOLO; no independent family means independent review BLOCKED.
143
143
  Never invent a platform capability to fill a setup gap.
144
144
 
package/src/bundle.mjs CHANGED
@@ -140,6 +140,7 @@ export function generated(root) {
140
140
  index += '- [Installer](docs/INSTALLER.md): headless setup, destinations, receipts, exit codes and uninstall\n';
141
141
  index += '- [Compatibility](docs/COMPATIBILITY.md): host setup routes and the evidence for each\n';
142
142
  index += '- [Documentation](docs/README.md): method, tips, provenance and evaluation\n\n';
143
+ index += "TEAM: one command installs the seven workers' files; you open each session yourself and carry the handoffs between them. Researcher goes first.\n\n";
143
144
  index += '## Active sources\n\n';
144
145
  for (const asset of m.assets.filter(a => a.active)) index += `- [${asset.path}](${CORE}/${asset.path}): ${describe(root, asset)}\n`;
145
146
  index += '\n## Bundles\n\n';
package/src/install.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import { resolve, relative, dirname, basename, sep } from 'node:path';
2
+ import { resolve, relative, dirname, basename, join, sep } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { randomUUID } from 'node:crypto';
5
5
  import { CORE, files, owned, digest } from './bundle.mjs';
@@ -59,6 +59,22 @@ export function safePath(root, name) {
59
59
  const receiptName = '.website-build-skill-receipt.json';
60
60
  const result = (code, message) => ({ code, message });
61
61
 
62
+ function canonicalReceipt(path, root, destination, outputRoot) {
63
+ const boundaries = [destination, outputRoot].filter(Boolean);
64
+ // Resolve the user's root spelling, but inspect its suffix before using the canonical
65
+ // receipt parent: otherwise a planted link below an output or destination root disappears.
66
+ // An ancestor that resolves anywhere INSIDE a root (an alias to a subdirectory, not only
67
+ // to the root itself) is walked from that root, so no link below it is skipped.
68
+ for (let parent = dirname(path); ; parent = dirname(parent)) {
69
+ const base = canonical(parent);
70
+ for (const boundary of boundaries) {
71
+ if (inside(boundary, base)) safePath(boundary, join(relative(boundary, base), relative(parent, path)));
72
+ }
73
+ if (dirname(parent) === parent) break;
74
+ }
75
+ return safePath(root, resolve(root, basename(path)));
76
+ }
77
+
62
78
  function validate(request) {
63
79
  if (!Object.hasOwn(targets, request.target)) throw Error('Unknown or missing target');
64
80
  if (!['solo', 'team'].includes(request.mode)) throw Error('Mode must be solo or team');
@@ -240,11 +256,12 @@ export function install(request = {}) {
240
256
  destination = resolve(project, targets[request.target]);
241
257
  receiptPath = resolve(request.receipt ?? resolve(destination, receiptName));
242
258
  receiptRoot = request.receipt ? canonical(dirname(receiptPath)) : destination;
243
- outputRoot = request.outputDir === undefined ? null : canonical(request.outputDir);
244
259
  }
260
+ outputRoot = request.outputDir === undefined ? null : canonical(request.outputDir);
245
261
  } catch (error) { return result(2, error.message); }
246
- if (request.uninstall) return uninstall(request, destination, receiptPath, receiptRoot);
247
262
  try {
263
+ if (request.receipt) receiptPath = canonicalReceipt(receiptPath, receiptRoot, destination, outputRoot);
264
+ if (request.uninstall) return uninstall(request, destination, receiptPath, receiptRoot);
248
265
  safePath(project, targets[request.target]);
249
266
  if (request.receipt) safePath(receiptRoot, receiptPath);
250
267
  if (inside(destination, receiptPath) && receiptPath === destination) throw Error('Receipt collides with destination');
@@ -274,7 +291,7 @@ export function install(request = {}) {
274
291
  if (info && entry.wrote) conflicts.push(entry.path);
275
292
  }
276
293
  if (conflicts.length) return result(3, `Preflight conflicts; nothing written:\n${conflicts.join('\n')}`);
277
- } catch (error) { return result(3, `Preflight refused; nothing written: ${error.message}`); }
294
+ } catch (error) { return request.uninstall ? result(2, error.message) : result(3, `Preflight refused; nothing written: ${error.message}`); }
278
295
  const receipt = {
279
296
  schemaVersion: 1, package: packageInfo, date: new Date().toISOString(), mode: request.mode,
280
297
  target: request.target, scope: request.scope ?? 'project', destination, outputRoot,