rcf-lite 0.18.0 → 0.20.0

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.
Files changed (142) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/bin/rcf.js +5 -0
  3. package/blueprints/application-api-rest/blueprint.json +12 -4
  4. package/blueprints/application-api-rest/contributions/adrs/adr-304-application-api-rest-logging.json +3 -3
  5. package/blueprints/application-api-rest/docs/topics.md +4 -2
  6. package/blueprints/application-error-handling/README.md +42 -0
  7. package/blueprints/application-error-handling/assets/schemas/error-record.schema.json +17 -0
  8. package/blueprints/application-error-handling/blueprint.json +27 -0
  9. package/blueprints/application-error-handling/contributions/adrs/adr-1701-application-error-handling-record-shape.json +25 -0
  10. package/blueprints/application-error-handling/contributions/adrs/adr-1702-application-error-handling-classification-vocabulary.json +20 -0
  11. package/blueprints/application-error-handling/contributions/adrs/adr-1703-application-error-handling-transport-mapping.json +20 -0
  12. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-001.json +15 -0
  13. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-002.json +15 -0
  14. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-003.json +15 -0
  15. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-004.json +15 -0
  16. package/blueprints/application-error-handling/contributions/tacs/tac-1701-application-error-handling-boundary.json +45 -0
  17. package/blueprints/application-error-handling/contributions/tacs/tac-1702-application-error-handling-record-factory.json +40 -0
  18. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16101.json +25 -0
  19. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16102.json +25 -0
  20. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16103.json +34 -0
  21. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16104.json +25 -0
  22. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16105.json +25 -0
  23. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16106.json +25 -0
  24. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16107.json +25 -0
  25. package/blueprints/application-error-handling/docs/topics.md +24 -0
  26. package/blueprints/application-error-handling/guide/application-error-handling.md +35 -0
  27. package/blueprints/application-spa/blueprint.json +12 -2
  28. package/blueprints/application-spa/docs/topics.md +2 -0
  29. package/blueprints/observability-logging/README.md +44 -0
  30. package/blueprints/observability-logging/assets/samples/log-line.json +13 -0
  31. package/blueprints/observability-logging/blueprint.json +27 -0
  32. package/blueprints/observability-logging/contributions/adrs/adr-1601-observability-logging-line-shape.json +25 -0
  33. package/blueprints/observability-logging/contributions/adrs/adr-1602-observability-logging-correlation-id-header.json +25 -0
  34. package/blueprints/observability-logging/contributions/adrs/adr-1603-observability-logging-redaction-categories.json +25 -0
  35. package/blueprints/observability-logging/contributions/adrs/adr-1604-observability-logging-level-vocabulary.json +20 -0
  36. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-001.json +15 -0
  37. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-002.json +15 -0
  38. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-003.json +15 -0
  39. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-004.json +15 -0
  40. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-005.json +15 -0
  41. package/blueprints/observability-logging/contributions/tacs/tac-1601-observability-logging-logger-factory.json +46 -0
  42. package/blueprints/observability-logging/contributions/tacs/tac-1602-observability-logging-redaction-boundary.json +27 -0
  43. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15101.json +34 -0
  44. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15102.json +43 -0
  45. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15103.json +34 -0
  46. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15104.json +25 -0
  47. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15105.json +34 -0
  48. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15106.json +25 -0
  49. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15107.json +25 -0
  50. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15108.json +25 -0
  51. package/blueprints/observability-logging/docs/topics.md +21 -0
  52. package/blueprints/observability-logging/guide/observability-logging.md +36 -0
  53. package/fixtures/canary-manifest.json +6 -6
  54. package/guidance/harness-template.md +8 -0
  55. package/guidance/managed/agent-instructions-block.hash +1 -1
  56. package/guidance/managed/agent-instructions-block.md +8 -0
  57. package/package.json +2 -2
  58. package/rcf/code-nodes/cn-077.json +14 -0
  59. package/rcf/code-nodes/cn-078.json +15 -0
  60. package/rcf/code-nodes/cn-079.json +14 -0
  61. package/rcf/code-nodes/cn-080.json +15 -0
  62. package/rcf/code-nodes/cn-081.json +15 -0
  63. package/rcf/code-nodes/cn-082.json +15 -0
  64. package/rcf/code-nodes/cn-083.json +14 -0
  65. package/rcf/code-nodes/cn-084.json +15 -0
  66. package/rcf/code-nodes/cn-085.json +14 -0
  67. package/rcf/code-nodes/cn-086.json +16 -0
  68. package/rcf/code-nodes/cn-087.json +14 -0
  69. package/rcf/code-nodes/cn-088.json +14 -0
  70. package/rcf/code-nodes/cn-089.json +14 -0
  71. package/rcf/code-nodes/cn-090.json +14 -0
  72. package/rcf/code-nodes/cn-091.json +14 -0
  73. package/rcf/code-nodes/cn-092.json +15 -0
  74. package/rcf/code-nodes/cn-093.json +15 -0
  75. package/rcf/code-nodes/cn-094.json +14 -0
  76. package/rcf/code-nodes/cn-095.json +14 -0
  77. package/rcf/code-nodes/cn-096.json +14 -0
  78. package/rcf/code-nodes/cn-097.json +14 -0
  79. package/rcf/code-nodes/cn-098.json +13 -0
  80. package/rcf/code-nodes/cn-099.json +13 -0
  81. package/rcf/code-nodes/cn-100.json +13 -0
  82. package/rcf/code-nodes/cn-101.json +13 -0
  83. package/rcf/code-nodes/cn-102.json +13 -0
  84. package/rcf/code-nodes/cn-103.json +13 -0
  85. package/rcf/code-nodes/cn-104.json +13 -0
  86. package/rcf/code-nodes/cn-105.json +13 -0
  87. package/rcf/evals/eval-001.json +55 -0
  88. package/rcf/fbs/fbs-028.json +27 -0
  89. package/rcf/fbs/fbs-029.json +27 -0
  90. package/rcf/fbs/fbs-030.json +27 -0
  91. package/rcf/fbs/fbs-031.json +27 -0
  92. package/rcf/fbs/fbs-032.json +27 -0
  93. package/rcf/fbs/fbs-033.json +27 -0
  94. package/rcf/fbs/fbs-034.json +27 -0
  95. package/rcf/fbs/fbs-035.json +18 -0
  96. package/rcf/requirements/req-013.json +22 -0
  97. package/rcf/requirements/req-014.json +22 -0
  98. package/rcf/requirements/req-015.json +21 -0
  99. package/rcf/requirements/req-016.json +37 -0
  100. package/rcf/test-suites/ts-038.json +41 -0
  101. package/rcf/test-suites/ts-039.json +41 -0
  102. package/rcf/test-suites/ts-040.json +57 -0
  103. package/rcf/test-suites/ts-041.json +57 -0
  104. package/rcf/test-suites/ts-042.json +57 -0
  105. package/rcf/test-suites/ts-043.json +49 -0
  106. package/rcf/test-suites/ts-044.json +41 -0
  107. package/rcf/test-suites/ts-045.json +46 -0
  108. package/rcf/user-stories/us-1301.json +43 -0
  109. package/rcf/user-stories/us-1302.json +43 -0
  110. package/rcf/user-stories/us-1401.json +43 -0
  111. package/rcf/user-stories/us-1402.json +43 -0
  112. package/rcf/user-stories/us-1403.json +43 -0
  113. package/rcf/user-stories/us-1404.json +43 -0
  114. package/rcf/user-stories/us-1501.json +43 -0
  115. package/rcf/user-stories/us-1601.json +37 -0
  116. package/releases/releases.yaml +20 -1
  117. package/src/blueprint/apply.js +8 -0
  118. package/src/blueprint/companions.js +485 -0
  119. package/src/blueprint/index.js +16 -0
  120. package/src/blueprint/loader.js +243 -1
  121. package/src/cli/blueprint.js +309 -0
  122. package/src/cli/create.js +14 -0
  123. package/src/cli/eval-coverage.js +221 -0
  124. package/src/cli/eval.js +43 -0
  125. package/src/cli/finalise.js +64 -0
  126. package/src/cli/help.js +4 -0
  127. package/src/cli/validate.js +7 -0
  128. package/src/core/store/ids.js +5 -1
  129. package/src/core/store/init.js +4 -0
  130. package/src/core/store/loader.js +4 -0
  131. package/src/core/store/validator.js +8 -1
  132. package/src/core/store/walker.js +71 -2
  133. package/src/core/store/writer.js +4 -0
  134. package/src/eval/judge.js +338 -0
  135. package/src/finalise/index.js +8 -0
  136. package/src/finalise/ingest.js +27 -0
  137. package/src/finalise/ship-without-eval.js +123 -0
  138. package/src/query/eval-coverage.js +162 -0
  139. package/src/verify/chain/index.js +67 -0
  140. package/src/verify/cli/run.js +15 -0
  141. package/src/verify/engine/index.js +10 -0
  142. package/src/verify/verdict/index.js +46 -0
@@ -0,0 +1,37 @@
1
+ {
2
+ "createdAt": "2026-09-04T16:21:15.850Z",
3
+ "updatedAt": "2026-09-04T16:22:11.909Z",
4
+ "description": "rcf-schemas 0.6.0 lands the EVAL doc type and the AC-level determinism marker. rcf-lite consumes both: rcf audit eval coverage as a sibling of rcf audit coverage, EVAL-MISSING and EVAL-BELOW-THRESHOLD as per-AC verdicts on the verify report, finalise refusal with a mandatory-reason ship-without-eval opt-out, and a determinism flag on rcf define create ac plus the LLM-as-judge subprocess spawn wired to a runRecord entry on the EVAL doc. The eval-node discipline lives in the schema tier; rcf-lite is the first consumer to make it observable at every stage of the build cycle.",
5
+ "reqId": "REQ-016",
6
+ "prdId": "PRD-001",
7
+ "title": "rcf-schemas 0.6.0 EVAL node: consumer wiring in rcf-lite (audit / verify / finalise / define)",
8
+ "category": "functional",
9
+ "domain": "schemas",
10
+ "priority": "must",
11
+ "version": "0.1.0",
12
+ "status": "draft",
13
+ "shapeClassification": {
14
+ "shapes": [
15
+ "persistence"
16
+ ],
17
+ "reason": "keyword-scan",
18
+ "classifiedAt": "2026-09-04T16:21:15.868Z",
19
+ "signals": [
20
+ {
21
+ "source": "title",
22
+ "shape": "persistence",
23
+ "match": "schema"
24
+ },
25
+ {
26
+ "source": "description",
27
+ "shape": "persistence",
28
+ "match": "schema"
29
+ },
30
+ {
31
+ "source": "description",
32
+ "shape": "persistence",
33
+ "match": "schema"
34
+ }
35
+ ]
36
+ }
37
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "id": "TS-038",
3
+ "usId": "US-1301",
4
+ "title": "observability-logging v1.0.0 ships on the core shelf with the ratified anatomy and applies clean",
5
+ "purpose": "Cover the three ACs on US-1301: shipped anatomy (blueprint.json + contributions + README + guide + docs/topics.md + assets), clean apply into a fresh fixture, and shelf-canonical logging global topic on ADR-1601 with providesRoles logging.",
6
+ "testLevel": "integration",
7
+ "acIds": [
8
+ "AC-1301-1",
9
+ "AC-1301-2",
10
+ "AC-1301-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-038-blueprint-json-fields",
15
+ "acId": "AC-1301-1",
16
+ "description": "blueprints/observability-logging/blueprint.json declares slug, version 1.0.0, category observability, providesRoles [\"logging\"], and includes contributions for REQ-001..005, US-15101..15108, TAC-1601, TAC-1602 and ADR-1601..1604 with ADR-1601 carrying scope global and topic logging.",
17
+ "testPointer": "test/blueprint/observability-logging-anatomy.test.js::observability-logging: blueprint.json declares the ratified shape (TC-038-blueprint-json-fields)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-038-clean-apply",
23
+ "acId": "AC-1301-2",
24
+ "description": "rcf define blueprint add against a fresh fixture applies observability-logging cleanly (exit 0), records manifest.blueprints[] with slug observability-logging at 1.0.0, and writes rcf/adr/adr-1601-observability-logging-line-shape.json.",
25
+ "testPointer": "test/blueprint/observability-logging-anatomy.test.js::observability-logging: apply into a fresh fixture succeeds and writes the namespaced contributions (TC-038-clean-apply)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-038-anatomy-and-topics",
31
+ "acId": "AC-1301-3",
32
+ "description": "The blueprint anatomy is complete: README.md carries the Apply block and Known mechanism-reach gaps section; docs/topics.md names the logging global topic string and records the 15101-15899 band with 16xx suffix block; guide/observability-logging.md exists.",
33
+ "testPointer": "test/blueprint/observability-logging-anatomy.test.js::observability-logging: anatomy files exist with the required sections (TC-038-anatomy-and-topics)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ }
37
+ ],
38
+ "status": "draft",
39
+ "createdAt": "2026-09-04T12:20:00Z",
40
+ "updatedAt": "2026-09-04T12:20:00Z"
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "id": "TS-039",
3
+ "usId": "US-1302",
4
+ "title": "application-error-handling v1.0.0 ships on the core shelf with providesRoles errorHandling and mints the errorHandling global topic distinct from errorEnvelope",
5
+ "purpose": "Cover the three ACs on US-1302: shipped anatomy and blueprint.json fields, clean apply into a fresh fixture, and errorHandling vs errorEnvelope topic distinction.",
6
+ "testLevel": "integration",
7
+ "acIds": [
8
+ "AC-1302-1",
9
+ "AC-1302-2",
10
+ "AC-1302-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-039-blueprint-json-fields",
15
+ "acId": "AC-1302-1",
16
+ "description": "blueprints/application-error-handling/blueprint.json declares slug, version 1.0.0, category application, providesRoles [\"errorHandling\"], and includes contributions for REQ-001..004, US-16101..16107, TAC-1701, TAC-1702 and ADR-1701..1703 with ADR-1701 carrying scope global and topic errorHandling.",
17
+ "testPointer": "test/blueprint/application-error-handling-anatomy.test.js::application-error-handling: blueprint.json declares the ratified shape (TC-039-blueprint-json-fields)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-039-clean-apply",
23
+ "acId": "AC-1302-2",
24
+ "description": "rcf define blueprint add applies application-error-handling cleanly into a fresh fixture, records manifest.blueprints[] with the slug at 1.0.0, and writes rcf/adr/adr-1701-application-error-handling-record-shape.json.",
25
+ "testPointer": "test/blueprint/application-error-handling-anatomy.test.js::application-error-handling: apply into a fresh fixture succeeds and writes the namespaced contributions (TC-039-clean-apply)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-039-topics-distinct",
31
+ "acId": "AC-1302-3",
32
+ "description": "docs/topics.md distinguishes errorHandling from errorEnvelope (errorHandling internal record and boundary; errorEnvelope stays with application-api-rest as REST wire shape) and reserves the 16101-16899 band with 17xx suffix block.",
33
+ "testPointer": "test/blueprint/application-error-handling-anatomy.test.js::application-error-handling: docs/topics.md distinguishes errorHandling from errorEnvelope (TC-039-topics-distinct)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ }
37
+ ],
38
+ "status": "draft",
39
+ "createdAt": "2026-09-04T12:20:00Z",
40
+ "updatedAt": "2026-09-04T12:20:00Z"
41
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "id": "TS-040",
3
+ "usId": "US-1401",
4
+ "title": "Loader accepts providesRoles and suggestedCompanions with shape validation and paired-ADR gate",
5
+ "purpose": "Cover the three ACs on US-1401: accepted shape (both fields optional and independent), refusal shapes for camelCase pattern / empty reason / em-dash / emoji, paired-scope-global-ADR gate.",
6
+ "testLevel": "unit",
7
+ "acIds": [
8
+ "AC-1401-1",
9
+ "AC-1401-2",
10
+ "AC-1401-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-040-loader-accepts-both",
15
+ "acId": "AC-1401-1",
16
+ "description": "loadBlueprint against a fixture declaring providesRoles: [\"logging\"] and suggestedCompanions: [{role: \"logging\", reason: \"...\"}] returns the fields on the LoadedBlueprint object; a fixture declaring neither also loads clean.",
17
+ "testPointer": "test/blueprint/loader-companions.test.js::loader accepts and preserves providesRoles and suggestedCompanions (AC-1401-1)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-040-refuse-bad-camelcase",
23
+ "acId": "AC-1401-2",
24
+ "description": "loadBlueprint refuses a fixture declaring providesRoles: [\"Logging\"] (upper camel) with rcfError kind validation naming providesRoles[0] and the offending value.",
25
+ "testPointer": "test/blueprint/loader-companions.test.js::loader refuses providesRoles value that fails the lower camelCase pattern (AC-1401-2)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-040-refuse-empty-reason",
31
+ "acId": "AC-1401-2",
32
+ "description": "loadBlueprint refuses a fixture with suggestedCompanions entry whose reason is empty or whitespace-only.",
33
+ "testPointer": "test/blueprint/loader-companions.test.js::loader refuses suggestedCompanions entry with empty or whitespace-only reason (AC-1401-2)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ },
37
+ {
38
+ "id": "TC-040-refuse-em-dash-and-emoji",
39
+ "acId": "AC-1401-2",
40
+ "description": "loadBlueprint refuses a fixture with an em-dash (U+2014) or an emoji in the reason string.",
41
+ "testPointer": "test/blueprint/loader-companions.test.js::loader refuses em-dash in suggestedCompanions reason (AC-1401-2)",
42
+ "status": "pending",
43
+ "scope": "library"
44
+ },
45
+ {
46
+ "id": "TC-040-paired-adr-required",
47
+ "acId": "AC-1401-3",
48
+ "description": "loadBlueprint refuses a fixture declaring providesRoles: [\"logging\"] but no scope:global ADR carrying topic 'logging' with the exact paired-ADR refusal message.",
49
+ "testPointer": "test/blueprint/loader-companions.test.js::loader refuses providesRoles without a paired scope:global ADR on the topic string (AC-1401-3)",
50
+ "status": "pending",
51
+ "scope": "library"
52
+ }
53
+ ],
54
+ "status": "draft",
55
+ "createdAt": "2026-09-04T12:20:00Z",
56
+ "updatedAt": "2026-09-04T12:20:00Z"
57
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "id": "TS-041",
3
+ "usId": "US-1402",
4
+ "title": "rcf define blueprint add prints resolved companion suggestions and honours --companion / --no-companion-suggestions with persistence to rcf/companions.json",
5
+ "purpose": "Cover the three ACs on US-1402: apply-time suggestion block and its suppression, --companion selectors and refusal for non-providers, companions.json shape and pin overwrite behaviour.",
6
+ "testLevel": "integration",
7
+ "acIds": [
8
+ "AC-1402-1",
9
+ "AC-1402-2",
10
+ "AC-1402-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-041-suggestion-block",
15
+ "acId": "AC-1402-1",
16
+ "description": "rcf define blueprint add application-api-rest into a fresh fixture prints the header line and one line per suggested role with the origin annotation; the apply does not adopt any companion.",
17
+ "testPointer": "test/cli/blueprint-companions.test.js::apply prints resolved companion suggestion block after success (TC-041-suggestion-block)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-041-no-suggestions-flag",
23
+ "acId": "AC-1402-1",
24
+ "description": "rcf define blueprint add application-api-rest --no-companion-suggestions succeeds and produces no suggestion block on stdout.",
25
+ "testPointer": "test/cli/blueprint-companions.test.js::--no-companion-suggestions suppresses the block (TC-041-no-suggestions-flag)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-041-companion-flag-writes-pin",
31
+ "acId": "AC-1402-2",
32
+ "description": "rcf define blueprint add application-api-rest --companion logging=observability-logging --companion errorHandling=application-error-handling writes rcf/companions.json with both pins carrying pinnedAt.",
33
+ "testPointer": "test/cli/blueprint-companions.test.js::--companion selectors write rcf/companions.json pins with pinnedAt (TC-041-companion-flag-writes-pin)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ },
37
+ {
38
+ "id": "TC-041-companion-flag-non-provider",
39
+ "acId": "AC-1402-2",
40
+ "description": "rcf define blueprint add --companion logging=observability-essentials (which does not declare providesRoles containing logging) refuses exit 2 with the specified message shape.",
41
+ "testPointer": "test/cli/blueprint-companions.test.js::--companion naming a non-provider refuses exit 2 with no side effects (TC-041-companion-flag-non-provider)",
42
+ "status": "pending",
43
+ "scope": "library"
44
+ },
45
+ {
46
+ "id": "TC-041-pin-file-shape-and-overwrite",
47
+ "acId": "AC-1402-3",
48
+ "description": "rcf/companions.json is created lazily with schemaVersion 1 and current-pin-only shape; a re-run with a different --companion value overwrites the pin and prints the pin-transition stderr line.",
49
+ "testPointer": "test/cli/blueprint-companions.test.js::rcf/companions.json shape and pin overwrite prints transition line (TC-041-pin-file-shape-and-overwrite)",
50
+ "status": "pending",
51
+ "scope": "library"
52
+ }
53
+ ],
54
+ "status": "draft",
55
+ "createdAt": "2026-09-04T12:20:00Z",
56
+ "updatedAt": "2026-09-04T12:20:00Z"
57
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "id": "TS-042",
3
+ "usId": "US-1403",
4
+ "title": "rcf define blueprint companions <slug>|set|unset verb: text output, --json envelope, exit codes",
5
+ "purpose": "Cover the three ACs on US-1403: <slug> resolution printing with origin annotations, set/unset pin round-trip and refusals, --json envelope on all three sub-verbs.",
6
+ "testLevel": "integration",
7
+ "acIds": [
8
+ "AC-1403-1",
9
+ "AC-1403-2",
10
+ "AC-1403-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-042-companions-slug-text",
15
+ "acId": "AC-1403-1",
16
+ "description": "rcf define blueprint companions application-api-rest with application-api-rest applied prints the header and one line per role with the origin annotations already-applied / shelf-fallback / registered-library.",
17
+ "testPointer": "test/cli/blueprint-companions.test.js::rcf define blueprint companions <slug> prints resolved companions with origin (TC-042-companions-slug-text)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-042-companions-slug-not-applied",
23
+ "acId": "AC-1403-1",
24
+ "description": "rcf define blueprint companions <slug> refuses exit 2 when the named slug is not applied on the project.",
25
+ "testPointer": "test/cli/blueprint-companions.test.js::rcf define blueprint companions refuses when slug is not applied (TC-042-companions-slug-not-applied)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-042-companions-set-unset-round-trip",
31
+ "acId": "AC-1403-2",
32
+ "description": "rcf define blueprint companions set logging observability-logging writes companions.json; rcf define blueprint companions unset logging removes the entry; an unset without a pin refuses exit 2.",
33
+ "testPointer": "test/cli/blueprint-companions.test.js::companions set writes pin and unset removes it; unset without pin refuses (TC-042-companions-set-unset-round-trip)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ },
37
+ {
38
+ "id": "TC-042-companions-set-refuses-non-provider",
39
+ "acId": "AC-1403-2",
40
+ "description": "rcf define blueprint companions set logging observability-essentials refuses exit 2 because observability-essentials does not declare providesRoles containing logging.",
41
+ "testPointer": "test/cli/blueprint-companions.test.js::companions set refuses non-provider slug (TC-042-companions-set-refuses-non-provider)",
42
+ "status": "pending",
43
+ "scope": "library"
44
+ },
45
+ {
46
+ "id": "TC-042-companions-json-envelope",
47
+ "acId": "AC-1403-3",
48
+ "description": "rcf define blueprint companions application-api-rest --json emits {slug, suggestions: [{role, provider, origin, notes}]} preserving the order of suggestedCompanions[].",
49
+ "testPointer": "test/cli/blueprint-companions.test.js::--json emits machine-readable envelope preserving suggestedCompanions order (TC-042-companions-json-envelope)",
50
+ "status": "pending",
51
+ "scope": "library"
52
+ }
53
+ ],
54
+ "status": "draft",
55
+ "createdAt": "2026-09-04T12:20:00Z",
56
+ "updatedAt": "2026-09-04T12:20:00Z"
57
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "id": "TS-043",
3
+ "usId": "US-1404",
4
+ "title": "Resolution rule tier ladder, two-libraries refusal exit 3, and validate refusal for unresolvable pin",
5
+ "purpose": "Cover the three ACs on US-1404: deterministic tier ladder (applied > registered library > core shelf) with pin override, two-libraries-one-role refusal message shape on both add and companions verb, validate refusal for a pin naming no known provider.",
6
+ "testLevel": "integration",
7
+ "acIds": [
8
+ "AC-1404-1",
9
+ "AC-1404-2",
10
+ "AC-1404-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-043-resolver-tier-ladder",
15
+ "acId": "AC-1404-1",
16
+ "description": "The resolveCompanions function returns origin already-applied when a provider is applied, registered-library-<prefix> when one library provides it, shelf-fallback when only the core shelf provides it, and pinned when rcf/companions.json overrides.",
17
+ "testPointer": "test/blueprint/companions-resolver.test.js::resolver returns shelf-fallback when only the core shelf provides the role",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-043-two-libraries-refuse-exit-3",
23
+ "acId": "AC-1404-2",
24
+ "description": "With two registered libraries both providing role logging and no pin, rcf define blueprint add on a service blueprint refuses exit 3 with the ambiguous-role message naming both library slugs and the three resolution paths verbatim.",
25
+ "testPointer": "test/cli/blueprint-companions.test.js::two libraries providing one role refuse exit 3 with three-path resolution message (TC-043-two-libraries-refuse-exit-3)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-043-two-libraries-on-companions-verb",
31
+ "acId": "AC-1404-2",
32
+ "description": "The same two-libraries-one-role case on rcf define blueprint companions <slug> refuses exit 3 with the same three-path resolution message.",
33
+ "testPointer": "test/cli/blueprint-companions.test.js::rcf define blueprint companions refuses exit 3 when two libraries provide same role (TC-043-two-libraries-on-companions-verb)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ },
37
+ {
38
+ "id": "TC-043-validate-refuses-unresolvable-pin",
39
+ "acId": "AC-1404-3",
40
+ "description": "rcf define validate refuses exit 3 when rcf/companions.json pins a role to a slug that no applied blueprint, no registered library, and no shelf blueprint provides; message shape names the exact role and slug.",
41
+ "testPointer": "test/cli/validate-companions-pin.test.js::validate refuses exit 3 when a companions.json pin names an unresolvable provider (TC-043-validate-refuses-unresolvable-pin)",
42
+ "status": "pending",
43
+ "scope": "library"
44
+ }
45
+ ],
46
+ "status": "draft",
47
+ "createdAt": "2026-09-04T12:20:00Z",
48
+ "updatedAt": "2026-09-04T12:20:00Z"
49
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "id": "TS-044",
3
+ "usId": "US-1501",
4
+ "title": "Loader validates standardsTrace with the standardsTraceClause discipline; refuses missing clause without cross-checking severity",
5
+ "purpose": "Cover the three ACs on US-1501: loader acceptance of standardsTrace/recommendedDefault/elicited/standardsTraceClause, refusal message shape when standardsTrace is declared and any ADR lacks a standardsTraceClause, and no-cross-check on MUST-to-kind mapping.",
6
+ "testLevel": "unit",
7
+ "acIds": [
8
+ "AC-1501-1",
9
+ "AC-1501-2",
10
+ "AC-1501-3"
11
+ ],
12
+ "testCases": [
13
+ {
14
+ "id": "TC-044-loader-accepts-standards-fields",
15
+ "acId": "AC-1501-1",
16
+ "description": "loadBlueprint on a fixture with standardsTrace [{id: WSD-001, version: 2026-05}] and one ADR contribution carrying recommendedDefault true and standardsTraceClause 'WSD-001 clause 3.1' returns the fields on the LoadedBlueprint object; no rcfError.",
17
+ "testPointer": "test/blueprint/loader-standards-trace.test.js::loader accepts standardsTrace and recommendedDefault/elicited/standardsTraceClause (AC-1501-1)",
18
+ "status": "pending",
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "TC-044-loader-refuses-missing-clause",
23
+ "acId": "AC-1501-2",
24
+ "description": "loadBlueprint refuses a fixture declaring standardsTrace but with one ADR contribution missing standardsTraceClause; rcfError kind validation with the exact refusal message shape.",
25
+ "testPointer": "test/blueprint/loader-standards-trace.test.js::loader refuses missing standardsTraceClause when standardsTrace is declared (AC-1501-2)",
26
+ "status": "pending",
27
+ "scope": "library"
28
+ },
29
+ {
30
+ "id": "TC-044-no-cross-check-and-sentinel",
31
+ "acId": "AC-1501-3",
32
+ "description": "The two new core companion blueprints (observability-logging, application-error-handling), which declare NO standardsTrace, load clean regardless of standardsTraceClause presence; a fixture with standardsTrace declared and every ADR carrying 'generic enterprise practice' loads clean; the loader does not refuse a MUST-marked ADR (no cross-check of clause severity to kind, per amendment A2).",
33
+ "testPointer": "test/blueprint/loader-standards-trace.test.js::no cross-check on severity; sentinel and no-standardsTrace baseline both load clean (AC-1501-3)",
34
+ "status": "pending",
35
+ "scope": "library"
36
+ }
37
+ ],
38
+ "status": "draft",
39
+ "createdAt": "2026-09-04T12:20:00Z",
40
+ "updatedAt": "2026-09-04T12:20:00Z"
41
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "createdAt": "2026-09-04T16:22:23.766Z",
3
+ "updatedAt": "2026-09-04T17:21:35.618Z",
4
+ "purpose": "Cover the four ACs on US-1601 via the unit and integration suites landed in this train. L1 through L3 are deterministic tests over pure or seam-injected code paths; L4 tests the judge invocation shape via a stubbed spawn seam (a real subprocess round-trip is exercised out-of-band as the section 11 real-claude smoke).",
5
+ "testLevel": "integration",
6
+ "acIds": [
7
+ "AC-1601-1",
8
+ "AC-1601-2",
9
+ "AC-1601-3",
10
+ "AC-1601-4"
11
+ ],
12
+ "id": "TS-045",
13
+ "usId": "US-1601",
14
+ "title": "rcf-lite consumer wiring for the rcf-schemas 0.6.0 EVAL node",
15
+ "testCases": [
16
+ {
17
+ "id": "TC-045-computeevalcoverage-across-the-four",
18
+ "acId": "AC-1601-1",
19
+ "description": "computeEvalCoverage across the four outcome buckets (covered, covered-optional, missing, not-required) and the classifyEvalDoc pending/superseded/resolving classification",
20
+ "status": "pending",
21
+ "testPointer": "test/query/eval-coverage.test.js::nonDeterministic AC without a bound EVAL reports missing and fails the gate"
22
+ },
23
+ {
24
+ "id": "TC-045-per-ac-verdicts-carries-the-two-new-eval",
25
+ "acId": "AC-1601-2",
26
+ "description": "PER_AC_VERDICTS carries the two new EVAL classes; evalPerAcVerdict returns null for deterministic ACs; fires EVAL-MISSING when nonDeterministic AC has no resolving EVAL; fires EVAL-BELOW-THRESHOLD on a failing run",
27
+ "status": "pending",
28
+ "testPointer": "test/verify/verdict/eval-per-ac.test.js::derivePerAcVerdicts folds EVAL classes alongside the pre-existing per-AC verdicts"
29
+ },
30
+ {
31
+ "id": "TC-045-findevalrefusalacs-and",
32
+ "acId": "AC-1601-3",
33
+ "description": "findEvalRefusalAcs and reportHasEvalRefusal read the two EVAL classes off perAcVerdicts[]; composeShipWithoutEvalRecord carries the operator reason and declared per-AC verdicts; nextShipWithoutEvalId increments monotonically",
34
+ "status": "pending",
35
+ "testPointer": "test/cli/finalise-eval-refusal.test.js::finalise --ship-without-eval \"harness offline\" exits 0 and appends a monotonic swe-* record on manifest.shipWithoutEval[]"
36
+ },
37
+ {
38
+ "id": "TC-045-runonecase-spawns-the-invoker-claude-or",
39
+ "acId": "AC-1601-4",
40
+ "description": "runOneCase spawns the invoker (claude or codex) via the seam, validates response against the declared schema, composeRunRecord verdict resolves to pass on met threshold and fail on critical criterion failure",
41
+ "status": "pending",
42
+ "testPointer": "test/eval/judge.test.js::runOneCase returns the parsed graded envelope on a valid response"
43
+ }
44
+ ],
45
+ "status": "draft"
46
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "usId": "US-1301",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-013",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Core shelf ships observability-logging v1.0.0 with providesRoles logging and the shelf-canonical logging global topic",
8
+ "asA": "operator running rcf define blueprint add on a fresh project that needs a general-enterprise-practice logging contract",
9
+ "iWant": "the shipped core shelf to carry an observability-logging blueprint (v1.0.0) that provides the logging role, mints the logging global topic on ADR-1601, and applies cleanly into a fixture project alongside every other shipped shelf blueprint",
10
+ "soThat": "a project falls back to a sensible logging contract without registering any library, the mechanism in REQ-014 has a shelf provider to resolve to, and the logging global topic has one owner on the shelf",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1301-1",
14
+ "description": "`blueprints/observability-logging/blueprint.json` exists with `slug: \"observability-logging\"`, `version: \"1.0.0\"`, `category: \"observability\"`, `providesRoles: [\"logging\"]`, and a contributions list carrying five REQs (`observability-logging-REQ-001` through `-REQ-005`), user stories in the 15101-15899 band (at least `-US-15101` through `-US-15108`), TACs `TAC-1601-observability-logging-logger-factory` and `TAC-1602-observability-logging-redaction-boundary`, and ADRs `ADR-1601` through `ADR-1604` including `ADR-1601-observability-logging-line-shape` with `scope: \"global\", topic: \"logging\"`.",
15
+ "given": "the shipped core shelf at packages/rcf-lite/blueprints/observability-logging (staged from the top-level blueprints/ directory)",
16
+ "when": "the loader reads blueprint.json and enumerates contributions[]",
17
+ "then": "the fields resolve to the values above and jq queries against blueprint.json return them verbatim",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1301-2",
23
+ "description": "`rcf define blueprint add <path>/blueprints/observability-logging` applied into a fresh fixture project with no prior applied blueprints succeeds (exit 0), writes `manifest.blueprints[]` with slug `observability-logging`, and copies the namespaced contribution files under `rcf/req/`, `rcf/userStory/`, `rcf/tac/` and `rcf/adr/`.",
24
+ "given": "a fresh fixture project initialised via `rcf init` with no applied blueprints",
25
+ "when": "the operator runs `rcf define blueprint add <path-to>/blueprints/observability-logging`",
26
+ "then": "the exit code is 0, `manifest.blueprints[]` lists observability-logging at version 1.0.0, and `rcf/adr/adr-1601-observability-logging-line-shape.json` exists on disk",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1301-3",
32
+ "description": "The blueprint anatomy is complete: `README.md`, `guide/observability-logging.md`, `docs/topics.md` and `assets/` are present at the blueprint root; the README carries an `Apply` block and a `Known mechanism-reach gaps` section; `docs/topics.md` names the `logging` global topic string with the shelf band 15101-15899 and 16xx suffix block recorded.",
33
+ "given": "the blueprint source directory on disk",
34
+ "when": "the reviewer walks the anatomy",
35
+ "then": "every named file exists, the docs/topics.md table includes the observability-logging row, and the README carries the two required sections",
36
+ "testable": true,
37
+ "scope": "library"
38
+ }
39
+ ],
40
+ "tacIds": [],
41
+ "createdAt": "2026-09-04T12:20:00Z",
42
+ "updatedAt": "2026-09-04T12:20:00Z"
43
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "usId": "US-1302",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-013",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Core shelf ships application-error-handling v1.0.0 with providesRoles errorHandling and mints the errorHandling global topic",
8
+ "asA": "operator running rcf define blueprint add on a fresh project that needs a transport-agnostic error-handling contract",
9
+ "iWant": "the shipped core shelf to carry an application-error-handling blueprint (v1.0.0) that provides the errorHandling role, mints the errorHandling global topic on ADR-1701 (distinct from errorEnvelope), and applies cleanly into a fixture project",
10
+ "soThat": "a project falls back to a sensible error-handling contract without registering any library, and the internal error record shape sits one project decision above any transport-specific error-envelope decision",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1302-1",
14
+ "description": "`blueprints/application-error-handling/blueprint.json` exists with `slug: \"application-error-handling\"`, `version: \"1.0.0\"`, `category: \"application\"`, `providesRoles: [\"errorHandling\"]`, and a contributions list carrying four REQs (`application-error-handling-REQ-001` through `-REQ-004`), user stories in the 16101-16899 band (at least `-US-16101` through `-US-16107`), TACs `TAC-1701-application-error-handling-boundary` and `TAC-1702-application-error-handling-record-factory`, and ADRs `ADR-1701` through `ADR-1703` including `ADR-1701-application-error-handling-record-shape` with `scope: \"global\", topic: \"errorHandling\"`.",
15
+ "given": "the shipped core shelf at packages/rcf-lite/blueprints/application-error-handling (staged from the top-level blueprints/ directory)",
16
+ "when": "the loader reads blueprint.json and enumerates contributions[]",
17
+ "then": "the fields resolve to the values above and jq queries return them verbatim",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1302-2",
23
+ "description": "`rcf define blueprint add <path>/blueprints/application-error-handling` applied into a fresh fixture project with no prior applied blueprints succeeds (exit 0), writes `manifest.blueprints[]` with slug `application-error-handling`, and copies the namespaced contribution files.",
24
+ "given": "a fresh fixture project initialised via `rcf init` with no applied blueprints",
25
+ "when": "the operator runs `rcf define blueprint add <path-to>/blueprints/application-error-handling`",
26
+ "then": "the exit code is 0, `manifest.blueprints[]` lists application-error-handling at version 1.0.0, and `rcf/adr/adr-1701-application-error-handling-record-shape.json` exists on disk",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1302-3",
32
+ "description": "The `errorHandling` topic is DISTINCT from `errorEnvelope`; the blueprint's docs/topics.md names both, distinguishes them (errorHandling is the internal record shape and uncaught-exception boundary; errorEnvelope stays with application-api-rest as the REST wire shape), and reserves the 16101-16899 band and 17xx suffix block for the shelf-wide registry.",
33
+ "given": "the blueprint's docs/topics.md file",
34
+ "when": "the reviewer reads the topic table",
35
+ "then": "the errorHandling and errorEnvelope rows are both present, distinct, and the band registry row is recorded",
36
+ "testable": true,
37
+ "scope": "library"
38
+ }
39
+ ],
40
+ "tacIds": [],
41
+ "createdAt": "2026-09-04T12:20:00Z",
42
+ "updatedAt": "2026-09-04T12:20:00Z"
43
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "usId": "US-1401",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-014",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Loader accepts and validates providesRoles[] and suggestedCompanions[] on blueprint.json (shape + camelCase + paired-ADR + reason-string)",
8
+ "asA": "blueprint author declaring a companion suggestion or a role provided on a shipped blueprint",
9
+ "iWant": "the loader to accept two additive top-level fields on blueprint.json, validate their shape at load time, and refuse a mis-authored file before the tree is touched",
10
+ "soThat": "a service blueprint can name the roles it recommends and a provider blueprint can name the roles it provides, and mis-shaped or unpaired declarations never reach apply",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1401-1",
14
+ "description": "The loader accepts optional top-level `providesRoles` (non-empty array of lower camelCase strings on the pattern `^[a-z][a-zA-Z0-9]*$`) and optional top-level `suggestedCompanions` (non-empty array of `{role, reason}` objects; `role` is a lower camelCase string; `reason` is a non-empty string with no em-dashes and no emojis). Both fields are independent (a blueprint may provide a role AND suggest another; a blueprint may declare neither). Existing shelf blueprints (application-spa v1.4.0 baseline, observability-essentials v2.0.0, etc.) that declare neither still load clean.",
15
+ "given": "a blueprint.json declaring `providesRoles: [\"logging\"]` and `suggestedCompanions: [{role: \"logging\", reason: \"...\"}]`",
16
+ "when": "the loader parses the file",
17
+ "then": "the LoadedBlueprint object carries both fields verbatim and returns no rcfError; a blueprint declaring neither loads clean",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1401-2",
23
+ "description": "The loader refuses (rcfError kind `validation`, exit 2 at the CLI edge) each of: a `providesRoles` value that fails the lower camelCase pattern (message names the offending index and value); a `suggestedCompanions` entry with a non-string or empty `role`; a `suggestedCompanions` entry with a missing, empty, or whitespace-only `reason`; a `suggestedCompanions` entry whose `reason` contains an em-dash (U+2014) or an emoji.",
24
+ "given": "four separate mis-authored blueprint.json fixtures, one per refusal shape",
25
+ "when": "the loader parses each",
26
+ "then": "each returns an rcfError of kind `validation` with a message naming the offending field and (for arrays) the index",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1401-3",
32
+ "description": "A blueprint that declares a role in `providesRoles[]` MUST also carry a `scope: \"global\"` ADR contribution whose `topic` string equals the role name; the loader refuses otherwise with `providesRoles[] names '<role>' but no scope:global ADR carries topic '<role>'.` and exits 2 at the CLI edge.",
33
+ "given": "a fixture blueprint with `providesRoles: [\"logging\"]` and no ADR contribution carrying `scope: \"global\", topic: \"logging\"`",
34
+ "when": "the loader parses the file",
35
+ "then": "the loader returns an rcfError of kind `validation` with the paired-ADR message exactly as specified",
36
+ "testable": true,
37
+ "scope": "library"
38
+ }
39
+ ],
40
+ "tacIds": [],
41
+ "createdAt": "2026-09-04T12:20:00Z",
42
+ "updatedAt": "2026-09-04T12:20:00Z"
43
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "usId": "US-1402",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-014",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "`rcf define blueprint add` prints resolved companion suggestions and accepts --companion selectors that persist to rcf/companions.json",
8
+ "asA": "operator running rcf define blueprint add on a service blueprint that declares suggestedCompanions[]",
9
+ "iWant": "the apply to print the resolved companion set as a suggestion block after a successful apply, and to accept `--companion <role>=<slug>` selectors that record my choice to rcf/companions.json for future runs",
10
+ "soThat": "the mechanism surfaces the suggestion at the moment of the apply, my explicit selection at apply time survives to future re-runs without repeating the flag, and the apply itself never adopts a companion on my behalf",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1402-1",
14
+ "description": "After `rcf define blueprint add <service-slug>` succeeds and the service blueprint declares `suggestedCompanions[]`, stdout carries a block: a header line `Suggested companions this blueprint recommends alongside it:` followed by one line per suggested role in the shape ` <role> -> <resolved-provider> (<origin>)`, where origin reads `registered library '<prefix>'` or `shelf fallback` or `already applied`, and a footer line `Apply either with: rcf define blueprint add <slug>`. The apply itself does not adopt any companion (`manifest.blueprints[]` contains only the service blueprint and any prior applies). `--no-companion-suggestions` suppresses the block entirely and every other apply behaviour is unchanged.",
15
+ "given": "a fixture project with application-api-rest v2.1.0 (or later) applied cleanly and no core companions applied",
16
+ "when": "the operator runs `rcf define blueprint add <path-to>/blueprints/application-api-rest`",
17
+ "then": "the suggestion block prints for `logging` and `errorHandling` roles, manifest.blueprints[] carries only application-api-rest, and passing `--no-companion-suggestions` on the same command produces no suggestion block",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1402-2",
23
+ "description": "`rcf define blueprint add <service-slug> --companion <role>=<slug>` (repeatable) accepts `<libraryPrefix>:<slug>` for a library provider or a bare kebab slug for a shelf provider, validates that the named provider blueprint's `providesRoles[]` contains the role, refuses with exit 2 (`--companion <role>=<slug>: blueprint '<slug>' does not declare providesRoles containing '<role>'.`) when it does not, and writes the accepted choices to `rcf/companions.json` under `roles.<role>.provider` with a `pinnedAt` ISO-8601 timestamp.",
24
+ "given": "a fixture project with application-api-rest applying and the shelf observability-logging blueprint available",
25
+ "when": "the operator runs `rcf define blueprint add <path-to>/blueprints/application-api-rest --companion logging=observability-logging --companion errorHandling=application-error-handling`",
26
+ "then": "the exit code is 0, `rcf/companions.json` exists with `roles.logging.provider = \"observability-logging\"` and `roles.errorHandling.provider = \"application-error-handling\"`, and `--companion logging=observability-essentials` (a non-provider) refuses exit 2 with the specified message",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1402-3",
32
+ "description": "`rcf/companions.json` is created lazily on the first pin (no file when no pins exist), rides git, is human-readable JSON with `schemaVersion: 1`, and carries only the current pin per role (no per-apply history per amendment A1). A re-run of the same `rcf define blueprint add ... --companion ...` command overwrites the pin's `pinnedAt` timestamp but keeps the same provider; a `--companion` naming a different provider than the current pin overwrites the pin and prints one stderr line `[blueprint] companion pin for role '<role>' updated: '<old>' -> '<new>'`.",
33
+ "given": "a fixture project with an existing companions.json pin",
34
+ "when": "the operator re-runs the apply with the same or a different --companion selector",
35
+ "then": "the pin file schema stays valid, the shape matches the spec section 2.4 example (schemaVersion + roles + pinnedAt), and the pin overwrite prints the transition line",
36
+ "testable": true,
37
+ "scope": "library"
38
+ }
39
+ ],
40
+ "tacIds": [],
41
+ "createdAt": "2026-09-04T12:20:00Z",
42
+ "updatedAt": "2026-09-04T12:20:00Z"
43
+ }