rcf-lite 0.18.0 → 0.19.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 (108) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/blueprints/application-api-rest/blueprint.json +12 -4
  3. package/blueprints/application-api-rest/contributions/adrs/adr-304-application-api-rest-logging.json +3 -3
  4. package/blueprints/application-api-rest/docs/topics.md +4 -2
  5. package/blueprints/application-error-handling/README.md +42 -0
  6. package/blueprints/application-error-handling/assets/schemas/error-record.schema.json +17 -0
  7. package/blueprints/application-error-handling/blueprint.json +27 -0
  8. package/blueprints/application-error-handling/contributions/adrs/adr-1701-application-error-handling-record-shape.json +25 -0
  9. package/blueprints/application-error-handling/contributions/adrs/adr-1702-application-error-handling-classification-vocabulary.json +20 -0
  10. package/blueprints/application-error-handling/contributions/adrs/adr-1703-application-error-handling-transport-mapping.json +20 -0
  11. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-001.json +15 -0
  12. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-002.json +15 -0
  13. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-003.json +15 -0
  14. package/blueprints/application-error-handling/contributions/requirements/application-error-handling-req-004.json +15 -0
  15. package/blueprints/application-error-handling/contributions/tacs/tac-1701-application-error-handling-boundary.json +45 -0
  16. package/blueprints/application-error-handling/contributions/tacs/tac-1702-application-error-handling-record-factory.json +40 -0
  17. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16101.json +25 -0
  18. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16102.json +25 -0
  19. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16103.json +34 -0
  20. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16104.json +25 -0
  21. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16105.json +25 -0
  22. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16106.json +25 -0
  23. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16107.json +25 -0
  24. package/blueprints/application-error-handling/docs/topics.md +24 -0
  25. package/blueprints/application-error-handling/guide/application-error-handling.md +35 -0
  26. package/blueprints/application-spa/blueprint.json +12 -2
  27. package/blueprints/application-spa/docs/topics.md +2 -0
  28. package/blueprints/observability-logging/README.md +44 -0
  29. package/blueprints/observability-logging/assets/samples/log-line.json +13 -0
  30. package/blueprints/observability-logging/blueprint.json +27 -0
  31. package/blueprints/observability-logging/contributions/adrs/adr-1601-observability-logging-line-shape.json +25 -0
  32. package/blueprints/observability-logging/contributions/adrs/adr-1602-observability-logging-correlation-id-header.json +25 -0
  33. package/blueprints/observability-logging/contributions/adrs/adr-1603-observability-logging-redaction-categories.json +25 -0
  34. package/blueprints/observability-logging/contributions/adrs/adr-1604-observability-logging-level-vocabulary.json +20 -0
  35. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-001.json +15 -0
  36. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-002.json +15 -0
  37. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-003.json +15 -0
  38. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-004.json +15 -0
  39. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-005.json +15 -0
  40. package/blueprints/observability-logging/contributions/tacs/tac-1601-observability-logging-logger-factory.json +46 -0
  41. package/blueprints/observability-logging/contributions/tacs/tac-1602-observability-logging-redaction-boundary.json +27 -0
  42. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15101.json +34 -0
  43. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15102.json +43 -0
  44. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15103.json +34 -0
  45. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15104.json +25 -0
  46. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15105.json +34 -0
  47. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15106.json +25 -0
  48. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15107.json +25 -0
  49. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15108.json +25 -0
  50. package/blueprints/observability-logging/docs/topics.md +21 -0
  51. package/blueprints/observability-logging/guide/observability-logging.md +36 -0
  52. package/fixtures/canary-manifest.json +6 -6
  53. package/guidance/harness-template.md +8 -0
  54. package/guidance/managed/agent-instructions-block.hash +1 -1
  55. package/guidance/managed/agent-instructions-block.md +8 -0
  56. package/package.json +1 -1
  57. package/rcf/code-nodes/cn-077.json +14 -0
  58. package/rcf/code-nodes/cn-078.json +15 -0
  59. package/rcf/code-nodes/cn-079.json +14 -0
  60. package/rcf/code-nodes/cn-080.json +15 -0
  61. package/rcf/code-nodes/cn-081.json +15 -0
  62. package/rcf/code-nodes/cn-082.json +15 -0
  63. package/rcf/code-nodes/cn-083.json +14 -0
  64. package/rcf/code-nodes/cn-084.json +15 -0
  65. package/rcf/code-nodes/cn-085.json +14 -0
  66. package/rcf/code-nodes/cn-086.json +16 -0
  67. package/rcf/code-nodes/cn-087.json +14 -0
  68. package/rcf/code-nodes/cn-088.json +14 -0
  69. package/rcf/code-nodes/cn-089.json +14 -0
  70. package/rcf/code-nodes/cn-090.json +14 -0
  71. package/rcf/code-nodes/cn-091.json +14 -0
  72. package/rcf/code-nodes/cn-092.json +15 -0
  73. package/rcf/code-nodes/cn-093.json +15 -0
  74. package/rcf/code-nodes/cn-094.json +14 -0
  75. package/rcf/code-nodes/cn-095.json +14 -0
  76. package/rcf/code-nodes/cn-096.json +14 -0
  77. package/rcf/code-nodes/cn-097.json +14 -0
  78. package/rcf/fbs/fbs-028.json +27 -0
  79. package/rcf/fbs/fbs-029.json +27 -0
  80. package/rcf/fbs/fbs-030.json +27 -0
  81. package/rcf/fbs/fbs-031.json +27 -0
  82. package/rcf/fbs/fbs-032.json +27 -0
  83. package/rcf/fbs/fbs-033.json +27 -0
  84. package/rcf/fbs/fbs-034.json +27 -0
  85. package/rcf/requirements/req-013.json +22 -0
  86. package/rcf/requirements/req-014.json +22 -0
  87. package/rcf/requirements/req-015.json +21 -0
  88. package/rcf/test-suites/ts-038.json +41 -0
  89. package/rcf/test-suites/ts-039.json +41 -0
  90. package/rcf/test-suites/ts-040.json +57 -0
  91. package/rcf/test-suites/ts-041.json +57 -0
  92. package/rcf/test-suites/ts-042.json +57 -0
  93. package/rcf/test-suites/ts-043.json +49 -0
  94. package/rcf/test-suites/ts-044.json +41 -0
  95. package/rcf/user-stories/us-1301.json +43 -0
  96. package/rcf/user-stories/us-1302.json +43 -0
  97. package/rcf/user-stories/us-1401.json +43 -0
  98. package/rcf/user-stories/us-1402.json +43 -0
  99. package/rcf/user-stories/us-1403.json +43 -0
  100. package/rcf/user-stories/us-1404.json +43 -0
  101. package/rcf/user-stories/us-1501.json +43 -0
  102. package/releases/releases.yaml +11 -1
  103. package/src/blueprint/apply.js +8 -0
  104. package/src/blueprint/companions.js +485 -0
  105. package/src/blueprint/index.js +16 -0
  106. package/src/blueprint/loader.js +243 -1
  107. package/src/cli/blueprint.js +309 -0
  108. package/src/cli/validate.js +7 -0
@@ -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,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
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "usId": "US-1403",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-014",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "`rcf define blueprint companions` verb: three sub-verbs (print resolution, set pin, unset pin) with --json on all three",
8
+ "asA": "operator inspecting or pinning companion suggestions on an applied service blueprint outside the apply flow",
9
+ "iWant": "a `rcf define blueprint companions <slug>` sub-verb that prints the resolved companion set for one applied service blueprint, `rcf define blueprint companions set <role> <slug>` that writes a project-level pin to rcf/companions.json, and `rcf define blueprint companions unset <role>` that removes a pin",
10
+ "soThat": "I can read the current resolution without re-applying, pin a decision the operator makes outside the apply, and lift a pin cleanly",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1403-1",
14
+ "description": "`rcf define blueprint companions <slug>` (three positionals: `blueprint`, `companions`, `<slug>`) with `<slug>` naming an applied service blueprint that declares `suggestedCompanions[]` prints on stdout: header `<slug> suggests companions:` and one line per role in the shape ` <role> -> <resolved-provider> (<origin-note>)`, where the origin note reads `already applied` / `pinned via rcf/companions.json` / `registered library '<prefix>' (overrides shelf provider <shelf-slug>)` / `shelf fallback (no registered library provides this role)`. Exit 0. Refuses with exit 2 when `<slug>` names no applied blueprint or the applied blueprint declares no `suggestedCompanions[]`.",
15
+ "given": "a fixture project with application-api-rest v2.1.0 applied and observability-logging applied",
16
+ "when": "the operator runs `rcf define blueprint companions application-api-rest`",
17
+ "then": "stdout carries the header and one line per role with `already applied` on `logging` and `shelf fallback` (or similar) on `errorHandling`; a slug that is not applied refuses exit 2",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1403-2",
23
+ "description": "`rcf define blueprint companions set <role> <slug>` writes `rcf/companions.json` under `roles.<role>.provider` with `pinnedAt` ISO-8601 (or updates it if present); refuses exit 2 when `<slug>` names no blueprint or the named blueprint does not declare `providesRoles` containing `<role>`. `rcf define blueprint companions unset <role>` removes the `roles.<role>` entry (leaves the rest of the file intact); refuses exit 2 when no pin exists for `<role>`. Both sub-verbs honour `--json` (emit `{ok: true, role, provider, pinnedAt}` on success; `{ok: false, error: {...}}` on refusal).",
24
+ "given": "a fixture project with no existing pin",
25
+ "when": "the operator runs `rcf define blueprint companions set logging observability-logging`, then `rcf define blueprint companions unset logging`",
26
+ "then": "the first run writes companions.json with the pin (exit 0); the second run removes the pin and prints `[blueprint] companion pin for role 'logging' removed` on stdout (exit 0); an unset on a role without a pin refuses exit 2",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1403-3",
32
+ "description": "`--json` on `rcf define blueprint companions <slug>` emits a machine-readable object: `{slug, suggestions: [{role, provider, origin, notes}]}`, exit 0. The suggestions array preserves the order of the applied blueprint's `suggestedCompanions[]`.",
33
+ "given": "a fixture project with application-api-rest applied and both companions applied",
34
+ "when": "the operator runs `rcf define blueprint companions application-api-rest --json`",
35
+ "then": "stdout carries a JSON object of the shape above and jq queries against it return the resolved provider per role",
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-1404",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-014",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Resolution rule prefers applied > registered library > core shelf; two libraries on one role refuse exit 3; validate refuses an unresolvable pin exit 3",
8
+ "asA": "operator resolving a companion suggestion on a project with a registered library that provides the same role as the shelf",
9
+ "iWant": "the deterministic tier ladder (applied provider wins, single library candidate wins over shelf, two library candidates refuse with the explicit three-path resolution message, shelf provider is the terminal fallback) and validate to refuse a pin that names no known provider",
10
+ "soThat": "the operator's opt-in to a library is honoured over the shelf, ambiguity refuses with the explicit remedy paths rather than picking silently, and a stale pin cannot silently drift after a library is removed",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1404-1",
14
+ "description": "For each role suggested by an applied service blueprint, the resolver walks the tier ladder in order: (1) any applied blueprint whose `providesRoles[]` contains the role wins immediately with origin `already applied`; (2) otherwise, any registered library blueprint (from `rcf/blueprint-libraries.json` + each library's `library.json:blueprints[]`) whose source `providesRoles[]` contains the role wins with origin `registered library '<prefix>'`; (3) otherwise, the single core-shelf blueprint whose `providesRoles[]` contains the role wins with origin `shelf fallback`; (4) otherwise the role is unresolved (origin `unresolved`, provider null). A pin in `rcf/companions.json` overrides steps (2) and (3) with origin `pinned via rcf/companions.json` when the pin names a known provider.",
15
+ "given": "three fixture projects: (a) core-only; (b) one registered library providing logging + the core provider; (c) an already-applied library-side logging provider",
16
+ "when": "the resolver runs on the same suggestedCompanions[] from application-api-rest",
17
+ "then": "(a) resolves logging to observability-logging with `shelf fallback`; (b) resolves logging to the library provider with `registered library '<prefix>'`; (c) resolves logging to the applied library provider with `already applied`",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1404-2",
23
+ "description": "When two or more registered libraries each carry a `providesRoles[]` containing the same role and no explicit selector or pin is set, the resolver refuses with exit 3 and prints (on `rcf define blueprint add` and on `rcf define blueprint companions <slug>`, both) a message naming the ambiguous role, both library-qualified slugs, and three resolution paths verbatim per spec section 2.4: (1) `rcf define blueprint add <service-slug> --companion <role>=<lib>:<slug>` at apply; (2) `rcf define blueprint companions set <role> <lib>:<slug>` to pin at project level; (3) `rcf define blueprint library remove <prefix>` to remove one library.",
24
+ "given": "a fixture project with two registered libraries both providing role `logging`, no pin",
25
+ "when": "the operator runs `rcf define blueprint add <path>/application-api-rest`",
26
+ "then": "the exit code is 3 and stderr carries the refusal message with both library slugs and the three resolution paths verbatim",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1404-3",
32
+ "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 `rcf/companions.json pins role '<role>' to '<slug>' but no such provider is applied, registered or on the shelf.`. The check runs on every validate pass alongside the existing schema and referential-integrity checks; a missing `rcf/companions.json` file is not itself a validation error.",
33
+ "given": "a fixture project whose companions.json pins `logging` to `nope:nope`",
34
+ "when": "the operator runs `rcf define validate`",
35
+ "then": "the exit code is 3 and stderr carries the unresolvable-pin refusal message with the exact quoted role and slug",
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-1501",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-015",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Loader accepts standardsTrace[], recommendedDefault, elicited and standardsTraceClause; refuses a declared standardsTrace missing a clause reference on any ADR contribution",
8
+ "asA": "library author writing a standards-derived blueprint (e.g. wsd-logging composing on WSD-001)",
9
+ "iWant": "the loader to accept a blueprint-level standardsTrace[] and per-ADR-contribution recommendedDefault, elicited and standardsTraceClause fields, and refuse the load when standardsTrace[] is declared but any ADR contribution has no standardsTraceClause",
10
+ "soThat": "the standards-derived discipline is machine-checkable at load time and a mis-authored library blueprint fails fast, before an apply lands into the tree",
11
+ "acceptanceCriteria": [
12
+ {
13
+ "id": "AC-1501-1",
14
+ "description": "The loader accepts optional top-level `standardsTrace[]` (array of `{id: string, version: string}` objects; `id` is a non-empty string; `version` is a non-empty string), optional ADR-contribution fields `recommendedDefault: true|false`, `elicited: true|false` and `standardsTraceClause: string`. `recommendedDefault` and `elicited` are mutually independent (a SHOULD may be elicited; a MAY need not have a recommended default). The loader does NOT cross-check clause severity against kind (no refusal for a MUST clause mapped to an ADR; the discipline is prose in section 8a, not code, per amendment A2 Baz 2026-09-04T12:20:31Z).",
15
+ "given": "a blueprint fixture declaring standardsTrace with WSD-001 v2026-05, and one ADR contribution with recommendedDefault: true, elicited: false and standardsTraceClause: 'WSD-001 clause 3.1'",
16
+ "when": "the loader parses the file",
17
+ "then": "the LoadedBlueprint object carries the fields verbatim and returns no rcfError",
18
+ "testable": true,
19
+ "scope": "library"
20
+ },
21
+ {
22
+ "id": "AC-1501-2",
23
+ "description": "The loader refuses (rcfError kind `validation`) when `standardsTrace[]` is set but any ADR contribution has no `standardsTraceClause` (or has it set to an empty or whitespace-only string). Refusal message shape: `blueprint '<slug>' declares standardsTrace but ADR contribution '<id>' has no standardsTraceClause; every ADR must reference a standard clause or the sentinel 'generic enterprise practice'.`. At the CLI edge the exit code is 2.",
24
+ "given": "a fixture blueprint with standardsTrace declared and one ADR contribution missing standardsTraceClause",
25
+ "when": "the loader parses the file",
26
+ "then": "the loader returns an rcfError of kind `validation` with the exact refusal message shape",
27
+ "testable": true,
28
+ "scope": "library"
29
+ },
30
+ {
31
+ "id": "AC-1501-3",
32
+ "description": "A blueprint that DOES NOT declare `standardsTrace[]` (every core shelf blueprint today, including the two new core-companion blueprints in REQ-013) loads clean regardless of whether ADR contributions carry `standardsTraceClause` (the discipline lands only when standardsTrace[] is present). The sentinel string `\"generic enterprise practice\"` is accepted as a standardsTraceClause value; the discipline documented in section 8a of blueprint-authoring.md names it explicitly.",
33
+ "given": "the two new core companion blueprints (observability-logging, application-error-handling) with no standardsTrace declared, and a fixture that declares standardsTrace and uses 'generic enterprise practice' on every ADR",
34
+ "when": "the loader parses each",
35
+ "then": "the core blueprints load clean; the fixture with the sentinel on every ADR loads clean",
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
+ }
@@ -40,8 +40,18 @@
40
40
  # `npm install rcf-lite`.
41
41
 
42
42
  feedVersion: 1
43
- latest: "0.18.0"
43
+ latest: "0.19.0"
44
44
  releases:
45
+ - version: "0.19.0"
46
+ date: "2026-09-04"
47
+ breaking: false
48
+ headlines:
49
+ - "The rcf-lite core shelf gains two new blueprints, observability-logging and application-error-handling, that carry the widely followed rules for structured logging and internal error handling so a service can compose them alongside its own blueprint."
50
+ - "Service blueprints can now name the roles they want alongside them and rcf define blueprint suggests the most specific provider for each at apply time, preferring an applied provider first, then a project-level pin, then a registered library, then the shipped shelf; the operator still applies each companion by hand."
51
+ - "The authoring standard grows a written discipline for blueprints that derive from an outside standard, so a must-clause that binds a testable behaviour becomes a test and a choice-shaped clause becomes a recommended default. Rerun rcf init to refresh the agent-instructions block."
52
+ minAgentAction: "rerun-init"
53
+ notesUrl: "https://stravica.ai/docs/rcf/changelog/"
54
+
45
55
  - version: "0.18.0"
46
56
  date: "2026-09-04"
47
57
  breaking: true
@@ -307,6 +307,14 @@ export async function applyBlueprint({ projectRoot, tree, source, displaySource,
307
307
  slug: appliedSlug,
308
308
  version: blueprint.version,
309
309
  contributions: writtenContributions,
310
+ // Companion-suggestion mechanism (spec 2.6). Bubble the source
311
+ // blueprint's `suggestedCompanions[]` up on the result so the CLI
312
+ // can render the resolved-suggestion block after a successful
313
+ // apply. Unresolved here (the CLI holds the tree + libraries to
314
+ // run the resolver); apply owns only the raw copy.
315
+ ...(Array.isArray(blueprint.suggestedCompanions) && blueprint.suggestedCompanions.length > 0
316
+ ? { suggestedCompanions: blueprint.suggestedCompanions }
317
+ : {}),
310
318
  ...(duplicateResolveTopics.length > 0 ? { warnings: [{ kind: 'duplicateResolveTopic', topics: duplicateResolveTopics }] } : {}),
311
319
  };
312
320
  }