feat(identity): derive package name/version into project identity (stages 1-2) - #121
Conversation
…ages 1-2) Part of #94. Derives validated packageName/packageVersion from the project's package.json into NormalizedMetadata and ProjectContext, and exposes both axes distinctly in artifact manifests, inspect output, and dev status DTOs (ArtifactEpoch). Projects without a package version keep a clearly labeled development fallback in displays; nothing new is required. New warning diagnostics: AB4008 (plugin.version differs from the package version), AB4009 (invalid npm package name), AB4010 (invalid package semver), AB4011 (unparsable package.json). Per G9, plugin.name stays the host-native slug and is never derived.
Adopted from PR #115 (parallel session): the labeled 0.0.0-dev development-fallback naming, package identity on the dev source status DTO (SourceStatus + agent API wire DTOs + coordinator passthrough), a minor changeset (new public manifest/context fields are a feature), and ProjectService-level source-status test coverage. Codex fixes: reject npm-reserved package names (node_modules, favicon.ico) and ignore a package.json symlinked outside the project root (AB4011) so identity cannot drift without a revision change. Also pins rejection of invalid semver prerelease identifiers, which #115's looser pattern accepted.
🦋 Changeset detectedLatest commit: 316b150 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62dded1611
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| root: string, | ||
| ): SourceStatus => Object.freeze({ | ||
| diagnostics, | ||
| ...sourceIdentity(root), |
There was a problem hiding this comment.
Accept identity axes in the Workbench status schemas
For every project with a valid package name or version, this now adds extra keys to the source status returned by /api/project/status, but packages/workbench/src/project-client.ts still parses that object with a z.strictObject containing only diagnostics, revision, and state. Consequently ProjectClient rejects the response as invalid and the Workbench cannot load packaged projects; after a build, artifactEpochSchema similarly rejects the newly added epoch identity keys. Extend both strict schemas when exposing these fields.
AGENTS.md reference: AGENTS.md:L12-L16
Useful? React with 👍 / 👎.
| try { | ||
| canonicalRoot = realpathSync(resolve(root)); | ||
| packageJsonPath = realpathSync(join(resolve(root), 'package.json')); | ||
| } catch { | ||
| return deepFreeze({ issues: [] }); |
There was a problem hiding this comment.
Report package manifests that cannot be read
When package.json exists but resolving it fails because of permissions, a dangling symlink, or another filesystem error, this catch reports the same empty, issue-free snapshot as a genuinely missing manifest. The later readFileSync catch does the same for readable-path/I/O failures, so validation silently omits package identity instead of producing the advertised AB4011 unusable-manifest diagnostic; distinguish ENOENT from failures involving an existing manifest and return an unparsable/unusable issue for the latter.
Useful? React with 👍 / 👎.
commit: |
…status and artifact decoders The workbench client decodes /api/project/status and the artifact inspection route with exact-key validation, so the new optional packageName/packageVersion axes made every decode fail and the dashboard never settled (all browser e2e suites timed out on visibility). Allow both optional fields in sourceStatusSchema, artifactEpochSchema, and the artifact-client isProject check, and flip the overview.e2e source-status pin to include the derived packageName.
Part of #94 (stages 1 and 2 only; stage 3 — making
plugin.versionoptional and release fail-closed — remains).Continues #117 unchanged (same branch; GitHub blocked reopening it after a post-closure rebase force-push). This is the reconciled superset of #117 and #115 and the single #94 stages 1-2 vehicle; #115 stays closed.
Summary
packageName/packageVersionare derived from the project'spackage.json, validated (npm name rules incl. reserved-name rejection, strict semver 2.0.0), and carried as optional fields onNormalizedMetadataandProjectContext. Both axes surface distinctly in artifact manifests (optionalproject.packageName/project.packageVersionwith strict validation),inspectoutput (JSON viaprojectContext, plusPackage:/Version:human lines), and dev status DTOs (SourceStatus+ agent API wire DTOs,ArtifactEpoch, epoch-store persistence, artifact inspection).package.jsonis authoritative for the release axes;plugin.versiononly authors the native plugin version and never silently wins: a mismatch reports the AB4008 warning. Invalid identity is a diagnostic, never a crash: AB4009 (invalid npm package name), AB4010 (invalid package semver), AB4011 (unusable package.json — unparsable or symlinked outside the project root). Missing package.json/fields stay a silent, normal dev state with the labeled0.0.0-dev.<short-revision>display fallback.plugin.namestays the host-native slug, never derived from the npm package name.Adopted from #115 (parallel session) + Codex triage
0.0.0-devfallback naming; dev source-status DTO exposure; minor changeset; ProjectService-level coverage.Proof
examples-contract.test.ts: audiobook-curator derives@agent-bundle-example/audiobook-curator/1.0.0from package.json (one version source, no AB4008); skills-starter (no package version) shows the labeled development fallback.package-identity.test.ts: direct AB4008 mismatch test; AB4009/AB4010/AB4011; derivation through normalize → context → source status; symlink containment; fallback label.manifest.test.ts: identity axes round-trip; invalid values rejected.normalization.test.tspins for workspace-rooted fixtures now include AB4008.examples/audiobook-curator/agent-bundle.config.tsdocuments the derivation and the AB4008 contract.Out of scope (later waves)
Making
plugin.versionoptional, release fail-closed behavior, derivingplugin.name.