diff --git a/.gitea/workflows/verify.yml b/.gitea/workflows/verify.yml index 6d57f80..2171b4d 100644 --- a/.gitea/workflows/verify.yml +++ b/.gitea/workflows/verify.yml @@ -37,9 +37,9 @@ jobs: - uses: https://github.com/actions/setup-node@v4 with: node-version-file: .nvmrc - - name: Install pinned OpenSpec CLI and lychee 0.24.2 + - name: Install OpenSpec CLI and lychee 0.24.2 run: | - npm install -g "@fission-ai/openspec@$(cat openspec/.cli-version)" + npm install -g @fission-ai/openspec openspec store register . curl --fail --location --silent --show-error https://github.com/lycheeverse/lychee/releases/download/lychee-v0.24.2/lychee-x86_64-unknown-linux-gnu.tar.gz -o /tmp/lychee.tar.gz echo '1f4e0ef7f6554a6ed33dd7ac144fb2e1bbed98598e7af973042fc5cd43951c9a /tmp/lychee.tar.gz' | sha256sum --check diff --git a/README.md b/README.md index 00f3cf8..738eed8 100644 --- a/README.md +++ b/README.md @@ -21,20 +21,20 @@ OpenSpec применяется после явного решения Change Ow npm run validate ``` -Одна команда, её же вызывает CI `verify`: `check:openspec` (Node, версия CLI, -store), `openspec schema validate` (все schemas), `openspec validate --all --strict` -(specs и active changes) и [lychee](https://lychee.cli.rs/) 0.24.2 `--offline +Одна команда, её же вызывает CI `verify`: `openspec schema validate` (все schemas), +`openspec validate --all` (specs и active changes) и [lychee](https://lychee.cli.rs/) 0.24.2 `--offline --include-fragments` для относительных ссылок и anchors в корневых `*.md` (включая `AI_INDEX`) и `openspec/specs`. Архивы и внешние URL не проверяются. В чистой среде один раз: `openspec store register .`; lychee ставится отдельно (например, `brew install lychee`). Для отдельного change: `openspec status --change --store wealth-ledger-specs`. -OpenSpec CLI ставится глобально и не закрепляется в `package.json`: его транзитивная -зависимость `braces` имеет advisory без исправления в 3.x. Ожидаемая версия хранится -в `openspec/.cli-version`; `npm run check:openspec` проверяет Node из `.nvmrc`, версию -CLI и доступность store, и при расхождении выводит команду исправления. Structural -validation не заменяет semantic verification и independent read-only review перед archive. +OpenSpec CLI ставится глобально (`npm install -g @fission-ai/openspec`) и не закрепляется +ни в `package.json` (его транзитивная зависимость `braces` имеет advisory без исправления +в 3.x), ни отдельным файлом версии: CI ставит актуальный выпуск. `validate` не использует +`--strict`: с 1.15 предупреждение о длинных требованиях (>500 символов) считается ошибкой +в strict-режиме. Structural validation не заменяет semantic verification и independent +read-only review перед archive. Node задаётся собственной `.nvmrc`; после `nvm use --silent` выполните `npm ci`. `npm run verify` локально проверяет whitespace в незакоммиченном diff; CI `verify` diff --git a/openspec/.cli-version b/openspec/.cli-version deleted file mode 100644 index b50dd27..0000000 --- a/openspec/.cli-version +++ /dev/null @@ -1 +0,0 @@ -1.13.1 diff --git a/package.json b/package.json index 7d7efe0..09697bd 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ }, "scripts": { "verify": "git diff --check", - "check:openspec": "node scripts/check-openspec.cjs", - "validate": "npm run check:openspec && openspec schema validate && openspec validate --all --strict --no-interactive --store wealth-ledger-specs && lychee --offline --include-fragments --no-progress './*.md' openspec/specs", + "validate": "openspec schema validate && openspec validate --all --no-interactive --store wealth-ledger-specs && lychee --offline --include-fragments --no-progress './*.md' openspec/specs", "release:preview": "release-it --dry-run --ci", "release:prepare": "release-it --ci", "commitlint": "commitlint", diff --git a/scripts/check-openspec.cjs b/scripts/check-openspec.cjs deleted file mode 100644 index 0a92e8a..0000000 --- a/scripts/check-openspec.cjs +++ /dev/null @@ -1,39 +0,0 @@ -const assert = require("node:assert/strict"); -const { execFileSync } = require("node:child_process"); -const { readFileSync } = require("node:fs"); -const path = require("node:path"); - -// OpenSpec CLI is installed globally (no npm pin: its transitive braces advisory has no 3.x fix). -// This check fails fast with an actionable message instead of silently using another version. -const root = path.resolve(__dirname, ".."); -const expectedCli = readFileSync(path.join(root, "openspec/.cli-version"), "utf8").trim(); -const expectedNode = readFileSync(path.join(root, ".nvmrc"), "utf8").trim(); -const store = "wealth-ledger-specs"; - -const run = (command, args) => - execFileSync(command, args, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim(); - -assert.equal( - process.version.replace(/^v/, ""), expectedNode, - `Node ${process.version} differs from .nvmrc ${expectedNode}. Run: nvm use --silent`, -); - -let cliVersion; -try { - cliVersion = run("openspec", ["--version"]); -} catch { - assert.fail(`openspec CLI not found. Install it globally: npm install -g @fission-ai/openspec@${expectedCli}`); -} -assert.equal( - cliVersion, expectedCli, - `openspec ${cliVersion} differs from openspec/.cli-version ${expectedCli}. Reinstall: npm install -g @fission-ai/openspec@${expectedCli}`, -); - -// Store presence is checked by the CLI itself: an unknown store must fail, not fall back silently. -try { - run("openspec", ["validate", "--specs", "--store", store]); -} catch (error) { - assert.fail(`openspec store '${store}' is not usable: ${error.stderr || error.stdout || error.message}`); -} - -console.log(`openspec ${cliVersion} on Node ${expectedNode}: toolchain matches`);