[E00-S01-T03] Configure ESM package boundaries #156

Closed
opened 2026-08-27 00:06:29 +00:00 by kpcto · 8 comments
Owner

Parent story: [E00-S01] Workspace bootstrap (#58)

Intent

Configure ESM package boundaries so apps, core packages and extensions keep clean module boundaries.

Acceptance criteria

  • each package declares ESM boundaries in its manifest
  • package boundaries are configured consistently across the workspace

Explicitly out of scope

  • tsconfig.base.json (E00-S01-T02)
  • dependency-boundary rule/test (E00-S01-T04)
  • root build/test scripts (E00-S01-T05)

Test plan

  • compile every workspace package and confirm boundaries resolve

Rollback note

  • revert the manifest/package configuration changes

Owning stream

platform

Risk quadrant

agent-full

> Parent story: [E00-S01] Workspace bootstrap (#58) ## Intent Configure ESM package boundaries so apps, core packages and extensions keep clean module boundaries. ## Acceptance criteria - each package declares ESM boundaries in its manifest - package boundaries are configured consistently across the workspace ## Explicitly out of scope - tsconfig.base.json (E00-S01-T02) - dependency-boundary rule/test (E00-S01-T04) - root build/test scripts (E00-S01-T05) ## Test plan - compile every workspace package and confirm boundaries resolve ## Rollback note - revert the manifest/package configuration changes ### Owning stream platform ### Risk quadrant agent-full
kpcto added this to the Sprint 0 milestone 2026-08-27 00:06:29 +00:00
kpcto added the
kind
task
status
ready
labels 2026-08-27 00:06:29 +00:00
bot-dispatcher added
status
proposed
and removed
status
ready
kind
task
labels 2026-08-27 00:06:31 +00:00
Member

Auto-reverted by dispatcher: DoR lint: required section "Intent" is empty; required section "Acceptance criteria" is empty; required section "Explicitly out of scope" is empty; required section "Test plan" is empty; required section "Rollback note" is empty; acceptance criteria: no bullet assertions found

status/ready may only be applied by a human maintainer.

> Auto-reverted by dispatcher: DoR lint: required section "Intent" is empty; required section "Acceptance criteria" is empty; required section "Explicitly out of scope" is empty; required section "Test plan" is empty; required section "Rollback note" is empty; acceptance criteria: no bullet assertions found `status/ready` may only be applied by a human maintainer.
kpcto added the
kind
task
label 2026-08-27 21:23:35 +00:00
kpcto added
status
ready
and removed
status
proposed
labels 2026-08-28 08:08:31 +00:00
bot-dispatcher added
loop
1
status
in-progress
and removed
status
ready
labels 2026-08-28 08:08:33 +00:00
Member
agent: dispatcher
phase: complete
plan_summary: Dispatch #156: [E00-S01-T03] Configure ESM package boundaries (platform)
```yaml agent: dispatcher phase: complete plan_summary: Dispatch #156: [E00-S01-T03] Configure ESM package boundaries (platform) ```
Member
agent: implementer
phase: start
objective: "[E00-S01-T03] Configure ESM package boundaries"
plan_summary: >
  Add ESM boundary declarations to every workspace package manifest
  (apps/server, packages/core, extensions/example): "type": "module", a
  main/types entry-point pair and an exports map (types + import conditions),
  plus "type": "module" on the workspace root so the whole workspace is
  uniformly ESM. Verify by compiling every package under tsconfig.base.json
  (NodeNext ESM emit), importing each built package through its exports map
  with Node, and confirming the frozen lockfile still installs unchanged;
  open a PR with a criterion -> test table.
feature_flag: feature/156
```yaml agent: implementer phase: start objective: "[E00-S01-T03] Configure ESM package boundaries" plan_summary: > Add ESM boundary declarations to every workspace package manifest (apps/server, packages/core, extensions/example): "type": "module", a main/types entry-point pair and an exports map (types + import conditions), plus "type": "module" on the workspace root so the whole workspace is uniformly ESM. Verify by compiling every package under tsconfig.base.json (NodeNext ESM emit), importing each built package through its exports map with Node, and confirming the frozen lockfile still installs unchanged; open a PR with a criterion -> test table. feature_flag: feature/156 ```
Member
agent: reviewer
verdict: in-progress

Beginning review of PR #370 for ESM package boundary configuration.

```yaml agent: reviewer verdict: in-progress ``` Beginning review of PR #370 for ESM package boundary configuration.
Member
agent: implementer
phase: complete
objective: "[E00-S01-T03] Configure ESM package boundaries"
result: >
  Every workspace package manifest (apps/server, packages/core,
  extensions/example) now declares its ESM boundary: "type": "module",
  "main": "./dist/index.js", "types": "./dist/index.d.ts" and an "exports"
  map ("." -> { types, import }) that exposes only the package root and
  blocks deep subpath imports. Root package.json also declares
  "type": "module" so the whole workspace is uniformly ESM. Sources are
  untouched (empty ESM placeholder modules). tsconfig.base.json,
  dependency-boundary rule/test and root build/test scripts stay out of
  scope per the brief.
verification:
  compile: "tsc -p <pkg>/tsconfig.json OK for all 3 packages (TS 6.0.3, NodeNext); each emits ESM dist/index.js + dist/index.d.ts + sourcemap"
  esm_emit: "dist/index.js is real ESM (top-level `export {};`, no CJS exports./require)"
  exports_resolution: "consumer project imports all 3 packages by name through the exports map -> [object Module]"
  boundary_enforcement: "deep import @personal-blog/core/src/index.js rejected: ERR_PACKAGE_PATH_NOT_EXPORTED"
  frozen_lockfile: "pnpm 11.23.0 install --frozen-lockfile -> 'Already up to date', exit 0, lockfile unchanged (git status clean apart from the 4 manifests)"
  workspace_groups: "pnpm -r list --depth -1 lists all 4 workspace projects (root + 3 packages)"
pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/370"
ci: "run #37 success (Frozen lockfile install, all 5 steps green)"
feature_flag: feature/156
```yaml agent: implementer phase: complete objective: "[E00-S01-T03] Configure ESM package boundaries" result: > Every workspace package manifest (apps/server, packages/core, extensions/example) now declares its ESM boundary: "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts" and an "exports" map ("." -> { types, import }) that exposes only the package root and blocks deep subpath imports. Root package.json also declares "type": "module" so the whole workspace is uniformly ESM. Sources are untouched (empty ESM placeholder modules). tsconfig.base.json, dependency-boundary rule/test and root build/test scripts stay out of scope per the brief. verification: compile: "tsc -p <pkg>/tsconfig.json OK for all 3 packages (TS 6.0.3, NodeNext); each emits ESM dist/index.js + dist/index.d.ts + sourcemap" esm_emit: "dist/index.js is real ESM (top-level `export {};`, no CJS exports./require)" exports_resolution: "consumer project imports all 3 packages by name through the exports map -> [object Module]" boundary_enforcement: "deep import @personal-blog/core/src/index.js rejected: ERR_PACKAGE_PATH_NOT_EXPORTED" frozen_lockfile: "pnpm 11.23.0 install --frozen-lockfile -> 'Already up to date', exit 0, lockfile unchanged (git status clean apart from the 4 manifests)" workspace_groups: "pnpm -r list --depth -1 lists all 4 workspace projects (root + 3 packages)" pr: "https://git.stevanovic.co.uk/Fabrika/PersonalBlog/pulls/370" ci: "run #37 success (Frozen lockfile install, all 5 steps green)" feature_flag: feature/156 ```
Member
agent: reviewer
verdict: approve
```yaml agent: reviewer verdict: approve ```
bot-dispatcher added
status
review
and removed
status
in-progress
loop
1
kind
task
labels 2026-08-28 08:14:45 +00:00
Member
agent: tester
phase: start
objective: "independently probe the PR for #156"
scope: PR #370 (feature/156 -> main)
acceptance:
  - "each package declares ESM boundaries in its manifest"
  - "package boundaries are configured consistently across the workspace"
method: "parse manifests + compile each package + verify exports-map resolution/blocking via Node"
```yaml agent: tester phase: start objective: "independently probe the PR for #156" scope: PR #370 (feature/156 -> main) acceptance: - "each package declares ESM boundaries in its manifest" - "package boundaries are configured consistently across the workspace" method: "parse manifests + compile each package + verify exports-map resolution/blocking via Node" ```
Member
agent: tester
phase: complete
verdict: pass
objective: "independently probe the PR for #156"
pr: "http://gitea:3000/Fabrika/PersonalBlog/pulls/370"
branch: "feature/156 -> main (head b1fef8d)"
ci:
  run: "http://gitea:3000/Fabrika/PersonalBlog/actions/runs/37"
  job: "http://gitea:3000/Fabrika/PersonalBlog/actions/runs/37/jobs/49"
  conclusion: success
  steps: "all 5 green (checkout, node24, corepack/pnpm, frozen install, workspace list)"
acceptance:
  - criterion: "each package declares ESM boundaries in its manifest"
    result: pass
    evidence: >-
      apps/server, packages/core, extensions/example each declare
      "type":"module", "main":"./dist/index.js", "types":"./dist/index.d.ts",
      and an "exports" map ( "." -> { types, import } ). Root package.json
      declares "type":"module". Verified by parsing every workspace manifest.
  - criterion: "package boundaries are configured consistently across the workspace"
    result: pass
    evidence: >-
      all 3 distributable packages share the byte-identical canonical boundary
      (type/module + main + types + exports); "types" condition precedes
      "import" in each exports map (3/3); workspace lists 4 projects
      (root + 3 packages). No other workspace member manifest is missing a
      boundary.
verification:
  compile: "tsc -p <pkg>/tsconfig.json OK for apps/server, packages/core, extensions/example (TypeScript 6.0.3, NodeNext) — exit 0"
  esm_emit: "each emits dist/index.js (top-level `export {};`) + dist/index.d.ts + dist/index.js.map; no CJS artifacts (grep for exports./module.exports/require -> none)"
  exports_resolution: "isolated file: consumer imports all 3 by name via exports map -> [object Module] (3/3)"
  boundary_enforcement: "deep imports blocked with ERR_PACKAGE_PATH_NOT_EXPORTED: core/src/index.js, core/dist/index.js, server/dist/index.js, example-extension/src/index.js, core/package.json (5/5)"
  frozen_lockfile: "pnpm 11.23.0 install --frozen-lockfile -> 'Already up to date', exit 0, git status clean, lockfile identical to main"
  workspace_groups: "pnpm -r list --depth -1 -> 4 projects"
notes:
  - "CI job #49 only runs frozen install + workspace list — it does NOT compile; compilation and exports-map resolution were verified independently in this probe."
  - "Root package.json carries only type:module (no main/types/exports); expected for a non-distributable workspace root, consistent with the issue's apps/core/extensions scope."
```yaml agent: tester phase: complete verdict: pass objective: "independently probe the PR for #156" pr: "http://gitea:3000/Fabrika/PersonalBlog/pulls/370" branch: "feature/156 -> main (head b1fef8d)" ci: run: "http://gitea:3000/Fabrika/PersonalBlog/actions/runs/37" job: "http://gitea:3000/Fabrika/PersonalBlog/actions/runs/37/jobs/49" conclusion: success steps: "all 5 green (checkout, node24, corepack/pnpm, frozen install, workspace list)" acceptance: - criterion: "each package declares ESM boundaries in its manifest" result: pass evidence: >- apps/server, packages/core, extensions/example each declare "type":"module", "main":"./dist/index.js", "types":"./dist/index.d.ts", and an "exports" map ( "." -> { types, import } ). Root package.json declares "type":"module". Verified by parsing every workspace manifest. - criterion: "package boundaries are configured consistently across the workspace" result: pass evidence: >- all 3 distributable packages share the byte-identical canonical boundary (type/module + main + types + exports); "types" condition precedes "import" in each exports map (3/3); workspace lists 4 projects (root + 3 packages). No other workspace member manifest is missing a boundary. verification: compile: "tsc -p <pkg>/tsconfig.json OK for apps/server, packages/core, extensions/example (TypeScript 6.0.3, NodeNext) — exit 0" esm_emit: "each emits dist/index.js (top-level `export {};`) + dist/index.d.ts + dist/index.js.map; no CJS artifacts (grep for exports./module.exports/require -> none)" exports_resolution: "isolated file: consumer imports all 3 by name via exports map -> [object Module] (3/3)" boundary_enforcement: "deep imports blocked with ERR_PACKAGE_PATH_NOT_EXPORTED: core/src/index.js, core/dist/index.js, server/dist/index.js, example-extension/src/index.js, core/package.json (5/5)" frozen_lockfile: "pnpm 11.23.0 install --frozen-lockfile -> 'Already up to date', exit 0, git status clean, lockfile identical to main" workspace_groups: "pnpm -r list --depth -1 -> 4 projects" notes: - "CI job #49 only runs frozen install + workspace list — it does NOT compile; compilation and exports-map resolution were verified independently in this probe." - "Root package.json carries only type:module (no main/types/exports); expected for a non-distributable workspace root, consistent with the issue's apps/core/extensions scope." ```
kpcto closed this issue 2026-08-28 08:21:11 +00:00
kpcto added
kind
task
status
done
and removed
status
review
labels 2026-08-28 08:25:26 +00:00
Sign in to join this conversation.