Skip to content

feat(identity): derive package name/version into project identity (stages 1-2) - #117

Closed
ScriptedAlchemy wants to merge 1 commit into
mainfrom
wave1/94-package-identity
Closed

feat(identity): derive package name/version into project identity (stages 1-2)#117
ScriptedAlchemy wants to merge 1 commit into
mainfrom
wave1/94-package-identity

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Part of #94 (stages 1 and 2 only; stage 3 — making plugin.version optional and release fail-closed — remains).

Summary

  • Stage 1 — derived identity axes. packageName/packageVersion are derived from the project's package.json, validated (npm name rules, strict semver 2.0.0), and carried as new optional fields on NormalizedMetadata and ProjectContext. Both axes surface distinctly in artifact manifests (project.packageName/project.packageVersion, optional keys with strict validation), inspect output (JSON via projectContext, plus Package:/Version: lines in human output), and dev status DTOs (ArtifactEpoch, epoch-store persistence, artifact inspection).
  • Stage 2 — mismatch diagnostics. When config plugin.version differs from the package version, validate reports the new AB4008 warning. Invalid identity values are diagnostics, never crashes: AB4009 (invalid npm package name), AB4010 (invalid package semver), AB4011 (unparsable package.json). All are warnings in the AB40xx plugin-metadata family; a missing package.json or missing fields stays a silent, normal dev state.
  • G9 respected: plugin.name stays the host-native slug and is never derived from the npm package name.

Proof

  • examples-contract.test.ts: audiobook-curator derives @agent-bundle-example/audiobook-curator / 1.0.0 from its 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 tests, derivation through normalize → project context, dev-fallback label.
  • manifest.test.ts: identity axes round-trip; invalid values rejected by the manifest validator.
  • Pin flips (conscious, same PR): three normalization.test.ts pins for fixtures rooted at the workspace now include AB4008 (workspace package.json 0.0.0 vs fixture plugin.version 1.0.0).
  • examples/audiobook-curator/agent-bundle.config.ts documents the derivation and the AB4008 contract.

Out of scope (later waves)

Making plugin.version optional, release fail-closed behavior, deriving plugin.name.

…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.
@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a49259a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T01:13:27.439599Z a49259a PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a49259a0ec

ℹ️ 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".

Comment on lines +51 to +52
/** npm's naming rules for new packages: lowercase, URL-safe, optional scope. */
const packageNamePattern = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/u;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject npm-reserved package names

Reject reserved names such as node_modules and favicon.ico, which this regex currently accepts even though npm's package-name validator marks them invalid. With either value in package.json, snapshotPackageIdentity emits it as a validated packageName, AB4009 is skipped, and artifact-manifest validation also accepts the invalid release identity.

Useful? React with 👍 / 👎.

Comment on lines +74 to +75
try {
bytes = readFileSync(join(resolve(root), 'package.json'), 'utf8');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep package identity inside the project root

Resolve and contain-check package.json before reading it. When a project-root package.json is a symlink to a file outside the root, this read derives release identity from that external file, while the source snapshot traversal ignores symlink entries; consequently the external bytes are absent from sourceInputs and the dev publication drift check cannot detect changes to them during a build.

Useful? React with 👍 / 👎.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Duplicate of Wave 1 Lane A #94 stages 1-2. Keeper is #115.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Codex review triage (commit 4179a20):

  • Reject npm-reserved package names — fixed. isValidPackageName now rejects node_modules and favicon.ico (case-insensitive), so AB4009 fires and the manifest validator refuses them.
  • Keep package identity inside the project root — fixed. snapshotPackageIdentity realpath-resolves package.json and, when it escapes the project root, ignores the identity and reports AB4011 (outside-root), so identity can never drift without a source-revision change.

Also folded in from the parallel PR #115: 0.0.0-dev fallback naming, package identity on the dev source status DTO + agent API wire DTOs, minor changeset, and ProjectService-level coverage. #115's other Codex finding (loose semver prerelease acceptance, e.g. 1.0.0-01) does not apply here — this PR uses the strict semver 2.0.0 grammar and now pins that with tests.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Crossed-closure note: two parallel reconciliations of the duplicate #94 PRs ran at once. This PR was closed at 01:15Z as a presumed duplicate of #115, while the other reconciliation (per the owner's directive) had closed #115 and kept this PR as the keeper — by then it had already absorbed #115's improvements (0.0.0-dev fallback naming, dev source-status DTO exposure, minor changeset, ProjectService coverage) plus the Codex fixes from both reviews (npm-reserved names → AB4009, package.json root-escape → AB4011), making it the reconciled superset.

The owner authorized reopening this PR, but GitHub refuses (state cannot be changed. The wave1/94-package-identity branch was force-pushed or recreated. — the branch was rebased onto main after closure, which permanently blocks reopen). The identical branch continues as the single #94 stages 1-2 vehicle in a follow-up PR; #115 stays closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant