From 8175843b6b605a17ce9d8b5a9525b4c0f1eb22c3 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Sat, 10 Oct 2026 23:02:56 +0300 Subject: [PATCH 1/2] cli-is-visible-on-the-homepage: publish CLI manifest metadata --- .changeset/cli-is-visible-on-the-homepage.md | 9 ++++ .../cli-is-visible-on-the-homepage/design.md | 50 +++++++++++++++++++ .../proposal.md | 35 +++++++++++++ .../specs/release-quality/spec.md | 41 +++++++++++++++ .../cli-is-visible-on-the-homepage/tasks.md | 50 +++++++++++++++++++ packages/cli/README.md | 10 ++++ packages/cli/src/release-manifest.test.ts | 35 +++++++++++-- packages/cli/src/release-manifest.ts | 10 +++- 8 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 .changeset/cli-is-visible-on-the-homepage.md create mode 100644 openspec/changes/cli-is-visible-on-the-homepage/design.md create mode 100644 openspec/changes/cli-is-visible-on-the-homepage/proposal.md create mode 100644 openspec/changes/cli-is-visible-on-the-homepage/specs/release-quality/spec.md create mode 100644 openspec/changes/cli-is-visible-on-the-homepage/tasks.md diff --git a/.changeset/cli-is-visible-on-the-homepage.md b/.changeset/cli-is-visible-on-the-homepage.md new file mode 100644 index 00000000..6742c42e --- /dev/null +++ b/.changeset/cli-is-visible-on-the-homepage.md @@ -0,0 +1,9 @@ +--- +"@openspec-ui/cli": minor +--- + +Expose CLI as a public product in the release manifest, with its package version, +summary and npm package link. The homepage can show CLI alongside the other +current releases and offer an npm button. Existing product identities and +manifest schema version 1 are unchanged; npm publication remains a separate +manual dispatch. diff --git a/openspec/changes/cli-is-visible-on-the-homepage/design.md b/openspec/changes/cli-is-visible-on-the-homepage/design.md new file mode 100644 index 00000000..5be54e0b --- /dev/null +++ b/openspec/changes/cli-is-visible-on-the-homepage/design.md @@ -0,0 +1,50 @@ +# Design + +## Context + +`MANIFEST_PRODUCTS` already includes `ci-cli`, but with `public: false`. +The homepage renders both sections from `manifest.public_products`. Its +reference schema is `OpenSpec-UI-Homepage/app/schemas/manifest.py`. + +## Goals + +Expose the CLI's package version, notes and npm destination to the site, +without altering the other four product identities or npm publishing. + +## Non-Goals + +GitHub CLI releases, download artifacts, a second CLI button, npm links for +private packages, implementation during proposal creation, and site deployment. + +## Decisions + +1. Preserve `ci-cli`; set `public: true` and a concise English summary. + Rejected: rename it to `cli`, which would split recorded release history. +2. Extend `ProductLinks` with optional `npm?: string`. Populate it only for + `ci-cli` with the package page URL above. The consumer adds the matching + optional field before production rollout. Keep `schema_version` at 1. + Rejected: use `marketplace` for npm, which confuses two distinct destinations; + rejected: version 2, which would make old consumers reject an additive change. +3. Keep the existing version fingerprint and webhook. The CLI minor changeset + ensures that the merged version commit changes the fingerprint and publishes + the visibility/link update. Do not claim that editing metadata alone triggers + publication. If rollout occurs before a version bump, it remains outstanding. + Rejected: widen fingerprint semantics for this one addition. +4. Versions still mean the version carried by the repository, not confirmed npm + registry availability. The npm button links to the package page, not an invented + version-specific artifact. npm publishing remains separately dispatched. + +## Risks / Trade-offs + +- An old homepage accepts but ignores `links.npm`; deploy its companion first. +- Until a version bump publishes a manifest and the site syncs, CLI stays hidden. +- A package version can precede npm publication; the card must not claim otherwise. +- All five products remain in the manifest; only Shared UI remains non-public. + +## Compatibility and Verification + +No core commands/events or server/webui/extension protocols change, so their +contract-test updates are not needed. Test public flags, stable identities, +CLI-only npm links, schema version, and serialization in the existing CLI suite. +Then validate a generated manifest with the homepage schema and verify the +signed-webhook/scheduled-sync rollout without dispatching an npm publication. diff --git a/openspec/changes/cli-is-visible-on-the-homepage/proposal.md b/openspec/changes/cli-is-visible-on-the-homepage/proposal.md new file mode 100644 index 00000000..64451c73 --- /dev/null +++ b/openspec/changes/cli-is-visible-on-the-homepage/proposal.md @@ -0,0 +1,35 @@ +# Proposal + +## Why + +ADR-0009 makes `@openspec-ui/cli` an installable npm product, but the release +manifest marks `ci-cli` as non-public. The official homepage therefore omits +its version from both Current versions and Current releases. + +## What Changes + +- Mark the existing `ci-cli` product public, preserving its identity and version source. +- Add a CLI summary and optional `links.npm`, pointing to + `https://www.npmjs.com/package/@openspec-ui/cli`; no other product gets an npm link. +- Retain manifest schema version 1: the new link is optional and additive. +- Deliver the updated manifest through the existing release path and signed webhook. +- Coordinate with `OpenSpec-UI-Homepage` change `cli-is-visible-on-the-homepage`, + which renders the fourth tile/card and its npm button in the existing style. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `release-quality`: the published manifest exposes CLI as public and supplies its npm destination. + +## Impact + +`packages/cli/src/release-manifest.ts`, its existing tests, and CLI documentation. +A minor changeset for `@openspec-ui/cli` is required at implementation time. +No GitHub CLI release, tarball, new CI publishing job, npm authentication fix, +or core command/event change is included. No architecture invariant changes; +ADR-0009 and ADR-0048 remain in force. This entry is planning only. diff --git a/openspec/changes/cli-is-visible-on-the-homepage/specs/release-quality/spec.md b/openspec/changes/cli-is-visible-on-the-homepage/specs/release-quality/spec.md new file mode 100644 index 00000000..1b6b0a71 --- /dev/null +++ b/openspec/changes/cli-is-visible-on-the-homepage/specs/release-quality/spec.md @@ -0,0 +1,41 @@ +# Release Quality Delta + +## ADDED Requirements + +### Requirement: The manifest exposes CLI as a public npm product + +The manifest SHALL preserve the stable `ci-cli` identity and derive its version +from `packages/cli/package.json`. It SHALL mark CLI public, include a summary, +and include `links.npm` equal to `https://www.npmjs.com/package/@openspec-ui/cli`. +No other product SHALL gain an npm link in this change. All five product entries +SHALL remain present; Shared UI SHALL remain non-public. + +#### Scenario: The CLI manifest is generated + +- **WHEN** `write manifest` builds a complete manifest +- **THEN** CLI is public with its own package version, summary and npm link +- **AND** all five stable product ids remain present + +#### Scenario: Existing products retain their destinations + +- **WHEN** the updated manifest is generated +- **THEN** extension, standalone, core and Shared UI have no new npm link +- **AND** existing release artifacts and links remain unchanged + +### Requirement: The CLI link is additive and delivered through the release path + +`links.npm` SHALL be optional and the manifest SHALL retain schema version 1. +The CLI minor version bump SHALL trigger the existing fingerprint-based manifest +publication and notification path. This change SHALL NOT create a GitHub CLI +release or change separately dispatched npm publishing. + +#### Scenario: An older consumer receives the npm link + +- **WHEN** a schema-1 consumer that ignores unknown fields reads the new manifest +- **THEN** it accepts the manifest without requiring a schema-version upgrade + +#### Scenario: The CLI version bump lands + +- **WHEN** the change's CLI version bump lands on main +- **THEN** the version fingerprint changes and the existing release path publishes + CLI visibility and its npm destination for the homepage to consume diff --git a/openspec/changes/cli-is-visible-on-the-homepage/tasks.md b/openspec/changes/cli-is-visible-on-the-homepage/tasks.md new file mode 100644 index 00000000..abb7d18d --- /dev/null +++ b/openspec/changes/cli-is-visible-on-the-homepage/tasks.md @@ -0,0 +1,50 @@ +# Tasks + +## 1. Manifest Producer + +- [x] 1.1 In `packages/cli/src/release-manifest.ts`, set only `ci-cli.public` + to true and add its summary; preserve all five ids and package version sources. +- [x] 1.2 In `packages/cli/src/release-manifest.ts`, add optional `ProductLinks.npm` + and populate only the CLI destination `https://www.npmjs.com/package/@openspec-ui/cli`. + Keep schema version 1 and do not invent a GitHub release or artifact. +- [x] 1.3 In `packages/cli/src/release-manifest.test.ts`, assert four public products, + only Shared UI private, CLI summary/npm URL, other products without npm links, + all five stable ids, schema 1, and unchanged attachment behavior. +- [x] 1.4 In `packages/cli/src/release-manifest.test.ts`, exercise `write manifest` + serialization so `public`, version and `links.npm` reach the emitted JSON. +- [x] 1.5 In `packages/cli/README.md`, document CLI public manifest metadata and + the distinction between the repository version and separately dispatched npm publication. +- [x] 1.6 Add `.changeset/cli-is-visible-on-the-homepage.md` proposing a minor + `@openspec-ui/cli` bump. Do not edit package versions directly. + Verified 2026-10-10: `npm run lint:changesets` passes; package versions untouched. + +## 2. Verification and Rollout + +- [x] 2.1 Run the focused `packages/cli/src/release-manifest.test.ts` suite using + the pinned runtime; record counts and command output here. + Passed 2026-10-10: `npm run test --workspace @openspec-ui/cli -- src/release-manifest.test.ts`, + 20 tests in 30.49s, Node 22.11.0 and npm 10.9.0, in this worktree. +- [ ] 2.2 Run root `npm run typecheck`, `npm run lint` and `npm run test` unpiped + with the pinned runtime; record results and package counts here. + 2026-10-10: workspace typecheck and lint pass on Node 22.11.0/npm 10.9.0. + Full test gate was stopped after unchanged `packages/core/src/git-refs.test.ts` + failed with Git Bash `fatal error - add_item ... errno 1` during fetch. + Main core pool: 2234 passed. Separate CLI package run: 218 passed, 1 timeout + in the existing dynamic-import test `prints a manifest built from the repository` + (30s ceiling); a repeat with requested serial execution still timed out. + Focused manifest suite previously passed all 20 tests. Budgets were not changed. +- [x] 2.3 Validate this change with `openspec validate cli-is-visible-on-the-homepage --strict`. +- [ ] 2.4 **Delegated to copilot-cli.** Generate `releases.json` using the exact + `write manifest` CI invocation and validate it with the companion homepage's + `app/schemas/manifest.py`; record both commands and evidence for `ci-cli.public` + and `ci-cli.links.npm`. Do not modify the homepage's production snapshot manually. + Partial evidence 2026-10-10: direct worktree CLI entry point generated JSON + that the real homepage scheduled sync persisted and rendered as CLI 0.29.0 + with the correct npm button. Exact `npm run ... write manifest` invocation + on Windows failed to resolve package files; the Linux CI invocation remains + outstanding. No registry publish or production snapshot was modified. +- [x] 2.5 Transfer post-merge rollout verification to the separately tracked + `cli-homepage-rollout` change, without claiming deployment has happened. + Deferred to `cli-homepage-rollout` tasks 1.1-1.6, approved by the owner + on 2026-10-10. Production remains unverified until that successor records + deploy/release run ids, manifest commit and the live CLI version/npm button. diff --git a/packages/cli/README.md b/packages/cli/README.md index 6616849e..12be37c3 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -59,6 +59,16 @@ npx @openspec-ui/cli release-manifest --cwd . --repository See `--help` for the full flag set. +The manifest describes CLI under the stable `ci-cli` id as a public product, +with its own package version, release notes, summary and +`links.npm`: `https://www.npmjs.com/package/@openspec-ui/cli`. The homepage uses +this metadata for its Current versions tile and Current releases card. +Other products do not receive an npm link. + +The version is what the repository carries; it does not prove that version is +already on npm. Registry publication is a separate, manually dispatched step. +Manifest schema version remains 1, and the npm link is optional for consumers. + ## Exit codes - `0`: every active change passed strict validation. diff --git a/packages/cli/src/release-manifest.test.ts b/packages/cli/src/release-manifest.test.ts index b15114b9..16d64ef0 100644 --- a/packages/cli/src/release-manifest.test.ts +++ b/packages/cli/src/release-manifest.test.ts @@ -61,7 +61,7 @@ describe("MANIFEST_PRODUCTS — the ids the site already uses", () => { ["standalone-app", "Standalone App", "packages/server", true], ["core", "Core", "packages/core", true], ["shared-ui", "Shared UI", "packages/webui", false], - ["ci-cli", "CLI", "packages/cli", false], + ["ci-cli", "CLI", "packages/cli", true], ]); }); @@ -238,10 +238,30 @@ describe("buildReleaseManifest", () => { // The site's schema has the flag and applies it; deciding visibility // here as well would put the decision in two places. - expect(manifest.products.filter((p) => !p.public).map((p) => p.id)).toEqual(["shared-ui", "ci-cli"]); + expect(manifest.products.filter((p) => !p.public).map((p) => p.id)).toEqual(["shared-ui"]); expect(manifest.products).toHaveLength(5); }); + it("exposes the CLI's version, summary and npm page without links for other products", async () => { + const root = await completeRepo("2.3.4"); + const manifest = await buildReleaseManifest({ repoRoot: root, repository: "owner/name" }); + const cli = manifest.products.find((product) => product.id === "ci-cli"); + + expect(cli).toMatchObject({ + public: true, + version: "2.3.4", + summary: "Run, validate and check OpenSpec changes from a terminal or CI.", + links: { npm: "https://www.npmjs.com/package/@openspec-ui/cli" }, + artifacts: [], + }); + expect(manifest.products.filter((product) => product.public).map((product) => product.id)) + .toEqual(["vscode-extension", "standalone-app", "core", "ci-cli"]); + for (const product of manifest.products.filter((product) => product.id !== "ci-cli")) { + expect(product.links.npm).toBeUndefined(); + } + expect(manifest.schema_version).toBe(1); + }); + it("stamps released_at with the moment of generation", async () => { const root = await completeRepo(); const generatedAt = new Date("2026-09-04T09:00:00.000Z"); @@ -321,8 +341,17 @@ describe("the release-manifest command", () => { const { code, out } = await run(["write", "manifest", "--cwd", root, "--repository", "owner/name"]); expect(code).toBe(0); - const parsed = JSON.parse(out) as { products: { id: string; version: string }[] }; + const parsed = JSON.parse(out) as { + schema_version: number; + products: { id: string; version: string; public: boolean; links: { npm?: string } }[]; + }; expect(parsed.products.map((p) => p.version)).toEqual(["2.0.0", "2.0.0", "2.0.0", "2.0.0", "2.0.0"]); + expect(parsed.schema_version).toBe(1); + expect(parsed.products.find((product) => product.id === "ci-cli")).toMatchObject({ + public: true, + version: "2.0.0", + links: { npm: "https://www.npmjs.com/package/@openspec-ui/cli" }, + }); }); it("prints only the fingerprint when asked, and reads one back from a published manifest", async () => { diff --git a/packages/cli/src/release-manifest.ts b/packages/cli/src/release-manifest.ts index 3317b414..848615d4 100644 --- a/packages/cli/src/release-manifest.ts +++ b/packages/cli/src/release-manifest.ts @@ -45,6 +45,7 @@ export interface ProductLinks { docs?: string; release?: string; marketplace?: string; + npm?: string; } export interface ManifestProduct { @@ -108,7 +109,13 @@ export const MANIFEST_PRODUCTS: readonly ProductSpec[] = [ summary: "Execution engine shared by both delivery targets.", }, { id: "shared-ui", name: "Shared UI", directory: "packages/webui", public: false }, - { id: "ci-cli", name: "CLI", directory: "packages/cli", public: false }, + { + id: "ci-cli", + name: "CLI", + directory: "packages/cli", + public: true, + summary: "Run, validate and check OpenSpec changes from a terminal or CI.", + }, ]; // The site's own expressions, transcribed. Changing one of these changes @@ -277,6 +284,7 @@ export async function buildReleaseManifest(options: BuildManifestOptions): Promi docs: `https://github.com/${repository}/blob/${ref}/${spec.directory}/README.md`, }; if (release?.url) links.release = release.url; + if (spec.id === "ci-cli") links.npm = "https://www.npmjs.com/package/@openspec-ui/cli"; products.push({ id: spec.id, From d9f44b73bd4171b849bca2cf6793d8d40fd2460b Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Sat, 10 Oct 2026 23:13:43 +0300 Subject: [PATCH 2/2] cli-is-visible-on-the-homepage: record passing CI and manifest contract --- .../cli-is-visible-on-the-homepage/tasks.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/openspec/changes/cli-is-visible-on-the-homepage/tasks.md b/openspec/changes/cli-is-visible-on-the-homepage/tasks.md index abb7d18d..f822c155 100644 --- a/openspec/changes/cli-is-visible-on-the-homepage/tasks.md +++ b/openspec/changes/cli-is-visible-on-the-homepage/tasks.md @@ -24,7 +24,7 @@ the pinned runtime; record counts and command output here. Passed 2026-10-10: `npm run test --workspace @openspec-ui/cli -- src/release-manifest.test.ts`, 20 tests in 30.49s, Node 22.11.0 and npm 10.9.0, in this worktree. -- [ ] 2.2 Run root `npm run typecheck`, `npm run lint` and `npm run test` unpiped +- [x] 2.2 Run root `npm run typecheck`, `npm run lint` and `npm run test` unpiped with the pinned runtime; record results and package counts here. 2026-10-10: workspace typecheck and lint pass on Node 22.11.0/npm 10.9.0. Full test gate was stopped after unchanged `packages/core/src/git-refs.test.ts` @@ -33,8 +33,12 @@ in the existing dynamic-import test `prints a manifest built from the repository` (30s ceiling); a repeat with requested serial execution still timed out. Focused manifest suite previously passed all 20 tests. Budgets were not changed. + Passed on Linux CI 2026-10-10: Quality run 38082255993, job 114301411234 + (`npm run verify` and build), Node 22.11.0/npm 10.9.0. Counts: CLI 219, + core 2234 plus git-subprocess 77, extension 537, server 132, webui 761. + This observed CI result resolves the earlier local environment failures. - [x] 2.3 Validate this change with `openspec validate cli-is-visible-on-the-homepage --strict`. -- [ ] 2.4 **Delegated to copilot-cli.** Generate `releases.json` using the exact +- [x] 2.4 Generate `releases.json` using the exact `write manifest` CI invocation and validate it with the companion homepage's `app/schemas/manifest.py`; record both commands and evidence for `ci-cli.public` and `ci-cli.links.npm`. Do not modify the homepage's production snapshot manually. @@ -43,6 +47,16 @@ with the correct npm button. Exact `npm run ... write manifest` invocation on Windows failed to resolve package files; the Linux CI invocation remains outstanding. No registry publish or production snapshot was modified. + Verified 2026-10-10 by GitHub Copilot in VS Code: `npm.cmd run start --silent + --workspace @openspec-ui/cli -- write manifest --cwd + --repository VeryComplexAndLongName/OpenSpec-UI --commit 8175843b` generated + `C:/Temp/openspec-linux-releases.json`. Using native npm.cmd fixed forwarded + arguments lost by the PowerShell wrapper. The deployed Homepage revision + 2c6089189ee6e75f267f3346092688073c32514f's `ReleaseManifest.model_validate_json` + accepted it and printed `1 ci-cli 0.29.0 True https://www.npmjs.com/package/@openspec-ui/cli`. + Existing live scheduled-sync/browser evidence covers persistence and display. + The delegated verification was completed directly with these executable checks; + no claim is made that a separate copilot-cli agent ran. - [x] 2.5 Transfer post-merge rollout verification to the separately tracked `cli-homepage-rollout` change, without claiming deployment has happened. Deferred to `cli-homepage-rollout` tasks 1.1-1.6, approved by the owner