musubix3 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/plugin/marketplace.json +2 -2
- package/.github/skills/sdd-change/SKILL.md +1 -2
- package/CHANGELOG.md +38 -0
- package/README-ja.md +3 -1
- package/README.md +76 -3
- package/dist/packages/analysis/src/approval-domains.d.ts +22 -0
- package/dist/packages/analysis/src/approval-domains.js +75 -0
- package/dist/packages/analysis/src/approval-domains.js.map +1 -0
- package/dist/packages/analysis/src/approval-record.d.ts +7 -1
- package/dist/packages/analysis/src/approval-record.js +23 -9
- package/dist/packages/analysis/src/approval-record.js.map +1 -1
- package/dist/packages/analysis/src/approval.d.ts +67 -5
- package/dist/packages/analysis/src/approval.js +226 -27
- package/dist/packages/analysis/src/approval.js.map +1 -1
- package/dist/packages/analysis/src/attestation.js +12 -0
- package/dist/packages/analysis/src/attestation.js.map +1 -1
- package/dist/packages/analysis/src/change-evidence.d.ts +91 -0
- package/dist/packages/analysis/src/change-evidence.js +172 -0
- package/dist/packages/analysis/src/change-evidence.js.map +1 -0
- package/dist/packages/analysis/src/change-waiver.d.ts +186 -0
- package/dist/packages/analysis/src/change-waiver.js +688 -0
- package/dist/packages/analysis/src/change-waiver.js.map +1 -0
- package/dist/packages/analysis/src/change.d.ts +11 -53
- package/dist/packages/analysis/src/change.js +210 -78
- package/dist/packages/analysis/src/change.js.map +1 -1
- package/dist/packages/analysis/src/config.d.ts +5 -0
- package/dist/packages/analysis/src/config.js +36 -3
- package/dist/packages/analysis/src/config.js.map +1 -1
- package/dist/packages/analysis/src/gate.d.ts +41 -1
- package/dist/packages/analysis/src/gate.js +61 -10
- package/dist/packages/analysis/src/gate.js.map +1 -1
- package/dist/packages/analysis/src/index.d.ts +7 -0
- package/dist/packages/analysis/src/index.js +7 -0
- package/dist/packages/analysis/src/index.js.map +1 -1
- package/dist/packages/analysis/src/mutation.js +11 -2
- package/dist/packages/analysis/src/mutation.js.map +1 -1
- package/dist/packages/analysis/src/order.d.ts +50 -2
- package/dist/packages/analysis/src/order.js +43 -6
- package/dist/packages/analysis/src/order.js.map +1 -1
- package/dist/packages/analysis/src/tdd.d.ts +30 -1
- package/dist/packages/analysis/src/tdd.js +236 -11
- package/dist/packages/analysis/src/tdd.js.map +1 -1
- package/dist/packages/analysis/src/workflow-types.d.ts +58 -0
- package/dist/packages/analysis/src/workflow-types.js +49 -0
- package/dist/packages/analysis/src/workflow-types.js.map +1 -0
- package/dist/packages/analysis/src/workflow-waiver.d.ts +131 -0
- package/dist/packages/analysis/src/workflow-waiver.js +339 -0
- package/dist/packages/analysis/src/workflow-waiver.js.map +1 -0
- package/dist/packages/analysis/src/workflow.d.ts +56 -58
- package/dist/packages/analysis/src/workflow.js +351 -123
- package/dist/packages/analysis/src/workflow.js.map +1 -1
- package/dist/packages/cli/src/main.js +142 -16
- package/dist/packages/cli/src/main.js.map +1 -1
- package/dist/packages/domain/src/types.d.ts +17 -0
- package/dist/packages/domain/src/types.js.map +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"owner": { "name": "nahisaho" },
|
|
4
4
|
"metadata": {
|
|
5
5
|
"description": "GitHub Copilot CLI specification-driven development skills",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.18"
|
|
7
7
|
},
|
|
8
8
|
"plugins": [
|
|
9
9
|
{
|
|
10
10
|
"name": "musubix3",
|
|
11
11
|
"source": ".",
|
|
12
|
-
"version": "0.1.
|
|
12
|
+
"version": "0.1.18",
|
|
13
13
|
"description": "Evidence-driven SDD without duplicating native Copilot capabilities."
|
|
14
14
|
}
|
|
15
15
|
]
|
|
@@ -68,8 +68,7 @@ Documentation/prototypes may omit TDD only when policy allows; record the reason
|
|
|
68
68
|
use strict `Formal:` JSON for explicit conditional, numeric, temporal or
|
|
69
69
|
transition semantics; report unsupported prose rather than claiming proof.
|
|
70
70
|
A required `formal` check enforces modeled fraction and configured solver.
|
|
71
|
-
3. Run `gate --changed --json` and `status --json`. Repair failures, dangling
|
|
72
|
-
links and stale evidence; never weaken requirements or policy to obtain green.
|
|
71
|
+
3. Run `gate --changed --json` and `status --json`. Repair failures, dangling links and stale evidence; never weaken requirements or policy to obtain green. If `workflow` fails, run `workflow-verify` compatible mode against this session's live transcript, then `workflow waiver record-all` (bulk, all-or-nothing) for remaining declaration-scoped diagnostics (it cannot clear `WORKFLOW_INVOCATION_UNVERIFIED`), then rerun gate/status.
|
|
73
72
|
4. Treat the first otherwise-passing gate as the release candidate. Run a `rubber-duck` review of the release/quality evidence summary and the CHANGE document; fix every reported issue and re-review until zero issues remain. Before any release operation, prepare/show its exact hash, ask one human approve/reject question and wait; record only that hash, then rerun gate/status.
|
|
74
73
|
5. Complete only when required checks pass and `status.gate.ready` is true;
|
|
75
74
|
otherwise report blockers. One-phase work must state downstream work.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.18 - 2026-09-13
|
|
4
|
+
|
|
5
|
+
New feature: bulk workflow-waiver recording, resolving the repeated
|
|
6
|
+
release-approval blocking pattern from `workflow-verify`/waiver reconciliation
|
|
7
|
+
friction (GitHub Issues #21/#22/#23, this change: #24).
|
|
8
|
+
|
|
9
|
+
- `musubix3 workflow waiver record-all --approver <name> --reason <text>
|
|
10
|
+
--confirm` waives every currently-outstanding waivable declaration-scoped
|
|
11
|
+
workflow diagnostic across the whole reconciliation report in one
|
|
12
|
+
all-or-nothing call, instead of requiring one `workflow waiver record`
|
|
13
|
+
invocation per diagnostic.
|
|
14
|
+
- Rejects (recording nothing) if any bulk waiver precondition fails first:
|
|
15
|
+
malformed waiver evidence, an invalid waiver chain, a blank
|
|
16
|
+
`--approver`/`--reason`, or an outstanding `WORKFLOW_INVOCATION_UNVERIFIED`
|
|
17
|
+
diagnostic (which only `workflow-verify` having actually run this session
|
|
18
|
+
can resolve).
|
|
19
|
+
- Idempotent: with zero remaining waivable candidates it succeeds and records
|
|
20
|
+
nothing.
|
|
21
|
+
- Spec: `REQ-WORKFLOW-WAIVER-BULK-001..004`,
|
|
22
|
+
`DES-WORKFLOW-WAIVER-BULK-001..003`, tracked end-to-end in `CHANGE-0012`.
|
|
23
|
+
|
|
24
|
+
## 0.1.17 - 2026-09-13
|
|
25
|
+
|
|
26
|
+
`gate --changed` remediation for the change-evidence-waiver feature
|
|
27
|
+
(CHANGE-0012, GitHub Issue #1 item):
|
|
28
|
+
|
|
29
|
+
- Fixed a `TRACE_DUPLICATE` diagnostic caused by a duplicate trace `@id` on
|
|
30
|
+
two distinct annotations in `order.ts`.
|
|
31
|
+
- Added a missing `@implements REQ-TDD-CYCLE-VOID-013` trace annotation on
|
|
32
|
+
the voided-cycle handling in `tdd.ts`, closing a `CHANGE_COMPLETENESS_CODE`
|
|
33
|
+
gap for CHANGE-0011.
|
|
34
|
+
- Retroactively waived 166 historical `change-history`/`change-completeness`
|
|
35
|
+
diagnostics predating the CHANGE-0012 waiver mechanism as reviewed legacy
|
|
36
|
+
debt (CHANGE-0005, 0006, 0009, 0010, 0011).
|
|
37
|
+
- Performed a full retroactive TDD Red-Green ceremony (18 test/requirement
|
|
38
|
+
pairs across 15 tests in `tests/change-evidence-waiver.test.ts`), resolving
|
|
39
|
+
all `TDD_TEST_STALE`/`TDD_REQUIREMENT_UNCOVERED` diagnostics.
|
|
40
|
+
|
|
3
41
|
## 0.1.16 - 2026-09-12
|
|
4
42
|
|
|
5
43
|
New feature: scaffold starter `requirements.md`/`design.md` files for a new
|
package/README-ja.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# musubix3
|
|
2
2
|
|
|
3
|
-
**最新リリース v0.1.
|
|
3
|
+
**最新リリース v0.1.17 · GitHub Copilot CLI 専用 · Node.js ≥20 · TypeScript · MIT**
|
|
4
4
|
|
|
5
5
|
[English](README.md)
|
|
6
6
|
|
|
@@ -362,6 +362,8 @@ npx musubix3 tdd green TEST-EXAMPLE-002 --requirement REQ-EXAMPLE-002 --command
|
|
|
362
362
|
| `tdd validate` | 保存済みRed/Green/Refactorの順序、指紋、実行時間、hash-chainを検証 |
|
|
363
363
|
| `tdd red\|green\|refactor <TEST-ID> --requirement <REQ-ID> --command <name>` | 検証可能なTDDフェーズを実行・記録 |
|
|
364
364
|
| `workflow-record <skill> <phase> --status <status>` | 自己申告のworkflow宣言を記録 |
|
|
365
|
+
| `workflow waiver record <code> --skill <skill> --phase <phase> --recorded-at <timestamp> [--index <n>] --approver <name> --reason <text> --confirm` | declaration単位のworkflow照合診断(`WORKFLOW_SKILL_NOT_INVOKED`、`WORKFLOW_INVOCATION_ORDER`、`WORKFLOW_INVOCATION_INCOMPLETE`、`WORKFLOW_INVOCATION_FAILED`、`WORKFLOW_INVOCATION_REUSED`のいずれか)1件を、監査可能な範囲でnon-blockingなwaived状態に降格記録する。同じdeclaration scopeを共有する`WORKFLOW_BINDING_MISSING`診断も同時に降格される。`WORKFLOW_INVOCATION_UNVERIFIED`はwaiveできず、そのsessionで実際に`workflow-verify`を実行した場合のみ解消できる |
|
|
366
|
+
| `workflow waiver record-all --approver <name> --reason <text> --confirm` | `workflow waiver record`の一括版。reconciliation report全体で現在waive可能なdeclaration scope診断を、1件ずつの`record`呼び出しの代わりに全件一括でall-or-nothingにwaiveする。不正なwaiver証拠、無効なwaiver chain、空の`--approver`/`--reason`、または`workflow-verify`が未解決の`WORKFLOW_INVOCATION_UNVERIFIED`診断のいずれかが事前条件チェックで検出された場合は何も記録せず拒否する(`workflow-verify`が一度も実行されていない場合、個別waiverも一括waiverもこれを代替できない)。waiveされた各declaration scope診断に対応する`WORKFLOW_BINDING_MISSING`も、既存の単体`record`コマンドと同様に同時に降格される。waive対象が0件(既にwaive済み、または該当なし)の場合は冪等に成功し、何も記録しない |
|
|
365
367
|
| `workflow-sanitize <copilot.jsonl> <output-file> [--session-id <uuid>]` | reviewやstrict検証前にmessageとSkill以外のtool dataを除去 |
|
|
366
368
|
| `workflow-verify <copilot.jsonl> [--strict] [--session-id <uuid>]` | Skillイベントを照合し、任意で完全な成功session transcriptを要求 |
|
|
367
369
|
| `attestation oidc-audience --key-id <id> [--public-key-file <pem>]` | 署名鍵を許可するGitHub custom audienceを導出 |
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# musubix3
|
|
2
2
|
|
|
3
|
-
**Latest release v0.1.
|
|
3
|
+
**Latest release v0.1.17 · GitHub Copilot CLI only · Node.js ≥20 · TypeScript · MIT**
|
|
4
4
|
|
|
5
5
|
[日本語](README-ja.md)
|
|
6
6
|
|
|
@@ -410,14 +410,16 @@ validation/gate or requested solver failure, **2** usage, I/O or malformed confi
|
|
|
410
410
|
| `mutation validate` | Revalidate requirement-scoped schema-v1 killed-mutant evidence |
|
|
411
411
|
| `mutation identity <REQ-ID> <TEST-ID> <sourcePath> <operator> <line> <column>` | Print the deterministic `MUT-*` identity a mutation report must declare |
|
|
412
412
|
| `tdd validate` | Validate persisted Red/Green/Refactor order, fingerprints, durations, and hash-chain evidence |
|
|
413
|
-
| `tdd red\|green\|refactor <TEST-ID> --requirement <REQ-ID> --command <name>` | Execute and record a verified TDD phase |
|
|
413
|
+
| `tdd red\|green\|refactor <TEST-ID> --requirement <REQ-ID> --command <name>` | Execute and record a verified TDD phase. Recording the project's **first** `tdd` cycle (any `red` call while `.musubix/evidence/tdd.json` has zero cycles) makes `gate`'s `tdd` check required **project-wide**, for every mandatory requirement, not just the ones touched by the current change; each uncovered requirement then surfaces as `TDD_REQUIREMENT_UNCOVERED`. `approval record release` always runs the full (non-`--changed`) gate, so it is blocked by any resulting `TDD_REQUIREMENT_UNCOVERED` diagnostics. `tdd migrate` cannot be used to bulk-onboard previously-uncovered requirements: it only re-fingerprints a requirement that already has a valid Green cycle. `tdd red` prints/returns a `TDD_ADOPTION_PROJECT_WIDE` warning (in a `warnings` array, separate from `diagnostics`) the moment this first cycle is persisted, listing every other still-uncovered mandatory requirement. |
|
|
414
414
|
| `workflow-record <skill> <phase> --status <status>` | Record a compact self-reported workflow declaration |
|
|
415
|
+
| `workflow waiver record <code> --skill <skill> --phase <phase> --recorded-at <timestamp> [--index <n>] --approver <name> --reason <text> --confirm` | Record an audited, bounded downgrade of one declaration-scoped workflow reconciliation diagnostic (`WORKFLOW_SKILL_NOT_INVOKED`, `WORKFLOW_INVOCATION_ORDER`, `WORKFLOW_INVOCATION_INCOMPLETE`, `WORKFLOW_INVOCATION_FAILED`, or `WORKFLOW_INVOCATION_REUSED`) to a non-blocking waived status; a paired `WORKFLOW_BINDING_MISSING` diagnostic sharing the same declaration scope is downgraded together with it. It cannot waive `WORKFLOW_INVOCATION_UNVERIFIED`, which only `workflow-verify` having actually run this session can resolve |
|
|
416
|
+
| `workflow waiver record-all --approver <name> --reason <text> --confirm` | Bulk variant of `workflow waiver record`: waives every currently-outstanding waivable declaration-scoped diagnostic across the whole reconciliation report in one all-or-nothing call, instead of one `record` invocation per diagnostic. Rejects (recording nothing) if any bulk waiver precondition fails first — malformed waiver evidence, an invalid waiver chain, a blank `--approver`/`--reason`, or a `WORKFLOW_INVOCATION_UNVERIFIED` diagnostic (which `workflow-verify` must resolve first; no per-declaration or bulk waiver can substitute for `workflow-verify` never having run). Each waived declaration-scoped diagnostic's paired `WORKFLOW_BINDING_MISSING` is downgraded together with it, identically to the existing single-record command. With zero remaining candidates (already waived, or none present) it succeeds idempotently and records nothing |
|
|
415
417
|
| `workflow-sanitize <copilot.jsonl> <output-file> [--session-id <uuid>]` | Remove messages and non-Skill tool data before review or strict verification |
|
|
416
418
|
| `workflow-verify <copilot.jsonl...> [--strict] [--session-id <uuid>]` | Reconcile Skill events; compatible mode accepts multiple transcript files (concatenated in chronological session order) so declarations whose invocation occurred in an earlier Copilot CLI session can be reconciled; `--strict`/`--session-id` still require exactly one file |
|
|
417
419
|
| `attestation oidc-audience --key-id <id> [--public-key-file <pem>]` | Derive the GitHub custom audience that authorizes a signing key |
|
|
418
420
|
| `attestation payload --provider <name> --run-id <id> --key-id <id> [--public-key-file <pem>] [--github-oidc-token-file <jwt>]` | Emit canonical unsigned CI payload for external signing |
|
|
419
421
|
| `attestation verify` | Verify static-key or GitHub OIDC-authorized Ed25519 provenance |
|
|
420
|
-
| `change-record <CHANGE-ID> <phase> --requirement <REQ-ID
|
|
422
|
+
| `change-record <CHANGE-ID> <phase> --requirement <REQ-ID...> [--allow-unchanged] [--dry-run]` | Record ordered artifact/TDD fingerprints for a staged change. `impact`/`requirements`/`design`/`quality` require the change's full requirement ID set; `red`/`implementation`/`green` also accept a proper non-empty subset, recorded as an independent per-requirement batch, so a multi-requirement change can be completed with an interleaved per-requirement Red-Implementation-Green loop instead of one global batch. Rejects with a non-zero exit and a stable `*_UNCHANGED_AT_RECORD` diagnostic (leaving `changes.json`/`order.json` untouched) when a phase's fingerprint is byte-identical to the immediately preceding phase's, since that mistake is otherwise only caught much later by `trace check --strict`/`gate`, at which point the append-only evidence store makes it unfixable. `--allow-unchanged` bypasses this check for the `requirements` phase only (the one case `sdd-change` documents as legitimate: a defect fix that intentionally leaves its requirement unchanged) and persists a durable marker so later validation does not re-flag it. `--dry-run` previews the exact success/rejection outcome, including every existing check, without persisting anything. Each recorded phase/batch stores both `order` (the verified, `gate`-checked logical append sequence from `order.json` — the only field guaranteed correct and monotonic per change) and `recordedAt` (an independently captured wall-clock timestamp with no ordering guarantee relative to `order`); `gate` reports a non-blocking `CHANGE_RECORDEDAT_OUT_OF_ORDER` warning when a change's `recordedAt` values disagree with its `order` sequence |
|
|
421
423
|
| `config lint` | Report configured commands whose `args` reference repository-relative paths that do not exist |
|
|
422
424
|
| `config scaffold` | Propose native test-command entries for detected Go/Rust/Maven/Python/Node toolchains without writing `.musubix/config.json` |
|
|
423
425
|
| `gate [--changed] [--feature <name>]` | Fresh full checks plus actual configured commands; persist evidence. `--feature` scopes requirements/design/trace/tdd/change-history/change-completeness checks to one feature as a diagnostic view; never a substitute for the repository-wide gate |
|
|
@@ -901,8 +903,79 @@ artifact identity. Excluding the attestation check from the quality head avoids
|
|
|
901
903
|
a circular signature dependency. A missing `ci-required` attestation is reported
|
|
902
904
|
as a failed/missing check, never as skipped local evidence.
|
|
903
905
|
|
|
906
|
+
#### Attestation evidence-head composition
|
|
907
|
+
|
|
908
|
+
`collectEvidenceHeads` (`packages/analysis/src/attestation.ts`) canonicalizes
|
|
909
|
+
up to ten independent evidence entries into stable per-entry digests. Each
|
|
910
|
+
entry's direct input/projection is:
|
|
911
|
+
|
|
912
|
+
- `tdd`: the last entry's `recordSha256` from `.musubix/evidence/tdd.json`'s
|
|
913
|
+
hash chain — a chain-tip digest, not a projection over every recorded
|
|
914
|
+
phase field.
|
|
915
|
+
- `workflow`: `workflowEvidenceHead`'s projection of
|
|
916
|
+
`.musubix/evidence/workflow.json`'s `verification` block only
|
|
917
|
+
(`eventsSha256`, `sourceSha256`, `transcriptSha256`, `mode`, `sessionId`,
|
|
918
|
+
`exitCode`, `terminalAt`, `eventCount`, `sourceBytes`,
|
|
919
|
+
`maxTranscriptBytes`, `maximumLineBytes`, `maxTranscriptLineBytes`, and
|
|
920
|
+
`invocations` (each entry's `skill`/`toolCallId`/`invokedAt`/
|
|
921
|
+
`completedAt`/`status`, unsorted/order-sensitive as stored), or just
|
|
922
|
+
`eventsSha256`/`sourceSha256` when `mode`, `transcriptSha256`, and
|
|
923
|
+
`sessionId` are all absent); the raw `events` log itself is excluded.
|
|
924
|
+
- `changes`: a canonical digest of `.musubix/evidence/changes.json`'s
|
|
925
|
+
`changes` array directly — not the `.musubix/changes/*.md` documents
|
|
926
|
+
themselves, which are a separate upstream input to that evidence.
|
|
927
|
+
- `order`: the last entry's `recordSha256` from `.musubix/evidence/order.json`'s
|
|
928
|
+
records — a chain-tip digest, not a projection over every recorded
|
|
929
|
+
declaration.
|
|
930
|
+
- `formal`: retains only `fingerprints`, `totalRequirements`,
|
|
931
|
+
`modeledRequirements`, `modeledFraction`, and the solver's
|
|
932
|
+
`artifact`/`status`/`result.consistency` from `.musubix/evidence/formal.json`,
|
|
933
|
+
excluding `generatedAt` and every other `result` field such as solver
|
|
934
|
+
duration, diagnostics, literals, and constraints.
|
|
935
|
+
- `performance`: `performanceEvidenceHead`'s projection of
|
|
936
|
+
`.musubix/evidence/performance.json`, retaining per execution
|
|
937
|
+
`commandName`/`commandSha256`/`reportPath`/`sourceKind`/`processStatus`/
|
|
938
|
+
`exitCode`/a canonically-sorted `tests` array (each test entry kept in
|
|
939
|
+
full), and per observation `requirementId`/`testId`/`counter`/`observed`/
|
|
940
|
+
`maximum`/`status`/an optional `provenance` object retaining exactly
|
|
941
|
+
`commandName`/`commandSha256`/`reportPath`/`sourceKind`/`testId`/
|
|
942
|
+
`testStatus`/`counter`/`value`/`processStatus`/`exitCode`; both the
|
|
943
|
+
`executions` and `observations` arrays are canonicalized
|
|
944
|
+
order-independently.
|
|
945
|
+
- `mutation`: `mutationEvidenceHead`'s equivalent projection of
|
|
946
|
+
`.musubix/evidence/mutation.json`, retaining per execution
|
|
947
|
+
`commandName`/`commandSha256`/`reportPath`/`processStatus`/`exitCode`/a
|
|
948
|
+
canonically-sorted `mutants` array (each mutant's full record); both the
|
|
949
|
+
`executions` and nested `mutants` arrays are canonicalized
|
|
950
|
+
order-independently.
|
|
951
|
+
- `modelCorrespondence`: `modelCorrespondenceEvidenceHead`'s projection of
|
|
952
|
+
`.musubix/evidence/model-correspondence.json`, retaining `schemaVersion`,
|
|
953
|
+
`formalEvidenceSha256`, `traceEvidenceSha256`, and a canonically-sorted
|
|
954
|
+
`entries` array (each retaining `requirementId`/`requirementPath`/
|
|
955
|
+
`formalSha256`/`modelSha256`/`traceSha256`/a canonically-sorted `tests`
|
|
956
|
+
array retaining exactly `testId`/`testPath`/`testSha256`/`commandName`/
|
|
957
|
+
`commandSha256`/`reportPath`, excluding `reportSha256`/`provenanceSha256`);
|
|
958
|
+
any other stored run metadata is excluded.
|
|
959
|
+
- `quality`: retains `schemaVersion`, `mode`, a derived pass/fail `status`,
|
|
960
|
+
and each non-`attestation` check's `name`/`required`/`status`/a narrow
|
|
961
|
+
`diagnostics` projection (`code`/`severity`/`path`/`line`), plus `metrics`
|
|
962
|
+
with the `attestation.errors` entry excluded; also excludes `generatedAt`,
|
|
963
|
+
`durationMs`, and `stdout`/`stderr`.
|
|
964
|
+
- `workspace`: not an evidence file at all — a content digest over the
|
|
965
|
+
non-evidence repository file set returned by `files(root)`, filtered by
|
|
966
|
+
`evidenceInputPaths`; `.musubix/evidence/**` itself is excluded from this
|
|
967
|
+
walk so writing evidence never perturbs the workspace snapshot it is
|
|
968
|
+
bound into.
|
|
969
|
+
|
|
970
|
+
See `collectEvidenceHeads` and the per-entry head functions it delegates to
|
|
971
|
+
(`workflowEvidenceHead`, `performanceEvidenceHead`, `mutationEvidenceHead`,
|
|
972
|
+
`modelCorrespondenceEvidenceHead`) for the authoritative implementation; this
|
|
973
|
+
list is a summary, not a substitute for reading the source when precision
|
|
974
|
+
matters.
|
|
975
|
+
|
|
904
976
|
Example strict configuration:
|
|
905
977
|
|
|
978
|
+
|
|
906
979
|
```json
|
|
907
980
|
{
|
|
908
981
|
"attestation": {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ApprovalConfig } from './config.js';
|
|
2
|
+
export interface ResolvedDomain {
|
|
3
|
+
name: string;
|
|
4
|
+
features: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function domainsConfigured(config: ApprovalConfig): boolean;
|
|
7
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-002
|
|
8
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-002 REQ-APPROVAL-DOMAIN-SCOPING-003 REQ-APPROVAL-DOMAIN-SCOPING-004
|
|
9
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-002
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveDomains(root: string, config: ApprovalConfig): Promise<ResolvedDomain[]>;
|
|
12
|
+
export declare function domainOwning(resolved: ResolvedDomain[], slug: string): string | null;
|
|
13
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-014
|
|
14
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-016
|
|
15
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
16
|
+
*/
|
|
17
|
+
export declare function featureOwningRequirement(root: string, requirementId: string): Promise<string>;
|
|
18
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-015
|
|
19
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-017
|
|
20
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
21
|
+
*/
|
|
22
|
+
export declare function featureOwningDesignFile(file: string): string | null;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { validateRequirements } from '../../domain/src/index.js';
|
|
2
|
+
import { matchGlob } from './graph.js';
|
|
3
|
+
import { files, readText } from './files.js';
|
|
4
|
+
const featureRequirementsPattern = /^\.musubix\/features\/([^/]+)\/requirements\.md$/;
|
|
5
|
+
const featureDesignPattern = /^\.musubix\/features\/([^/]+)\/design\.md$/;
|
|
6
|
+
export function domainsConfigured(config) {
|
|
7
|
+
return config.domains.length > 0;
|
|
8
|
+
}
|
|
9
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-002
|
|
10
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-002 REQ-APPROVAL-DOMAIN-SCOPING-003 REQ-APPROVAL-DOMAIN-SCOPING-004
|
|
11
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-002
|
|
12
|
+
*/
|
|
13
|
+
export async function resolveDomains(root, config) {
|
|
14
|
+
const domains = config.domains;
|
|
15
|
+
if (domains.length === 0)
|
|
16
|
+
return [];
|
|
17
|
+
const slugs = [...new Set((await files(root))
|
|
18
|
+
.map((path) => featureRequirementsPattern.exec(path)?.[1])
|
|
19
|
+
.filter((slug) => !!slug))].sort();
|
|
20
|
+
const owners = new Map();
|
|
21
|
+
for (const slug of slugs) {
|
|
22
|
+
const matching = domains.filter((domain) => domain.featureGlobs.some((glob) => matchGlob(slug, glob)));
|
|
23
|
+
owners.set(slug, matching.map((domain) => domain.name).sort());
|
|
24
|
+
}
|
|
25
|
+
for (const slug of slugs) {
|
|
26
|
+
const matching = owners.get(slug);
|
|
27
|
+
if (matching.length === 0) {
|
|
28
|
+
throw new Error(`Feature "${slug}" is not owned by any configured approval domain; every feature directory must match exactly one domain's featureGlobs.`);
|
|
29
|
+
}
|
|
30
|
+
if (matching.length > 1) {
|
|
31
|
+
throw new Error(`Feature "${slug}" matches more than one configured approval domain: ${matching.join(', ')}; every feature directory must match exactly one domain.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const resolved = domains.map((domain) => ({
|
|
35
|
+
name: domain.name,
|
|
36
|
+
features: slugs.filter((slug) => owners.get(slug)[0] === domain.name).sort(),
|
|
37
|
+
}));
|
|
38
|
+
for (const domain of resolved) {
|
|
39
|
+
if (domain.features.length === 0) {
|
|
40
|
+
throw new Error(`Approval domain "${domain.name}" matches zero existing feature directories; remove it or add a matching feature.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return resolved;
|
|
44
|
+
}
|
|
45
|
+
export function domainOwning(resolved, slug) {
|
|
46
|
+
return resolved.find((domain) => domain.features.includes(slug))?.name ?? null;
|
|
47
|
+
}
|
|
48
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-014
|
|
49
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-016
|
|
50
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
51
|
+
*/
|
|
52
|
+
export async function featureOwningRequirement(root, requirementId) {
|
|
53
|
+
const paths = (await files(root)).filter((path) => featureRequirementsPattern.test(path));
|
|
54
|
+
const owners = [];
|
|
55
|
+
for (const path of paths) {
|
|
56
|
+
const slug = featureRequirementsPattern.exec(path)[1];
|
|
57
|
+
const result = validateRequirements(await readText(root, path), path);
|
|
58
|
+
if (result.value.some((requirement) => requirement.id === requirementId))
|
|
59
|
+
owners.push(slug);
|
|
60
|
+
}
|
|
61
|
+
if (owners.length === 0)
|
|
62
|
+
throw new Error(`Requirement ${requirementId} was not found in any feature's requirements.md.`);
|
|
63
|
+
if (owners.length > 1)
|
|
64
|
+
throw new Error(`Requirement ${requirementId} is defined in more than one feature: ${owners.join(', ')}.`);
|
|
65
|
+
return owners[0];
|
|
66
|
+
}
|
|
67
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-015
|
|
68
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-017
|
|
69
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
70
|
+
*/
|
|
71
|
+
export function featureOwningDesignFile(file) {
|
|
72
|
+
const match = featureDesignPattern.exec(file);
|
|
73
|
+
return match ? match[1] : null;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=approval-domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-domains.js","sourceRoot":"","sources":["../../../../packages/analysis/src/approval-domains.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import type { ApprovalConfig } from './config.js';
|
|
1
2
|
import { type ApprovalEvidence, type ApprovalStage } from './approval.js';
|
|
2
3
|
/** @id CODE-HUMAN-APPROVAL-GATES-002
|
|
3
4
|
* @implements REQ-HUMAN-APPROVAL-GATES-001 REQ-HUMAN-APPROVAL-GATES-006
|
|
4
5
|
* @design DES-APPROVAL-002 DES-APPROVAL-003
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-016
|
|
8
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-005 REQ-APPROVAL-DOMAIN-SCOPING-006 REQ-APPROVAL-DOMAIN-SCOPING-007
|
|
9
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-013 REQ-APPROVAL-DOMAIN-SCOPING-014 REQ-APPROVAL-DOMAIN-SCOPING-015
|
|
10
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
11
|
+
*/
|
|
12
|
+
export declare function recordApproval(root: string, stage: ApprovalStage, approver: string, expectedArtifactSha256: string, config: ApprovalConfig, domainName?: string): Promise<ApprovalEvidence>;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { approvalManifest, requireApproval, validateStageArtifacts, } from './approval.js';
|
|
1
|
+
import { approvalManifest, approvalPath, domainsConfigured, requireApproval, requireDomainOption, resolveDomains, validateStageArtifacts, } from './approval.js';
|
|
2
2
|
import { writeJson } from './files.js';
|
|
3
3
|
import { runGate } from './gate.js';
|
|
4
4
|
/** @id CODE-HUMAN-APPROVAL-GATES-002
|
|
5
5
|
* @implements REQ-HUMAN-APPROVAL-GATES-001 REQ-HUMAN-APPROVAL-GATES-006
|
|
6
6
|
* @design DES-APPROVAL-002 DES-APPROVAL-003
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-016
|
|
9
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-005 REQ-APPROVAL-DOMAIN-SCOPING-006 REQ-APPROVAL-DOMAIN-SCOPING-007
|
|
10
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-013 REQ-APPROVAL-DOMAIN-SCOPING-014 REQ-APPROVAL-DOMAIN-SCOPING-015
|
|
11
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
12
|
+
*/
|
|
13
|
+
export async function recordApproval(root, stage, approver, expectedArtifactSha256, config, domainName) {
|
|
9
14
|
const normalizedApprover = approver.trim();
|
|
10
15
|
if (!normalizedApprover || normalizedApprover.includes('\0')) {
|
|
11
16
|
throw new Error('Approver must be a nonempty name without NUL bytes.');
|
|
@@ -13,19 +18,28 @@ export async function recordApproval(root, stage, approver, expectedArtifactSha2
|
|
|
13
18
|
if (!/^[a-f0-9]{64}$/.test(expectedArtifactSha256)) {
|
|
14
19
|
throw new Error('Expected approval artifact SHA-256 must be 64 lowercase hexadecimal characters.');
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
requireDomainOption(config, stage, domainName);
|
|
22
|
+
const resolved = domainsConfigured(config) ? await resolveDomains(root, config) : [];
|
|
23
|
+
const domain = domainName ? resolved.find((d) => d.name === domainName) : undefined;
|
|
24
|
+
await validateStageArtifacts(root, stage, domain);
|
|
25
|
+
const requiredApproval = { mode: 'required', domains: [] };
|
|
26
|
+
if (stage === 'design') {
|
|
27
|
+
await requireApproval(root, 'requirements', requiredApproval, domain);
|
|
28
|
+
}
|
|
20
29
|
if (stage === 'release') {
|
|
21
|
-
|
|
30
|
+
for (const d of resolved) {
|
|
31
|
+
await requireApproval(root, 'requirements', requiredApproval, d);
|
|
32
|
+
await requireApproval(root, 'design', requiredApproval, d);
|
|
33
|
+
}
|
|
34
|
+
if (!resolved.length)
|
|
35
|
+
await requireApproval(root, 'design', requiredApproval);
|
|
22
36
|
const quality = await runGate(root);
|
|
23
37
|
const blockers = quality.checks.filter((check) => check.name !== 'approval' && check.required && check.status !== 'pass');
|
|
24
38
|
if (blockers.length) {
|
|
25
39
|
throw new Error(`Release approval requires passing non-approval quality checks: ${blockers.map((check) => check.name).join(', ')}.`);
|
|
26
40
|
}
|
|
27
41
|
}
|
|
28
|
-
const manifest = await approvalManifest(root, stage);
|
|
42
|
+
const manifest = await approvalManifest(root, stage, domain);
|
|
29
43
|
if (!Object.keys(manifest.artifacts).length)
|
|
30
44
|
throw new Error(`No artifacts are available for ${stage} approval.`);
|
|
31
45
|
if (manifest.artifactSha256 !== expectedArtifactSha256) {
|
|
@@ -37,7 +51,7 @@ export async function recordApproval(root, stage, approver, expectedArtifactSha2
|
|
|
37
51
|
approver: normalizedApprover,
|
|
38
52
|
approvedAt: new Date().toISOString(),
|
|
39
53
|
};
|
|
40
|
-
await writeJson(root,
|
|
54
|
+
await writeJson(root, approvalPath(stage, domainName), evidence);
|
|
41
55
|
return evidence;
|
|
42
56
|
}
|
|
43
57
|
//# sourceMappingURL=approval-record.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-record.js","sourceRoot":"","sources":["../../../../packages/analysis/src/approval-record.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAAE,eAAe,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"approval-record.js","sourceRoot":"","sources":["../../../../packages/analysis/src/approval-record.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type Diagnostic } from '../../domain/src/index.js';
|
|
2
2
|
import type { ApprovalConfig } from './config.js';
|
|
3
|
+
import { type ResolvedDomain } from './approval-domains.js';
|
|
4
|
+
export { domainsConfigured, domainOwning, featureOwningDesignFile, featureOwningRequirement, resolveDomains, type ResolvedDomain, } from './approval-domains.js';
|
|
3
5
|
export declare const approvalStages: readonly ["requirements", "design", "release"];
|
|
4
6
|
export type ApprovalStage = typeof approvalStages[number];
|
|
5
7
|
export type ApprovalStatus = 'approved' | 'missing' | 'stale';
|
|
6
8
|
export interface ApprovalManifest {
|
|
7
9
|
stage: ApprovalStage;
|
|
10
|
+
domain?: string;
|
|
11
|
+
features?: string[];
|
|
8
12
|
artifacts: Record<string, string>;
|
|
9
13
|
artifactSha256: string;
|
|
10
14
|
}
|
|
@@ -15,6 +19,7 @@ export interface ApprovalEvidence extends ApprovalManifest {
|
|
|
15
19
|
}
|
|
16
20
|
export interface ApprovalStageValidation {
|
|
17
21
|
stage: ApprovalStage;
|
|
22
|
+
domain?: string;
|
|
18
23
|
required: boolean;
|
|
19
24
|
present: boolean;
|
|
20
25
|
status: ApprovalStatus;
|
|
@@ -22,27 +27,84 @@ export interface ApprovalStageValidation {
|
|
|
22
27
|
currentArtifactSha256: string;
|
|
23
28
|
diagnostics: Diagnostic[];
|
|
24
29
|
}
|
|
30
|
+
export interface DomainApprovalValidation {
|
|
31
|
+
name: string;
|
|
32
|
+
stages: ApprovalStageValidation[];
|
|
33
|
+
}
|
|
25
34
|
export interface ApprovalValidation {
|
|
26
35
|
schemaVersion: 1;
|
|
27
36
|
mode: ApprovalConfig['mode'];
|
|
28
37
|
present: boolean;
|
|
29
38
|
valid: boolean;
|
|
30
39
|
stages: ApprovalStageValidation[];
|
|
40
|
+
domain?: string;
|
|
41
|
+
domains?: DomainApprovalValidation[];
|
|
42
|
+
release?: ApprovalStageValidation;
|
|
31
43
|
diagnostics: Diagnostic[];
|
|
32
44
|
}
|
|
45
|
+
export declare function approvalPath(stage: ApprovalStage, domain?: string): string;
|
|
33
46
|
/** @id CODE-HUMAN-APPROVAL-GATES-001
|
|
34
47
|
* @implements REQ-HUMAN-APPROVAL-GATES-001 REQ-HUMAN-APPROVAL-GATES-002 REQ-HUMAN-APPROVAL-GATES-003
|
|
35
48
|
* @implements REQ-HUMAN-APPROVAL-GATES-004 REQ-HUMAN-APPROVAL-GATES-005 REQ-HUMAN-APPROVAL-GATES-006
|
|
36
49
|
* @implements REQ-HUMAN-APPROVAL-GATES-007 REQ-HUMAN-APPROVAL-GATES-008
|
|
37
50
|
* @design DES-APPROVAL-001 DES-APPROVAL-002 DES-APPROVAL-003
|
|
38
51
|
*/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-007
|
|
53
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-011 REQ-APPROVAL-DOMAIN-SCOPING-012 REQ-APPROVAL-DOMAIN-SCOPING-013
|
|
54
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-014 REQ-APPROVAL-DOMAIN-SCOPING-023 REQ-APPROVAL-DOMAIN-SCOPING-024
|
|
55
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-003
|
|
56
|
+
*/
|
|
57
|
+
export declare function approvalManifest(root: string, stage: ApprovalStage, domain?: ResolvedDomain): Promise<ApprovalManifest>;
|
|
58
|
+
export declare function loadApproval(root: string, stage: ApprovalStage, domain?: string): Promise<ApprovalEvidence | null>;
|
|
59
|
+
export declare function validateApprovalStage(root: string, stage: ApprovalStage, config: ApprovalConfig, domain?: ResolvedDomain): Promise<ApprovalStageValidation>;
|
|
60
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-004
|
|
61
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-008 REQ-APPROVAL-DOMAIN-SCOPING-021 REQ-APPROVAL-DOMAIN-SCOPING-022
|
|
62
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
63
|
+
*/
|
|
42
64
|
export declare function validateApprovals(root: string, config: ApprovalConfig): Promise<ApprovalValidation>;
|
|
65
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-008
|
|
66
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-009 REQ-APPROVAL-DOMAIN-SCOPING-010
|
|
67
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
68
|
+
*/
|
|
69
|
+
export declare function validateApprovalsForDomain(root: string, config: ApprovalConfig, domainName: string): Promise<ApprovalValidation>;
|
|
70
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-006
|
|
71
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-019 REQ-APPROVAL-DOMAIN-SCOPING-020
|
|
72
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-006
|
|
73
|
+
*/
|
|
74
|
+
export declare function validateApprovalsForFeatureGate(root: string, config: ApprovalConfig, domainName: string): Promise<ApprovalValidation>;
|
|
75
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-009
|
|
76
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-005 REQ-APPROVAL-DOMAIN-SCOPING-006 REQ-APPROVAL-DOMAIN-SCOPING-007
|
|
77
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
78
|
+
*/
|
|
79
|
+
export declare function requireDomainOption(config: ApprovalConfig, stage: ApprovalStage, domain: string | undefined): void;
|
|
80
|
+
export declare function requireValidateDomainOption(config: ApprovalConfig, domain: string | undefined): void;
|
|
43
81
|
/** @id CODE-CLI-WORKFLOW-UX-003
|
|
44
82
|
* @implements REQ-CLI-WORKFLOW-UX-003
|
|
45
83
|
* @design DES-CLI-WORKFLOW-UX-003
|
|
46
84
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
85
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-005
|
|
86
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-016 REQ-APPROVAL-DOMAIN-SCOPING-017 REQ-APPROVAL-DOMAIN-SCOPING-018
|
|
87
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
88
|
+
*/
|
|
89
|
+
export declare function requireApproval(root: string, stage: ApprovalStage, config: ApprovalConfig, domain?: ResolvedDomain): Promise<void>;
|
|
90
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-010
|
|
91
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-016 REQ-APPROVAL-DOMAIN-SCOPING-017 REQ-APPROVAL-DOMAIN-SCOPING-018
|
|
92
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
93
|
+
*/
|
|
94
|
+
export declare function resolveOwningDomainOrThrow(root: string, config: ApprovalConfig, slug: string): Promise<ResolvedDomain | undefined>;
|
|
95
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-011
|
|
96
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-005 REQ-APPROVAL-DOMAIN-SCOPING-013
|
|
97
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-004
|
|
98
|
+
*/
|
|
99
|
+
export declare function resolveNamedDomain(root: string, config: ApprovalConfig, domainName: string): Promise<ResolvedDomain>;
|
|
100
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-012
|
|
101
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-017
|
|
102
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
103
|
+
*/
|
|
104
|
+
export declare function resolveDesignFileDomain(root: string, config: ApprovalConfig, file: string): Promise<ResolvedDomain | undefined>;
|
|
105
|
+
/** @id CODE-APPROVAL-DOMAIN-SCOPING-013
|
|
106
|
+
* @implements REQ-APPROVAL-DOMAIN-SCOPING-016
|
|
107
|
+
* @design DES-APPROVAL-DOMAIN-SCOPING-005
|
|
108
|
+
*/
|
|
109
|
+
export declare function resolveRequirementDomain(root: string, config: ApprovalConfig, requirementId: string): Promise<ResolvedDomain | undefined>;
|
|
110
|
+
export declare function validateStageArtifacts(root: string, stage: ApprovalStage, domain?: ResolvedDomain): Promise<void>;
|