docs(specs): harden OpenSpec authority lifecycle
This commit is contained in:
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
## Назначение
|
## Назначение
|
||||||
|
|
||||||
Репозиторий SDD-артефактов и OpenSpec store: `openspec/`. Все функциональные изменения планируются в `openspec/changes/<change>/` до реализации в frontend или backend.
|
Репозиторий единственных versioned SDD-артефактов и canonical OpenSpec store: `wealth-ledger-specs` в `specs/openspec` (относительно workspace). Все функциональные изменения планируются в `openspec/changes/<change>/` до реализации в frontend или backend.
|
||||||
|
|
||||||
## Проверка
|
## Проверка
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
openspec validate <change> --type change --store wealth-ledger-specs
|
openspec validate <change> --type change --store wealth-ledger-specs
|
||||||
openspec instructions apply --change <change> --json --store wealth-ledger-specs
|
openspec instructions apply --change <change> --json --store wealth-ledger-specs
|
||||||
|
bash scripts/verify-openspec-authority.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Границы
|
## Границы
|
||||||
@@ -17,3 +18,5 @@ openspec instructions apply --change <change> --json --store wealth-ledger-specs
|
|||||||
- Реализация отмечается в tasks только после выполненной работы. Перед архивированием change проходит `opsx-verify` и получает связанную документацию в `../docs`.
|
- Реализация отмечается в tasks только после выполненной работы. Перед архивированием change проходит `opsx-verify` и получает связанную документацию в `../docs`.
|
||||||
- Не хранить код приложений и долгоживущие ADR в этом репозитории.
|
- Не хранить код приложений и долгоживущие ADR в этом репозитории.
|
||||||
- Для задачи по Audit ID, продолжения remediation или выбора следующего улучшения сначала прочитать [`../docs/development/audit-remediation.md`](../docs/development/audit-remediation.md); продолжать или создавать change только в store `wealth-ledger-specs`.
|
- Для задачи по Audit ID, продолжения remediation или выбора следующего улучшения сначала прочитать [`../docs/development/audit-remediation.md`](../docs/development/audit-remediation.md); продолжать или создавать change только в store `wealth-ledger-specs`.
|
||||||
|
- Все OpenSpec commands, читающие или изменяющие change, обязаны указывать `--store wealth-ledger-specs`; nearest-root и global-default selection не поддерживаются.
|
||||||
|
- Не создавать и не коммитить framework-specific planning/spec/task/design artifacts вне `openspec/` (то есть `specs/openspec` от workspace), включая `superpowers/plans`; `../references/**` остаётся read-only исключением.
|
||||||
|
|||||||
@@ -33,5 +33,16 @@
|
|||||||
## 6. Верификация и архив
|
## 6. Верификация и архив
|
||||||
|
|
||||||
- [x] 6.1 Прогнать `opsx-verify` по change
|
- [x] 6.1 Прогнать `opsx-verify` по change
|
||||||
- [ ] 6.2 Архив change через `openspec archive` и синхронизация delta в main spec
|
- [x] 6.2 Архив change через `openspec archive` и синхронизация delta в main spec
|
||||||
- [ ] 6.3 Закоммитить по репозиториям: specs, docs, backend, frontend
|
- [x] 6.3 Закоммитить по репозиториям: specs, docs, backend, frontend
|
||||||
|
|
||||||
|
## Сверка evidence — 2026-08-23
|
||||||
|
|
||||||
|
Задачи 6.2–6.3 были незакрытыми administrative tasks после фактического archive. Их статус согласован по текущему read-only evidence; эта запись не меняет archive date, implementation files, delta specs или прошлые Git commits.
|
||||||
|
|
||||||
|
- `git -C specs show --stat --oneline --summary 6795ee6` — commit `6795ee6` от 2026-08-17 создаёт `openspec/changes/archive/2026-08-17-redesign-position-cards/` и одновременно изменяет `openspec/specs/portfolio-view/spec.md`; это подтверждает archive и sync delta.
|
||||||
|
- `git -C docs show --stat --oneline --summary c628535` — commit `c628535` от 2026-08-17 обновляет `features/portfolio-view.md`.
|
||||||
|
- `git -C backend show --stat --oneline --summary 5aa9bd3` — commit `5aa9bd3` от 2026-08-17 содержит ISIN DTO/service/client/spec changes.
|
||||||
|
- `git -C frontend show --stat --oneline --summary 5168870` — commit `5168870` от 2026-08-17 содержит Position Card, OpenAPI, i18n и tests changes.
|
||||||
|
|
||||||
|
В local history отсутствует отдельный terminal transcript вызова `openspec archive`; evidence выше подтверждает его наблюдаемый результат и связанные commits, не приписывая прошлому workflow незафиксированные команды.
|
||||||
|
|||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-08-23
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
## Контекст
|
||||||
|
|
||||||
|
Мотивация приведена в `proposal.md`, а поведенческий контракт — в delta specs. `specs/openspec` уже является единственным project-owned физическим OpenSpec root, но unscoped OpenSpec CLI resolution сейчас зависит от изменяемого machine default. Workspace и четыре независимых репозитория имеют agent instructions, тогда как восемь `.opencode` commands и восемь соответствующих skills сохраняют сгенерированный selection guidance, допускающий nearest-root fallback. Текущие archive instructions также позволяют owner-confirmed archive с incomplete artifacts или tasks.
|
||||||
|
|
||||||
|
`docs/development/audit-remediation.md` является durable evidence, а не вторым SDD store. `references/**` содержит импортированные framework plans и должен остаться нетронутым. Archive `2026-08-17-redesign-position-cards` имеет два unchecked lifecycle tasks, поэтому он является historical evidence, противоречащим целевой policy.
|
||||||
|
|
||||||
|
## Цели и нецели
|
||||||
|
|
||||||
|
**Цели:**
|
||||||
|
|
||||||
|
- Сделать каждую supported OpenSpec operation детерминированной из любого project-owned entrypoint.
|
||||||
|
- Сохранить единственный versioned SDD authority, оставив `docs` durable documentation и evidence.
|
||||||
|
- Превратить authority и archive rules в read-only, воспроизводимый verification result.
|
||||||
|
- Убрать incomplete-task исключение из archive и честно согласовать известное historical exception.
|
||||||
|
|
||||||
|
**Не входит в scope:**
|
||||||
|
|
||||||
|
- Не изменять OpenSpec CLI, глобальную OpenSpec configuration или несвязанные registered stores.
|
||||||
|
- Не удалять, не перемещать и не нормализовать artifacts под `references/**`.
|
||||||
|
- Не вводить Superpowers plans, другой planning framework, CI, runtime application changes или external tracker integration.
|
||||||
|
- Не переписывать прошлые Git commits и не утверждать, что historical lifecycle steps произошли в другую дату.
|
||||||
|
|
||||||
|
## Решения
|
||||||
|
|
||||||
|
### Canonical store contract заменяет contextual selection
|
||||||
|
|
||||||
|
`wealth-ledger-specs` — фиксированный идентификатор store, а `specs/openspec` — его единственный project-owned artifact root. Root, frontend, backend, specs и docs `AGENTS.md` используют одну краткую policy: requirements, design, delta specs, tasks, changes и archives принадлежат только этому store; все OpenSpec commands, читающие или изменяющие change, используют `--store wealth-ledger-specs`.
|
||||||
|
|
||||||
|
Восемь `.opencode/commands/opsx-*.md` и восемь `.opencode/skills/openspec-*/SKILL.md` заменят сгенерированные conditional store-selection blocks на блок для WealthLedger. Каждый конкретный OpenSpec invocation в этих project-owned workflows включает фиксированный flag; archive workflow использует тот же fixed selection. `references/**` исключается, поскольку не является project-owned workflow surface.
|
||||||
|
|
||||||
|
Сохранение существующих entrypoints не ломает discovery агентов и имена workflows. Опора на `openspec` root pointer или global default отклонена, поскольку они зависят от текущей директории или состояния машины. Удаление entrypoints отклонено, поскольку это ослабит, а не усилит документированный локальный workflow.
|
||||||
|
|
||||||
|
### Границы artifacts определяются их lifecycle role
|
||||||
|
|
||||||
|
Policy различает SDD state и durable documentation:
|
||||||
|
|
||||||
|
- `specs/openspec` владеет mutable и archived versioned SDD state: specs, changes, proposals, designs, delta specs и tasks.
|
||||||
|
- `docs` владеет durable architecture, development, feature, audit и remediation documentation, включая completion evidence со ссылкой на archive.
|
||||||
|
- `frontend` и `backend` владеют runtime code и tests; change planning artifacts в них не создаются.
|
||||||
|
- `references/**` остаётся read-only и исключён из cleanup и policy scanning.
|
||||||
|
|
||||||
|
Instructions запретят коммит framework-specific planning/spec/task/design artifacts вне canonical store, явно включая `superpowers/plans`. Запрет относится к параллельным sources of truth, а не к использованию инструмента или временным заметкам в разговоре. Полный запрет любого Markdown вне `specs` отклонён, поскольку он ошибочно запретит durable docs и существующий reference content.
|
||||||
|
|
||||||
|
### Repository-local verifier проверяет стабильные policy signals
|
||||||
|
|
||||||
|
Change добавит POSIX shell verifier в репозитории `specs` и документированную command, работающую из любого workspace cwd. Script определяет workspace по собственному расположению, не делает writes и сообщает о каждом нарушенном инварианте перед возвратом ненулевого результата.
|
||||||
|
|
||||||
|
Он проверит metadata зарегистрированного store и canonical path `specs/openspec`; отсутствие любого дополнительного project-owned `openspec/` directory; явное canonical-store wording и flag в root и четырёх repository `AGENTS.md`; а также compliance фиксированного набора из шестнадцати `.opencode` entrypoint documents. Он отклонит сгенерированные формулировки nearest-root/global-default и известные framework planning locations вне `specs/openspec`, исключая `references/**`, `.git`, dependencies и generated outputs из discovery.
|
||||||
|
|
||||||
|
Verifier намеренно является structural guardrail, а не general natural-language classifier для каждого возможного будущего framework. Policy text запрещает все parallel framework artifacts; verifier защищает known paths и entrypoints, которые могут воспроизвести audited failure. Широкое сканирование всего Markdown или всех directories с именем `plan` отклонено, поскольку оно создаст false positives в durable docs и reference material.
|
||||||
|
|
||||||
|
### Archive становится hard gate, а evidence фиксируется post-archive, не в task
|
||||||
|
|
||||||
|
Project-owned archive command и skill остановятся до sync или move change, если любой required planning artifact незавершён, если отсутствует `tasks.md` или если он содержит `- [ ]`. Owner-confirmation override отсутствует. До archive workflow также требует normal verification evidence; после archive он указывает implementer обновить durable registry/history evidence и выполнить commits затронутых repositories.
|
||||||
|
|
||||||
|
Post-archive work не представляется checkbox в change, потому что archive path нельзя фактически подтвердить до успешного move. Registry/history entry фиксирует actual archive path, commit IDs, commands и observed results после этого события. Это жертвует atomic cross-repository bookkeeping, но не позволяет archived change заявлять о completed tasks при известной incomplete work. Archive workflow, автоматически отмечающий произвольную работу, отклонён, поскольку он производил бы вымышленное evidence.
|
||||||
|
|
||||||
|
### Historical reconciliation фиксирует current evidence без изменения history
|
||||||
|
|
||||||
|
Historical archive `2026-08-17-redesign-position-cards` будет согласован на месте только после того, как read-only evidence установит actual archive path и commits затронутых repositories. Его две lifecycle tasks будут отмечены complete рядом с dated reconciliation note, отличающей original archive от текущей evidence review. Не изменяются implementation files, delta specs, archive date или past commits.
|
||||||
|
|
||||||
|
Оставить его без изменений отклонено, поскольку он останется контрпримером policy. Воссоздать change или изменить Git history отклонено, поскольку это скроет фактическую временную линию.
|
||||||
|
|
||||||
|
## Риски и компромиссы
|
||||||
|
|
||||||
|
- [Будущая OpenSpec command не содержит fixed store flag] → verifier использует фиксированный manifest всех шестнадцати текущих entrypoints и должен расширяться в том же change, который добавляет entrypoint.
|
||||||
|
- [Новый framework artifact не распознан path-based detection] → instructions задают широкое ограничение, а review и known-location checks verifier дают многоуровневую защиту без false-positive scanning durable docs.
|
||||||
|
- [Post-archive registry update прервано] → finding остаётся non-terminal, пока его durable evidence не заполнено; в archive не скрывается incomplete task.
|
||||||
|
- [Historical commits невозможно доказать из local history] → tasks остаются unresolved, а недостающее evidence фиксируется вместо ложного утверждения о complete.
|
||||||
|
- [Пользователь вручную запускает raw unscoped OpenSpec CLI] → supported commands и instructions остаются scoped; policy не изменяет внешнее поведение CLI.
|
||||||
|
|
||||||
|
## План миграции
|
||||||
|
|
||||||
|
1. Добавить формулировки canonical authority и artifact boundaries во все project-owned `AGENTS.md`, затем hard-bind шестнадцать `.opencode` entrypoints.
|
||||||
|
2. Добавить read-only verifier и запустить его из workspace и каждого independent repository context.
|
||||||
|
3. Заменить archive confirmation branches для incomplete artifacts/tasks на hard failures, потребовать `tasks.md` и задокументировать post-archive evidence sequence.
|
||||||
|
4. Добавить durable documentation, объясняющую authority/lifecycle contract, и обновить remediation registry: WL-P1-03 и WL-P1-04 получают статус `active` на время change.
|
||||||
|
5. Согласовать historical archive только по observed Git/OpenSpec evidence; если evidence неполно, не отмечать его tasks complete.
|
||||||
|
6. Проверить completed change, sync delta specs, архивировать его только при отмеченных tasks, затем добавить actual archive/commit/check evidence в registry и history.
|
||||||
|
|
||||||
|
Откат ограничен revert commits, добавляющими policy и instructions. Runtime data, API contract, package dependency или external configuration не мигрируются.
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Технический аудит подтвердил, что выбор OpenSpec store зависит от текущей директории и изменяемого глобального значения по умолчанию, а archive workflow допускает незакрытые tasks. Это создаёт два источника правды о SDD-работе и позволяет считать change завершённым без полного доказательства выполнения.
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Объявить `wealth-ledger-specs` с физическим root `specs/openspec` единственным поддерживаемым местом для versioned SDD-артефактов WealthLedger.
|
||||||
|
- Обязать project-owned OpenSpec entrypoints и agent instructions явно использовать `--store wealth-ledger-specs`; удалить поддержку выбора ближайшего root или fallback через глобальное значение по умолчанию.
|
||||||
|
- Запретить создание и коммит framework-specific planning/spec/task/design артефактов вне `specs/openspec`, включая `superpowers/plans`; сохранить `references/**` как read-only исключение.
|
||||||
|
- Разделить SDD-состояние и постоянную документацию: `docs` хранит только долговечную документацию и evidence, но не change-specific requirements, design или tasks.
|
||||||
|
- Сделать archive невозможным при любом незакрытом task и вынести post-archive bookkeeping из `tasks.md` в детерминированный evidence workflow.
|
||||||
|
- Добавить read-only verifier authority/lifecycle policy и исправить historical incomplete archive `2026-08-17-redesign-position-cards` проверяемыми фактами без переписывания Git-истории.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
|
||||||
|
- `openspec-authority-and-lifecycle`: canonical store, допустимые locations SDD-артефактов, обязательный scoped entrypoint, archive gate и machine-verifiable policy.
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
|
||||||
|
- `project-foundation`: локальные agent instructions должны однозначно направлять SDD-работу в canonical OpenSpec store и исключать параллельные framework artifacts.
|
||||||
|
- `audit-remediation-workflow`: terminal evidence audit-derived changes должно опираться на archive только после завершения всех tasks и определённого post-archive evidence workflow.
|
||||||
|
- `project-documentation`: durable docs отделяются от change-specific SDD-artifacts и фиксируют completion evidence без создания второго SDD source of truth.
|
||||||
|
- `brokerage-account-ledger`: русские нормативные формулировки используют RFC 2119 маркеры, совместимые со strict OpenSpec validation.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
Затрагиваются `AGENTS.md` в workspace и независимых репозиториях, `.opencode` OpenSpec commands/skills, `specs/openspec` configuration и verification tooling, historical archive и durable development documentation. Runtime-код frontend/backend, API, зависимости и пользовательское поведение не меняются.
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: Terminal status подтверждён проверяемым evidence
|
||||||
|
Registry SHALL NOT представлять finding как `done` без даты, archive path связанного OpenSpec change, commit identifiers для каждого затронутого Git-репозитория и точных non-mutating verification commands с результатами. Архивированный audit-derived change MUST иметь все tasks завершёнными до archive; completion evidence после archive MUST быть отдельной записью registry или history, а не незакрытым task в archived change. Статусы `deferred` и `accepted` MUST содержать дату, rationale и условие пересмотра либо ссылку на явное решение владельца.
|
||||||
|
|
||||||
|
#### Scenario: Change готовится к завершению
|
||||||
|
- **WHEN** implementer хочет поставить связанный finding в `done`
|
||||||
|
- **THEN** все tasks change и требуемая OpenSpec verification завершены до archive, а registry содержит полный набор post-archive evidence
|
||||||
|
|
||||||
|
#### Scenario: Риск сознательно не исправляется сейчас
|
||||||
|
- **WHEN** владелец переносит finding или принимает риск
|
||||||
|
- **THEN** registry сохраняет причину решения и условия, при которых оно должно быть пересмотрено
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: User can retrieve an account ledger
|
||||||
|
Система MUST предоставлять аутентифицированный журнал только для чтения одного Brokerage Account, принадлежащего текущему User. Журнал MUST содержать только исполненные операции T-Bank и при отсутствии периода по умолчанию охватывать интервал от начала текущего календарного года до момента запроса.
|
||||||
|
|
||||||
|
#### Scenario: Получение журнала с периодом по умолчанию
|
||||||
|
- **WHEN** аутентифицированный User запрашивает журнал принадлежащего ему Brokerage Account без периода
|
||||||
|
- **THEN** система возвращает его исполненные операции от начала текущего календарного года до момента запроса
|
||||||
|
|
||||||
|
#### Scenario: Отклонение недоступного счёта
|
||||||
|
- **WHEN** аутентифицированный User запрашивает журнал счёта, который не является открытым поддерживаемым счётом, доступным через его T-Bank connection
|
||||||
|
- **THEN** система возвращает существующий ответ о недоступности счёта и не раскрывает операции
|
||||||
|
|
||||||
|
### Requirement: User can browse a filtered ledger
|
||||||
|
Система MUST позволять User ограничивать журнал включительным периодом дат и любым подмножеством категорий trade, income, tax, fee, transfer, other. Система MUST разбивать упорядоченный результат на страницы с непрозрачным cursor и возвращать признак доступности следующей страницы.
|
||||||
|
|
||||||
|
#### Scenario: Фильтрация доходных операций за период
|
||||||
|
- **WHEN** User запрашивает период дат и категорию income
|
||||||
|
- **THEN** результат содержит только исполненные доходные операции с датой в пределах этого периода
|
||||||
|
|
||||||
|
#### Scenario: Продолжение истории
|
||||||
|
- **WHEN** User запрашивает cursor следующей страницы, возвращённый предыдущим ответом журнала
|
||||||
|
- **THEN** система возвращает следующую страницу без повторения записей предыдущей страницы
|
||||||
|
|
||||||
|
### Requirement: Ledger entries preserve broker operation meaning
|
||||||
|
Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.
|
||||||
|
|
||||||
|
#### Scenario: Отображение купонной выплаты
|
||||||
|
- **WHEN** T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
|
||||||
|
- **THEN** запись журнала определяет её как income и передаёт исходную сумму выплаты, валюту и данные инструмента
|
||||||
|
|
||||||
|
#### Scenario: Отображение комиссии сделки без синтетической записи
|
||||||
|
- **WHEN** T-Bank возвращает исполненную сделку, содержащую выплату и комиссию
|
||||||
|
- **THEN** журнал содержит одну запись сделки с комиссией в качестве её детали
|
||||||
|
|
||||||
|
#### Scenario: Отображение движения бумаг без денег
|
||||||
|
- **WHEN** T-Bank возвращает исполненную операцию, изменяющую состав инструментов, но без денежной выплаты
|
||||||
|
- **THEN** запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением
|
||||||
|
|
||||||
|
### Requirement: Account overview includes recent ledger events
|
||||||
|
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||||
|
|
||||||
|
#### Scenario: Отображение последних событий
|
||||||
|
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
||||||
|
- **THEN** обзор показывает не более пяти последних записей и ссылку на полный журнал
|
||||||
|
|
||||||
|
#### Scenario: Последние записи недоступны
|
||||||
|
- **WHEN** обзор счёта успешно загружается, но запрос последних записей завершается ошибкой
|
||||||
|
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
||||||
|
|
||||||
|
### Requirement: Full ledger presents compact rows
|
||||||
|
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте. Она MUST обозначать записи без движения денег и MUST NOT показывать цену или количество.
|
||||||
|
|
||||||
|
#### Scenario: Отображение записи только с инструментом
|
||||||
|
- **WHEN** полный журнал отображает запись без денежной выплаты
|
||||||
|
- **THEN** страница определяет её как запись без движения денег
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
## Purpose
|
||||||
|
|
||||||
|
Определяет единственный источник полномочий для OpenSpec и проверяемый жизненный цикл SDD-изменений независимо от текущей директории, глобальной конфигурации или agent framework.
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Канонический authority OpenSpec задан явно
|
||||||
|
WealthLedger SHALL использовать зарегистрированный store `wealth-ledger-specs` с физическим OpenSpec root `specs/openspec` как единственный поддерживаемый authority для versioned SDD artifacts. Каждый project-owned OpenSpec entrypoint и documented OpenSpec command MUST явно выбирать `--store wealth-ledger-specs`; он MUST NOT выбирать store из ближайшего root, текущей директории или глобального значения по умолчанию машины.
|
||||||
|
|
||||||
|
#### Scenario: Агент начинает SDD-работу из репозитория приложения
|
||||||
|
- **WHEN** агент начинает, продолжает, проверяет, синхронизирует или архивирует OpenSpec change из `frontend`, `backend`, `docs` или workspace root
|
||||||
|
- **THEN** documented workflow явно выбирает `wealth-ledger-specs` и разрешает artifacts под `specs/openspec`
|
||||||
|
|
||||||
|
#### Scenario: В окружении есть другой OpenSpec store или значение по умолчанию
|
||||||
|
- **WHEN** машина имеет другой зарегистрированный OpenSpec store или другое глобальное значение по умолчанию
|
||||||
|
- **THEN** project-owned entrypoints всё равно используют `wealth-ledger-specs` и не выполняют fallback к другому root
|
||||||
|
|
||||||
|
### Requirement: Versioned planning artifacts имеют единственное допустимое расположение
|
||||||
|
Система SHALL хранить committed OpenSpec specifications, changes, designs, delta specifications, tasks и archives только под `specs/openspec`. Она MUST NOT создавать или коммитить framework-specific planning, specification, task или design artifacts вне этого расположения, включая `superpowers/plans`. Это ограничение MUST NOT изменять или удалять read-only material под `references/**`.
|
||||||
|
|
||||||
|
#### Scenario: Агент фиксирует функциональное изменение
|
||||||
|
- **WHEN** агенту нужно зафиксировать requirements, design decisions или implementation tasks для функционального change
|
||||||
|
- **THEN** он создаёт versioned SDD artifacts в canonical OpenSpec store и не создаёт parallel framework artifact вне него
|
||||||
|
|
||||||
|
#### Scenario: Агент изучает reference material
|
||||||
|
- **WHEN** агент встречает framework artifacts под `references/**`
|
||||||
|
- **THEN** он рассматривает их как read-only reference content и не классифицирует их как нарушение policy
|
||||||
|
|
||||||
|
### Requirement: Authority policy имеет read-only verifier
|
||||||
|
Canonical store и policy расположения artifacts SHALL иметь documented read-only verifier. Verifier MUST возвращать ненулевой результат, когда project-owned OpenSpec entrypoint не выбирает canonical store, когда запрещённый project-owned planning artifact существует вне `specs/openspec`, или когда существует дополнительный project-owned `openspec/` root; он MUST исключать `references/**` из проверок расположения artifacts.
|
||||||
|
|
||||||
|
#### Scenario: Canonical authority остаётся целостным
|
||||||
|
- **WHEN** verifier запускается в compliant workspace
|
||||||
|
- **THEN** он завершается без изменения tracked files и сообщает об успехе
|
||||||
|
|
||||||
|
#### Scenario: Entry point вновь допускает неявный выбор store
|
||||||
|
- **WHEN** project-owned OpenSpec entrypoint допускает выбор nearest-root или global-default
|
||||||
|
- **THEN** verifier завершается ошибкой и указывает non-compliant entrypoint
|
||||||
|
|
||||||
|
### Requirement: Archive блокируется незавершёнными tasks
|
||||||
|
Project-owned archive workflow MUST отклонять archive, пока его `tasks.md` содержит любой unchecked task. Post-archive bookkeeping MUST NOT появляться как unchecked task; он SHALL фиксироваться через детерминированное completion evidence после успешного archive.
|
||||||
|
|
||||||
|
#### Scenario: Change имеет unchecked task
|
||||||
|
- **WHEN** implementer запрашивает archive и остаётся хотя бы один unchecked task
|
||||||
|
- **THEN** workflow не архивирует change и сообщает incomplete tasks как blocking condition
|
||||||
|
|
||||||
|
#### Scenario: Change завершил все tasks
|
||||||
|
- **WHEN** каждый task отмечен и required verification успешно завершена
|
||||||
|
- **THEN** workflow допускает archive и фиксирует его результат через определённый completion-evidence path без создания post-archive task
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Durable documentation is not a parallel SDD store
|
||||||
|
Репозиторий `docs` SHALL хранить только долговечную architecture, development, feature, audit и remediation documentation вместе с completion evidence. Change-specific requirements, designs, delta specifications и tasks MUST храниться только в canonical OpenSpec store и MUST NOT создаваться как framework-specific planning artifacts в `docs`.
|
||||||
|
|
||||||
|
#### Scenario: Change требует постоянной документации
|
||||||
|
- **WHEN** завершённый change должен оставить устойчивое объяснение решения или evidence
|
||||||
|
- **THEN** documentation фиксирует реализованное решение или completion evidence и ссылается на canonical OpenSpec change без дублирования его requirements, design или tasks
|
||||||
|
|
||||||
|
#### Scenario: Agent планирует незавершённый change
|
||||||
|
- **WHEN** агент создаёт requirements, design или tasks для незавершённого изменения
|
||||||
|
- **THEN** он сохраняет их под `specs/openspec` и не создаёт framework-specific planning document в `docs`
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: Репозитории содержат локальные инструкции для AI-агентов
|
||||||
|
Система SHALL содержать обзорный `AGENTS.md` в корне рабочей области и отдельный `AGENTS.md` в репозиториях frontend, backend, specs и docs. Инструкции MUST описывать назначение области, локальные команды проверки, границы ответственности и связь с SDD-артефактами. Каждая инструкция MUST объявлять `wealth-ledger-specs` и `specs/openspec` как canonical OpenSpec authority, требовать явный `--store wealth-ledger-specs` для поддерживаемых OpenSpec операций и запрещать versioned framework-specific planning artifacts вне canonical store. Локальные инструкции MUST направлять агента к durable remediation registry, когда задача связана с findings технического аудита.
|
||||||
|
|
||||||
|
#### Scenario: Агент начинает работу в отдельном репозитории
|
||||||
|
- **WHEN** агент открывает любой из репозиториев frontend, backend, specs или docs
|
||||||
|
- **THEN** он может определить локальные правила работы, canonical OpenSpec authority и источник связанных спецификаций из `AGENTS.md` этого репозитория
|
||||||
|
|
||||||
|
#### Scenario: Агент получает audit-derived задачу из отдельного репозитория
|
||||||
|
- **WHEN** задача ссылается на finding технического аудита
|
||||||
|
- **THEN** локальный `AGENTS.md` указывает на remediation registry и canonical OpenSpec workflow с явным store selection до начала изменения кода
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
## 1. Canonical OpenSpec authority
|
||||||
|
|
||||||
|
- [x] 1.1 Обновить корневой `AGENTS.md` и `frontend/AGENTS.md`, `backend/AGENTS.md`, `specs/AGENTS.md`, `docs/AGENTS.md`: объявить `wealth-ledger-specs`/`specs/openspec` единственным SDD store, потребовать `--store wealth-ledger-specs`, запретить versioned framework-specific planning artifacts вне store и сохранить исключение `references/**`.
|
||||||
|
- [x] 1.2 В каждом из восьми `.opencode/commands/opsx-*.md` и восьми `.opencode/skills/openspec-*/SKILL.md` заменить conditional store-selection guidance на fixed `wealth-ledger-specs`; все OpenSpec commands, читающие или изменяющие change, должны содержать `--store wealth-ledger-specs` и не должны допускать nearest-root/global-default fallback.
|
||||||
|
- [x] 1.3 Изменить `.opencode/commands/opsx-archive.md` и `.opencode/skills/openspec-archive-change/SKILL.md`: блокировать archive без подтверждающего обхода, если отсутствует `tasks.md`, любой planning artifact не `done`/`skipped` или в tasks есть `- [ ]`; описать post-archive evidence и commits как действие после archive, не как task change.
|
||||||
|
|
||||||
|
## 2. Read-only authority verifier
|
||||||
|
|
||||||
|
- [x] 2.1 Создать `specs/scripts/verify-openspec-authority.sh`, который по собственному расположению определяет workspace, не делает writes и проверяет `specs/.openspec-store/store.yaml`, единственный project-owned `specs/openspec`, пять `AGENTS.md`, все шестнадцать `.opencode` entrypoints, отсутствие generated fallback wording и известных framework planning locations вне store; исключить `references/**`, `.git`, dependencies и generated outputs.
|
||||||
|
- [x] 2.2 Добавить в verifier понятные сообщения для каждого нарушенного инварианта и ненулевой exit status; success path должен сообщать проверенное canonical authority без изменения tracked files.
|
||||||
|
- [x] 2.3 Добавить в `specs/AGENTS.md` documented command verifier и выполнить read-only проверки success path, дополнительного `openspec/` root, неявного entrypoint и запрещённого planning location на временных fixtures, не изменяя project-owned tracked files.
|
||||||
|
|
||||||
|
## 3. Durable documentation и remediation state
|
||||||
|
|
||||||
|
- [x] 3.1 Создать в `docs/development` краткую durable documentation authority/lifecycle contract: границы `specs/openspec`, `docs`, application repos и `references/**`; объяснить, что requirements, design и tasks не дублируются вне canonical store.
|
||||||
|
- [x] 3.2 Добавить документ в `docs/development/README.md` и убедиться, что он ссылается на canonical OpenSpec store, а не создаёт второй change-specific SDD artifact.
|
||||||
|
- [x] 3.3 Обновить `docs/development/audit-remediation.md`: сделать `harden-openspec-authority-and-lifecycle` active change для WL-P1-03/WL-P1-04 и убрать его из формулировки «ещё не создан», не помечая findings как `done` до фактического archive evidence.
|
||||||
|
|
||||||
|
## 4. Historical archive reconciliation
|
||||||
|
|
||||||
|
- [x] 4.1 Собрать read-only evidence из OpenSpec archive и Git history specs, docs, backend и frontend для `2026-08-17-redesign-position-cards`; установить фактические archive path и commits либо документировать недостающий факт.
|
||||||
|
- [x] 4.2 Только если evidence подтверждено, отметить tasks 6.2 и 6.3 archived change как complete и добавить dated reconciliation note с exact commands, observed results и различием между исходным archive и текущей проверкой; не менять implementation files, delta specs, archive date или историю Git.
|
||||||
|
|
||||||
|
## 5. Pre-archive verification
|
||||||
|
|
||||||
|
- [x] 5.1 Запустить authority verifier из workspace root и из `frontend`, `backend`, `specs` и `docs`; зафиксировать в change точные команды и observed results для дальнейшего completion evidence.
|
||||||
|
- [x] 5.2 Нормализовать RFC 2119 маркеры в `brokerage-account-ledger` через delta-spec без изменения требований или сценариев; выполнить `openspec validate harden-openspec-authority-and-lifecycle --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs` и `git diff --check` в каждом затронутом Git repository; устранить все blocking results.
|
||||||
|
- [x] 5.3 Выполнить независимый read-only review delta specs, policy boundaries, archive gate, verifier exclusions и historical reconciliation; подтвердить, что tasks не содержат post-archive bookkeeping или commit/registry-completion checkbox.
|
||||||
|
|
||||||
|
## Pre-archive verification evidence — 2026-08-23
|
||||||
|
|
||||||
|
- `bash specs/scripts/verify-openspec-authority.sh` из workspace root — `OpenSpec authority verified: wealth-ledger-specs at specs/openspec`.
|
||||||
|
- `cd frontend && bash ../specs/scripts/verify-openspec-authority.sh` — success с тем же результатом.
|
||||||
|
- `cd backend && bash ../specs/scripts/verify-openspec-authority.sh` — success с тем же результатом.
|
||||||
|
- `cd specs && bash scripts/verify-openspec-authority.sh` — success с тем же результатом.
|
||||||
|
- `cd docs && bash ../specs/scripts/verify-openspec-authority.sh` — success с тем же результатом.
|
||||||
|
- `bash specs/scripts/verify-openspec-authority.test.sh` — success; fixture подтверждает success path, дополнительный project-owned OpenSpec root, неявный store selection (включая вызов в скобках), conditional `--store "<id>"`, archive override wording, запрещённый `docs/superpowers/plans` и исключение `references/**`.
|
||||||
|
- `openspec validate harden-openspec-authority-and-lifecycle --type change --strict --store wealth-ledger-specs` — `Change 'harden-openspec-authority-and-lifecycle' is valid`.
|
||||||
|
- Первый запуск `openspec validate --specs --strict --store wealth-ledger-specs` выявил baseline `brokerage-account-ledger`: strict validator требует RFC 2119 `SHALL` или `MUST`, тогда как main spec использовала русское «ДОЛЖНА». По явному решению владельца change получил delta-spec, нормализующий только маркеры без изменения requirements или scenarios.
|
||||||
|
- Повторный `openspec validate --specs --strict --store wealth-ledger-specs` — 14 passed, 0 failed.
|
||||||
|
- `git diff --check` в frontend, backend, specs и docs — exit 0.
|
||||||
|
- Независимый read-only review 2026-08-23 — Critical/Important findings отсутствуют; проверены все 16 `.opencode` entrypoints, hard archive gate, exclusions verifier и historical reconciliation.
|
||||||
@@ -29,11 +29,11 @@
|
|||||||
- **THEN** агент продолжает связанный change и не создаёт второй remediation change без явного решения владельца
|
- **THEN** агент продолжает связанный change и не создаёт второй remediation change без явного решения владельца
|
||||||
|
|
||||||
### Requirement: Terminal status подтверждён проверяемым evidence
|
### Requirement: Terminal status подтверждён проверяемым evidence
|
||||||
Registry SHALL NOT представлять finding как `done` без даты, archive path связанного OpenSpec change, commit identifiers для каждого затронутого Git-репозитория и точных non-mutating verification commands с результатами. Статусы `deferred` и `accepted` MUST содержать дату, rationale и условие пересмотра либо ссылку на явное решение владельца.
|
Registry SHALL NOT представлять finding как `done` без даты, archive path связанного OpenSpec change, commit identifiers для каждого затронутого Git-репозитория и точных non-mutating verification commands с результатами. Архивированный audit-derived change MUST иметь все tasks завершёнными до archive; completion evidence после archive MUST быть отдельной записью registry или history, а не незакрытым task в archived change. Статусы `deferred` и `accepted` MUST содержать дату, rationale и условие пересмотра либо ссылку на явное решение владельца.
|
||||||
|
|
||||||
#### Scenario: Change готовится к завершению
|
#### Scenario: Change готовится к завершению
|
||||||
- **WHEN** implementer хочет поставить связанный finding в `done`
|
- **WHEN** implementer хочет поставить связанный finding в `done`
|
||||||
- **THEN** registry содержит полный набор evidence, а tasks change и требуемая OpenSpec verification завершены до обновления статуса
|
- **THEN** все tasks change и требуемая OpenSpec verification завершены до archive, а registry содержит полный набор post-archive evidence
|
||||||
|
|
||||||
#### Scenario: Риск сознательно не исправляется сейчас
|
#### Scenario: Риск сознательно не исправляется сейчас
|
||||||
- **WHEN** владелец переносит finding или принимает риск
|
- **WHEN** владелец переносит finding или принимает риск
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
### Requirement: User can retrieve an account ledger
|
### Requirement: User can retrieve an account ledger
|
||||||
Система ДОЛЖНА предоставлять аутентифицированный журнал только для чтения одного Brokerage Account, принадлежащего текущему User. Журнал ДОЛЖЕН содержать только исполненные операции T-Bank и при отсутствии периода по умолчанию охватывать интервал от начала текущего календарного года до момента запроса.
|
Система MUST предоставлять аутентифицированный журнал только для чтения одного Brokerage Account, принадлежащего текущему User. Журнал MUST содержать только исполненные операции T-Bank и при отсутствии периода по умолчанию охватывать интервал от начала текущего календарного года до момента запроса.
|
||||||
|
|
||||||
#### Scenario: Получение журнала с периодом по умолчанию
|
#### Scenario: Получение журнала с периодом по умолчанию
|
||||||
- **WHEN** аутентифицированный User запрашивает журнал принадлежащего ему Brokerage Account без периода
|
- **WHEN** аутентифицированный User запрашивает журнал принадлежащего ему Brokerage Account без периода
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
- **THEN** система возвращает существующий ответ о недоступности счёта и не раскрывает операции
|
- **THEN** система возвращает существующий ответ о недоступности счёта и не раскрывает операции
|
||||||
|
|
||||||
### Requirement: User can browse a filtered ledger
|
### Requirement: User can browse a filtered ledger
|
||||||
Система ДОЛЖНА позволять User ограничивать журнал включительным периодом дат и любым подмножеством категорий trade, income, tax, fee, transfer, other. Система ДОЛЖНА разбивать упорядоченный результат на страницы с непрозрачным cursor и возвращать признак доступности следующей страницы.
|
Система MUST позволять User ограничивать журнал включительным периодом дат и любым подмножеством категорий trade, income, tax, fee, transfer, other. Система MUST разбивать упорядоченный результат на страницы с непрозрачным cursor и возвращать признак доступности следующей страницы.
|
||||||
|
|
||||||
#### Scenario: Фильтрация доходных операций за период
|
#### Scenario: Фильтрация доходных операций за период
|
||||||
- **WHEN** User запрашивает период дат и категорию income
|
- **WHEN** User запрашивает период дат и категорию income
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
- **THEN** система возвращает следующую страницу без повторения записей предыдущей страницы
|
- **THEN** система возвращает следующую страницу без повторения записей предыдущей страницы
|
||||||
|
|
||||||
### Requirement: Ledger entries preserve broker operation meaning
|
### Requirement: Ledger entries preserve broker operation meaning
|
||||||
Система ДОЛЖНА представлять одну upstream-операцию одной записью журнала и ДОЛЖНА передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля ДОЛЖНЫ сохранять исходную валюту и точное десятичное значение.
|
Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.
|
||||||
|
|
||||||
#### Scenario: Отображение купонной выплаты
|
#### Scenario: Отображение купонной выплаты
|
||||||
- **WHEN** T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
|
- **WHEN** T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
- **THEN** запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением
|
- **THEN** запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением
|
||||||
|
|
||||||
### Requirement: Account overview includes recent ledger events
|
### Requirement: Account overview includes recent ledger events
|
||||||
Обзор счёта ДОЛЖЕН показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Неуспешный или пустой запрос последних записей ДОЛЖЕН оставаться локальным состоянием блока последних событий и НЕ ДОЛЖЕН заменять успешно отображённый обзор Portfolio.
|
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||||
|
|
||||||
#### Scenario: Отображение последних событий
|
#### Scenario: Отображение последних событий
|
||||||
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
||||||
|
|
||||||
### Requirement: Full ledger presents compact rows
|
### Requirement: Full ledger presents compact rows
|
||||||
Страница полного журнала ДОЛЖНА показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте. Она ДОЛЖНА обозначать записи без движения денег и НЕ ДОЛЖНА показывать цену или количество.
|
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте. Она MUST обозначать записи без движения денег и MUST NOT показывать цену или количество.
|
||||||
|
|
||||||
#### Scenario: Отображение записи только с инструментом
|
#### Scenario: Отображение записи только с инструментом
|
||||||
- **WHEN** полный журнал отображает запись без денежной выплаты
|
- **WHEN** полный журнал отображает запись без денежной выплаты
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# openspec-authority-and-lifecycle Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Определяет единственный источник полномочий для OpenSpec и проверяемый жизненный цикл SDD-изменений независимо от текущей директории, глобальной конфигурации или agent framework.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Канонический authority OpenSpec задан явно
|
||||||
|
WealthLedger SHALL использовать зарегистрированный store `wealth-ledger-specs` с физическим OpenSpec root `specs/openspec` как единственный поддерживаемый authority для versioned SDD artifacts. Каждый project-owned OpenSpec entrypoint и documented OpenSpec command MUST явно выбирать `--store wealth-ledger-specs`; он MUST NOT выбирать store из ближайшего root, текущей директории или глобального значения по умолчанию машины.
|
||||||
|
|
||||||
|
#### Scenario: Агент начинает SDD-работу из репозитория приложения
|
||||||
|
- **WHEN** агент начинает, продолжает, проверяет, синхронизирует или архивирует OpenSpec change из `frontend`, `backend`, `docs` или workspace root
|
||||||
|
- **THEN** documented workflow явно выбирает `wealth-ledger-specs` и разрешает artifacts под `specs/openspec`
|
||||||
|
|
||||||
|
#### Scenario: В окружении есть другой OpenSpec store или значение по умолчанию
|
||||||
|
- **WHEN** машина имеет другой зарегистрированный OpenSpec store или другое глобальное значение по умолчанию
|
||||||
|
- **THEN** project-owned entrypoints всё равно используют `wealth-ledger-specs` и не выполняют fallback к другому root
|
||||||
|
|
||||||
|
### Requirement: Versioned planning artifacts имеют единственное допустимое расположение
|
||||||
|
Система SHALL хранить committed OpenSpec specifications, changes, designs, delta specifications, tasks и archives только под `specs/openspec`. Она MUST NOT создавать или коммитить framework-specific planning, specification, task или design artifacts вне этого расположения, включая `superpowers/plans`. Это ограничение MUST NOT изменять или удалять read-only material под `references/**`.
|
||||||
|
|
||||||
|
#### Scenario: Агент фиксирует функциональное изменение
|
||||||
|
- **WHEN** агенту нужно зафиксировать requirements, design decisions или implementation tasks для функционального change
|
||||||
|
- **THEN** он создаёт versioned SDD artifacts в canonical OpenSpec store и не создаёт parallel framework artifact вне него
|
||||||
|
|
||||||
|
#### Scenario: Агент изучает reference material
|
||||||
|
- **WHEN** агент встречает framework artifacts под `references/**`
|
||||||
|
- **THEN** он рассматривает их как read-only reference content и не классифицирует их как нарушение policy
|
||||||
|
|
||||||
|
### Requirement: Authority policy имеет read-only verifier
|
||||||
|
Canonical store и policy расположения artifacts SHALL иметь documented read-only verifier. Verifier MUST возвращать ненулевой результат, когда project-owned OpenSpec entrypoint не выбирает canonical store, когда запрещённый project-owned planning artifact существует вне `specs/openspec`, или когда существует дополнительный project-owned `openspec/` root; он MUST исключать `references/**` из проверок расположения artifacts.
|
||||||
|
|
||||||
|
#### Scenario: Canonical authority остаётся целостным
|
||||||
|
- **WHEN** verifier запускается в compliant workspace
|
||||||
|
- **THEN** он завершается без изменения tracked files и сообщает об успехе
|
||||||
|
|
||||||
|
#### Scenario: Entry point вновь допускает неявный выбор store
|
||||||
|
- **WHEN** project-owned OpenSpec entrypoint допускает выбор nearest-root или global-default
|
||||||
|
- **THEN** verifier завершается ошибкой и указывает non-compliant entrypoint
|
||||||
|
|
||||||
|
### Requirement: Archive блокируется незавершёнными tasks
|
||||||
|
Project-owned archive workflow MUST отклонять archive, пока его `tasks.md` содержит любой unchecked task. Post-archive bookkeeping MUST NOT появляться как unchecked task; он SHALL фиксироваться через детерминированное completion evidence после успешного archive.
|
||||||
|
|
||||||
|
#### Scenario: Change имеет unchecked task
|
||||||
|
- **WHEN** implementer запрашивает archive и остаётся хотя бы один unchecked task
|
||||||
|
- **THEN** workflow не архивирует change и сообщает incomplete tasks как blocking condition
|
||||||
|
|
||||||
|
#### Scenario: Change завершил все tasks
|
||||||
|
- **WHEN** каждый task отмечен и required verification успешно завершена
|
||||||
|
- **THEN** workflow допускает archive и фиксирует его результат через определённый completion-evidence path без создания post-archive task
|
||||||
@@ -37,3 +37,14 @@
|
|||||||
#### Scenario: Завершён audit-derived change
|
#### Scenario: Завершён audit-derived change
|
||||||
- **WHEN** связанный OpenSpec change архивирован после успешной проверки
|
- **WHEN** связанный OpenSpec change архивирован после успешной проверки
|
||||||
- **THEN** registry обновляется с archive path, commits затронутых репозиториев и результатами exact verification commands
|
- **THEN** registry обновляется с archive path, commits затронутых репозиториев и результатами exact verification commands
|
||||||
|
|
||||||
|
### Requirement: Durable documentation is not a parallel SDD store
|
||||||
|
Репозиторий `docs` SHALL хранить только долговечную architecture, development, feature, audit и remediation documentation вместе с completion evidence. Change-specific requirements, designs, delta specifications и tasks MUST храниться только в canonical OpenSpec store и MUST NOT создаваться как framework-specific planning artifacts в `docs`.
|
||||||
|
|
||||||
|
#### Scenario: Change требует постоянной документации
|
||||||
|
- **WHEN** завершённый change должен оставить устойчивое объяснение решения или evidence
|
||||||
|
- **THEN** documentation фиксирует реализованное решение или completion evidence и ссылается на canonical OpenSpec change без дублирования его requirements, design или tasks
|
||||||
|
|
||||||
|
#### Scenario: Agent планирует незавершённый change
|
||||||
|
- **WHEN** агент создаёт requirements, design или tasks для незавершённого изменения
|
||||||
|
- **THEN** он сохраняет их под `specs/openspec` и не создаёт framework-specific planning document в `docs`
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
### Requirement: Репозитории содержат локальные инструкции для AI-агентов
|
### Requirement: Репозитории содержат локальные инструкции для AI-агентов
|
||||||
Система SHALL содержать обзорный `AGENTS.md` в корне рабочей области и отдельный `AGENTS.md` в репозиториях frontend, backend, specs и docs. Инструкции MUST описывать назначение области, локальные команды проверки, границы ответственности и связь с SDD-артефактами. Локальные инструкции MUST направлять агента к durable remediation registry, когда задача связана с findings технического аудита.
|
Система SHALL содержать обзорный `AGENTS.md` в корне рабочей области и отдельный `AGENTS.md` в репозиториях frontend, backend, specs и docs. Инструкции MUST описывать назначение области, локальные команды проверки, границы ответственности и связь с SDD-артефактами. Каждая инструкция MUST объявлять `wealth-ledger-specs` и `specs/openspec` как canonical OpenSpec authority, требовать явный `--store wealth-ledger-specs` для поддерживаемых OpenSpec операций и запрещать versioned framework-specific planning artifacts вне canonical store. Локальные инструкции MUST направлять агента к durable remediation registry, когда задача связана с findings технического аудита.
|
||||||
|
|
||||||
#### Scenario: Агент начинает работу в отдельном репозитории
|
#### Scenario: Агент начинает работу в отдельном репозитории
|
||||||
- **WHEN** агент открывает любой из репозиториев frontend, backend, specs или docs
|
- **WHEN** агент открывает любой из репозиториев frontend, backend, specs или docs
|
||||||
- **THEN** он может определить локальные правила работы и источник связанных спецификаций из `AGENTS.md` этого репозитория
|
- **THEN** он может определить локальные правила работы, canonical OpenSpec authority и источник связанных спецификаций из `AGENTS.md` этого репозитория
|
||||||
|
|
||||||
#### Scenario: Агент получает audit-derived задачу из отдельного репозитория
|
#### Scenario: Агент получает audit-derived задачу из отдельного репозитория
|
||||||
- **WHEN** задача ссылается на finding технического аудита
|
- **WHEN** задача ссылается на finding технического аудита
|
||||||
- **THEN** локальный `AGENTS.md` указывает на remediation registry и canonical OpenSpec workflow до начала изменения кода
|
- **THEN** локальный `AGENTS.md` указывает на remediation registry и canonical OpenSpec workflow с явным store selection до начала изменения кода
|
||||||
|
|
||||||
### Requirement: Локальный план MVP не является источником спецификации
|
### Requirement: Локальный план MVP не является источником спецификации
|
||||||
Система SHALL содержать корневой локальный `MVP.md` с границами MVP, принятыми решениями, порядком поставок и критериями готовности. Требования к функциональности MUST храниться в OpenSpec, а устойчивая документация MUST храниться в репозитории docs.
|
Система SHALL содержать корневой локальный `MVP.md` с границами MVP, принятыми решениями, порядком поставок и критериями готовности. Требования к функциональности MUST храниться в OpenSpec, а устойчивая документация MUST храниться в репозитории docs.
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
|
||||||
|
workspace=${WEALTH_LEDGER_WORKSPACE:-$(cd "$script_dir/../.." && pwd -P)}
|
||||||
|
failures=0
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf 'FAIL: %s\n' "$1" >&2
|
||||||
|
failures=$((failures + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
require_file_contains() {
|
||||||
|
local file=$1
|
||||||
|
local text=$2
|
||||||
|
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
fail "missing required file: ${file#$workspace/}"
|
||||||
|
elif ! grep -Fq -- "$text" "$file"; then
|
||||||
|
fail "${file#$workspace/} must contain: $text"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
store_file="$workspace/specs/.openspec-store/store.yaml"
|
||||||
|
require_file_contains "$store_file" 'id: wealth-ledger-specs'
|
||||||
|
|
||||||
|
canonical_root="$workspace/specs/openspec"
|
||||||
|
if [[ ! -d "$canonical_root" ]]; then
|
||||||
|
fail "missing canonical OpenSpec root: specs/openspec"
|
||||||
|
fi
|
||||||
|
|
||||||
|
openspec_roots=()
|
||||||
|
while IFS= read -r root; do
|
||||||
|
openspec_roots+=("$root")
|
||||||
|
done < <(
|
||||||
|
find "$workspace" \
|
||||||
|
\( -path "$workspace/references" -o -path "$workspace/.git" -o -path '*/node_modules' -o -path '*/dist' -o -path '*/coverage' \) -prune -o \
|
||||||
|
-type d -name openspec -print | sort
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ ${#openspec_roots[@]} -ne 1 || ${openspec_roots[0]:-} != "$canonical_root" ]]; then
|
||||||
|
fail "expected exactly one project-owned OpenSpec root at specs/openspec"
|
||||||
|
fi
|
||||||
|
|
||||||
|
agent_files=(AGENTS.md frontend/AGENTS.md backend/AGENTS.md specs/AGENTS.md docs/AGENTS.md)
|
||||||
|
for relative_path in "${agent_files[@]}"; do
|
||||||
|
file="$workspace/$relative_path"
|
||||||
|
require_file_contains "$file" 'wealth-ledger-specs'
|
||||||
|
require_file_contains "$file" '--store wealth-ledger-specs'
|
||||||
|
require_file_contains "$file" 'specs/openspec'
|
||||||
|
done
|
||||||
|
|
||||||
|
entrypoints=(
|
||||||
|
.opencode/commands/opsx-apply.md
|
||||||
|
.opencode/commands/opsx-archive.md
|
||||||
|
.opencode/commands/opsx-continue.md
|
||||||
|
.opencode/commands/opsx-explore.md
|
||||||
|
.opencode/commands/opsx-new.md
|
||||||
|
.opencode/commands/opsx-propose.md
|
||||||
|
.opencode/commands/opsx-sync.md
|
||||||
|
.opencode/commands/opsx-verify.md
|
||||||
|
.opencode/skills/openspec-apply-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-archive-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-continue-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-explore/SKILL.md
|
||||||
|
.opencode/skills/openspec-new-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-propose/SKILL.md
|
||||||
|
.opencode/skills/openspec-sync-specs/SKILL.md
|
||||||
|
.opencode/skills/openspec-verify-change/SKILL.md
|
||||||
|
)
|
||||||
|
|
||||||
|
for relative_path in "${entrypoints[@]}"; do
|
||||||
|
file="$workspace/$relative_path"
|
||||||
|
require_file_contains "$file" '--store wealth-ledger-specs'
|
||||||
|
if [[ -f "$file" ]] && grep -Eqi 'nearest local openspec|global default(store)?|defaultstore|without a store|store: pointer|--store <id>|--store "<id>"|when applicable' "$file"; then
|
||||||
|
fail "$relative_path permits conditional OpenSpec store selection"
|
||||||
|
fi
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ $line =~ (^|[^[:alnum:]_])openspec[[:space:]]+(new[[:space:]]+change[[:space:]]+|status[[:space:]]+|instructions[[:space:]]+|list[[:space:]]+|show[[:space:]]+|validate[[:space:]]+|archive[[:space:]]+|doctor[[:space:]]+|context[[:space:]]+|schemas[[:space:]]+|view[[:space:]]+) ]] && [[ $line != *'--store wealth-ledger-specs'* ]]; then
|
||||||
|
fail "$relative_path contains an unscoped OpenSpec invocation: $line"
|
||||||
|
fi
|
||||||
|
done < "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
archive_entrypoints=(
|
||||||
|
.opencode/commands/opsx-archive.md
|
||||||
|
.opencode/skills/openspec-archive-change/SKILL.md
|
||||||
|
)
|
||||||
|
for relative_path in "${archive_entrypoints[@]}"; do
|
||||||
|
file="$workspace/$relative_path"
|
||||||
|
require_file_contains "$file" 'Do not ask for or accept a confirmation override.'
|
||||||
|
if [[ -f "$file" ]] && grep -Eqi 'archive complete \(with warnings\)|don.t block archive on warnings|archived with [0-9]+ incomplete' "$file"; then
|
||||||
|
fail "$relative_path permits archive with incomplete work"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for relative_path in docs/superpowers/plans superpowers/plans .superpowers; do
|
||||||
|
if [[ -e "$workspace/$relative_path" ]]; then
|
||||||
|
fail "prohibited framework planning location: $relative_path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $failures -gt 0 ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'OpenSpec authority verified: wealth-ledger-specs at specs/openspec\n'
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
|
||||||
|
verifier="$script_dir/verify-openspec-authority.sh"
|
||||||
|
|
||||||
|
if [[ ! -f "$verifier" ]]; then
|
||||||
|
echo "expected verifier at $verifier" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fixture=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$fixture"' EXIT
|
||||||
|
|
||||||
|
write_file() {
|
||||||
|
local relative_path=$1
|
||||||
|
local content=$2
|
||||||
|
mkdir -p "$fixture/$(dirname "$relative_path")"
|
||||||
|
printf '%s\n' "$content" > "$fixture/$relative_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_file "specs/.openspec-store/store.yaml" $'version: 1\nid: wealth-ledger-specs'
|
||||||
|
mkdir -p "$fixture/specs/openspec"
|
||||||
|
|
||||||
|
for path in AGENTS.md frontend/AGENTS.md backend/AGENTS.md specs/AGENTS.md docs/AGENTS.md; do
|
||||||
|
write_file "$path" $'OpenSpec store: wealth-ledger-specs\nUse --store wealth-ledger-specs\nSDD artifacts only in specs/openspec\nreferences/** is read-only.'
|
||||||
|
done
|
||||||
|
|
||||||
|
entrypoints=(
|
||||||
|
.opencode/commands/opsx-apply.md
|
||||||
|
.opencode/commands/opsx-archive.md
|
||||||
|
.opencode/commands/opsx-continue.md
|
||||||
|
.opencode/commands/opsx-explore.md
|
||||||
|
.opencode/commands/opsx-new.md
|
||||||
|
.opencode/commands/opsx-propose.md
|
||||||
|
.opencode/commands/opsx-sync.md
|
||||||
|
.opencode/commands/opsx-verify.md
|
||||||
|
.opencode/skills/openspec-apply-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-archive-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-continue-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-explore/SKILL.md
|
||||||
|
.opencode/skills/openspec-new-change/SKILL.md
|
||||||
|
.opencode/skills/openspec-propose/SKILL.md
|
||||||
|
.opencode/skills/openspec-sync-specs/SKILL.md
|
||||||
|
.opencode/skills/openspec-verify-change/SKILL.md
|
||||||
|
)
|
||||||
|
|
||||||
|
for path in "${entrypoints[@]}"; do
|
||||||
|
write_file "$path" 'openspec status --store wealth-ledger-specs'
|
||||||
|
done
|
||||||
|
|
||||||
|
archive_gate='openspec status --store wealth-ledger-specs
|
||||||
|
Do not ask for or accept a confirmation override.'
|
||||||
|
write_file ".opencode/commands/opsx-archive.md" "$archive_gate"
|
||||||
|
write_file ".opencode/skills/openspec-archive-change/SKILL.md" "$archive_gate"
|
||||||
|
|
||||||
|
run_verifier() {
|
||||||
|
WEALTH_LEDGER_WORKSPACE="$fixture" bash "$verifier"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_verifier
|
||||||
|
|
||||||
|
mkdir -p "$fixture/frontend/openspec"
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected additional OpenSpec root to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rmdir "$fixture/frontend/openspec"
|
||||||
|
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" 'Without a store, commands act on the nearest local openspec root.'
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected implicit store selection to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" 'openspec status --store wealth-ledger-specs'
|
||||||
|
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" $'openspec status --store wealth-ledger-specs\nFor another store, append --store "<id>" when applicable.'
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected conditional store selection to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" 'openspec status --store wealth-ledger-specs'
|
||||||
|
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" $'openspec status --store wealth-ledger-specs\nRun `openspec status --change "example" --json` before continuing.'
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected unscoped OpenSpec invocation to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" 'openspec status --store wealth-ledger-specs'
|
||||||
|
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" $'openspec status --store wealth-ledger-specs\nUse artifact graph (openspec status --change "example" --json) before continuing.'
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected parenthesized unscoped OpenSpec invocation to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
write_file ".opencode/commands/opsx-apply.md" 'openspec status --store wealth-ledger-specs'
|
||||||
|
|
||||||
|
write_file ".opencode/commands/opsx-archive.md" $'openspec status --store wealth-ledger-specs\nDon\x27t block archive on warnings - just inform and confirm.'
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected archive override guidance to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
write_file ".opencode/commands/opsx-archive.md" "$archive_gate"
|
||||||
|
|
||||||
|
mkdir -p "$fixture/docs/superpowers/plans"
|
||||||
|
if run_verifier; then
|
||||||
|
echo "expected prohibited planning location to fail" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rmdir "$fixture/docs/superpowers/plans"
|
||||||
|
rmdir "$fixture/docs/superpowers"
|
||||||
|
|
||||||
|
mkdir -p "$fixture/references/example/superpowers/plans"
|
||||||
|
run_verifier
|
||||||
|
|
||||||
|
echo "verify-openspec-authority tests passed"
|
||||||
Reference in New Issue
Block a user