@n8r/surface 0.0.0-stage → 0.1.0-experimental.5

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 (181) hide show
  1. package/LICENSE +202 -0
  2. package/LICENSE-DOCS +395 -0
  3. package/LICENSING.md +36 -0
  4. package/README.md +207 -2
  5. package/dist/activity.d.ts +16 -0
  6. package/dist/activity.js +44 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +412 -0
  9. package/dist/codec.d.ts +6 -0
  10. package/dist/codec.js +56 -0
  11. package/dist/codex.d.ts +72 -0
  12. package/dist/codex.js +526 -0
  13. package/dist/contracts.d.ts +235 -0
  14. package/dist/contracts.js +1 -0
  15. package/dist/cyclonedx-schemas/bom-1.7.schema.json +6700 -0
  16. package/dist/cyclonedx-schemas/cryptography-defs.schema.json +576 -0
  17. package/dist/cyclonedx-schemas/jsf-0.82.schema.json +240 -0
  18. package/dist/cyclonedx-schemas/spdx.schema.json +786 -0
  19. package/dist/cyclonedx-validation.d.ts +1 -0
  20. package/dist/cyclonedx-validation.js +45 -0
  21. package/dist/html.d.ts +5 -0
  22. package/dist/html.js +74 -0
  23. package/dist/index.d.ts +7 -0
  24. package/dist/index.js +5 -0
  25. package/dist/notes.d.ts +52 -0
  26. package/dist/notes.js +184 -0
  27. package/dist/portable.d.ts +10 -0
  28. package/dist/portable.js +71 -0
  29. package/dist/recent.d.ts +9 -0
  30. package/dist/recent.js +71 -0
  31. package/dist/revisions.d.ts +2 -0
  32. package/dist/revisions.js +60 -0
  33. package/dist/settings.d.ts +23 -0
  34. package/dist/settings.js +100 -0
  35. package/dist/setup.d.ts +9 -0
  36. package/dist/setup.js +161 -0
  37. package/dist/skill-artifacts-cli.d.ts +1 -0
  38. package/dist/skill-artifacts-cli.js +13 -0
  39. package/dist/skill-artifacts.d.ts +15 -0
  40. package/dist/skill-artifacts.js +184 -0
  41. package/dist/skill-cyclonedx.d.ts +26 -0
  42. package/dist/skill-cyclonedx.js +214 -0
  43. package/dist/skill-presentation.d.ts +10 -0
  44. package/dist/skill-presentation.js +108 -0
  45. package/dist/skill-surface-cli.d.ts +1 -0
  46. package/dist/skill-surface-cli.js +37 -0
  47. package/dist/skill-surface-store.d.ts +7 -0
  48. package/dist/skill-surface-store.js +126 -0
  49. package/dist/source-tools.d.ts +102 -0
  50. package/dist/source-tools.js +201 -0
  51. package/dist/startup.d.ts +7 -0
  52. package/dist/startup.js +74 -0
  53. package/dist/surface-bom.d.ts +73 -0
  54. package/dist/surface-bom.js +139 -0
  55. package/dist/surface-draft.d.ts +22 -0
  56. package/dist/surface-draft.js +112 -0
  57. package/dist/surface-instructions.d.ts +3 -0
  58. package/dist/surface-instructions.js +32 -0
  59. package/dist/surface-overview.d.ts +15 -0
  60. package/dist/surface-overview.js +86 -0
  61. package/dist/surface-store.d.ts +34 -0
  62. package/dist/surface-store.js +213 -0
  63. package/dist/surface-view.d.ts +3 -0
  64. package/dist/surface-view.js +50 -0
  65. package/dist/validate.d.ts +4 -0
  66. package/dist/validate.js +482 -0
  67. package/docs/n8r-surface/README.md +133 -0
  68. package/docs/n8r-surface/cli-bundles.md +72 -0
  69. package/docs/n8r-surface/codex-research-transcript.md +51 -0
  70. package/docs/n8r-surface/codex-research-verification.md +176 -0
  71. package/docs/n8r-surface/command-outcomes.md +711 -0
  72. package/docs/n8r-surface/contracts.md +220 -0
  73. package/docs/n8r-surface/critical-path.md +184 -0
  74. package/docs/n8r-surface/design.md +289 -0
  75. package/docs/n8r-surface/first-use-access.md +143 -0
  76. package/docs/n8r-surface/first-use-overview.md +262 -0
  77. package/docs/n8r-surface/getting-started.md +74 -0
  78. package/docs/n8r-surface/guided-journey-verification.md +137 -0
  79. package/docs/n8r-surface/host-contract.md +176 -0
  80. package/docs/n8r-surface/implementation-decisions.md +96 -0
  81. package/docs/n8r-surface/instance-first-research.md +209 -0
  82. package/docs/n8r-surface/npm-distribution.md +107 -0
  83. package/docs/n8r-surface/npm-release.md +315 -0
  84. package/docs/n8r-surface/product-direction.md +327 -0
  85. package/docs/n8r-surface/recreation-handoff.md +117 -0
  86. package/docs/n8r-surface/researcher-discovery.md +157 -0
  87. package/docs/n8r-surface/researcher-prepared-check.md +117 -0
  88. package/docs/n8r-surface/researcher-reconciliation-trial.md +149 -0
  89. package/docs/n8r-surface/researcher-repository-check.md +95 -0
  90. package/docs/n8r-surface/researcher-skeleton-check.md +84 -0
  91. package/docs/n8r-surface/researcher-skill-verification.md +725 -0
  92. package/docs/n8r-surface/researcher-skill.md +309 -0
  93. package/docs/n8r-surface/researcher-vault.md +134 -0
  94. package/docs/n8r-surface/save-reopen-transcript.md +211 -0
  95. package/docs/n8r-surface/save-reopen-verification.md +152 -0
  96. package/docs/n8r-surface/security-assurance-strategy.md +267 -0
  97. package/docs/n8r-surface/skill-bom-verification.md +142 -0
  98. package/docs/n8r-surface/skill-cyclonedx-verification.md +144 -0
  99. package/docs/n8r-surface/skill-cyclonedx.md +85 -0
  100. package/docs/n8r-surface/skill-manual.md +129 -0
  101. package/docs/n8r-surface/skill-surface-artifacts.md +234 -0
  102. package/docs/n8r-surface/skill-usefulness-verification.md +135 -0
  103. package/docs/n8r-surface/skill-workspace-automation.md +359 -0
  104. package/docs/n8r-surface/startup-human-check.md +172 -0
  105. package/docs/n8r-surface/startup-verification.md +161 -0
  106. package/docs/n8r-surface/startup.md +151 -0
  107. package/docs/n8r-surface/surface-description-contract.md +224 -0
  108. package/docs/n8r-surface/surface-descriptions.md +173 -0
  109. package/docs/n8r-surface/surface-relationships.md +231 -0
  110. package/docs/n8r-surface/surface-revisions-transcript.md +552 -0
  111. package/docs/n8r-surface/surface-revisions-verification.md +161 -0
  112. package/docs/n8r-surface/tester-candidate.md +158 -0
  113. package/docs/n8r-surface/vault-setup-verification.md +210 -0
  114. package/docs/n8r-surface/verification.md +117 -0
  115. package/docs/n8r-surface/versioning.md +172 -0
  116. package/docs/n8r-surface/workspace-human-check.md +101 -0
  117. package/docs/n8r-surface/workspace-installation.md +68 -0
  118. package/docs/n8r-surface/workspace-verification.md +350 -0
  119. package/docs/n8r-surface/workspace.md +83 -0
  120. package/examples/researcher/README.md +100 -0
  121. package/examples/researcher/composed.surface.json +430 -0
  122. package/examples/researcher/composed.surface.yaml +283 -0
  123. package/examples/researcher/cyclonedx/configured/README.md +7 -0
  124. package/examples/researcher/cyclonedx/configured/manifest.json +10 -0
  125. package/examples/researcher/cyclonedx/configured/mapping.json +323 -0
  126. package/examples/researcher/cyclonedx/configured/surface-records.json +1275 -0
  127. package/examples/researcher/cyclonedx/configured/surface.cdx.json +79 -0
  128. package/examples/researcher/descriptions/README.md +29 -0
  129. package/examples/researcher/descriptions/bound-r1.json +141 -0
  130. package/examples/researcher/descriptions/bound-r2.json +153 -0
  131. package/examples/researcher/descriptions/capability.json +167 -0
  132. package/examples/researcher/descriptions/research-r1.json +153 -0
  133. package/examples/researcher/descriptions/research-r2.json +157 -0
  134. package/examples/researcher/descriptions/sources.md +24 -0
  135. package/examples/researcher/harbor-r1.research.html +193 -0
  136. package/examples/researcher/harbor-r2.research.html +226 -0
  137. package/examples/researcher/lumen-manual-edit.pending.html +271 -0
  138. package/examples/researcher/lumen-r1.research.html +271 -0
  139. package/examples/researcher/lumen-r2.research.html +280 -0
  140. package/examples/researcher/relationships/README.md +34 -0
  141. package/examples/researcher/relationships/bound-r1.json +346 -0
  142. package/examples/researcher/relationships/bound-r2.json +358 -0
  143. package/examples/researcher/relationships/capability.json +325 -0
  144. package/examples/researcher/relationships/config/assistant.env.example +4 -0
  145. package/examples/researcher/relationships/research-r1.json +300 -0
  146. package/examples/researcher/relationships/research-r2.json +304 -0
  147. package/examples/researcher/relationships/sources.md +38 -0
  148. package/examples/researcher/sources/harbor-api.md +16 -0
  149. package/examples/researcher/sources/harbor-auth.md +8 -0
  150. package/examples/researcher/sources/lumen-guide.md +28 -0
  151. package/examples/researcher/sources/lumen-settings.md +9 -0
  152. package/examples/researcher/surface-bom/README.md +17 -0
  153. package/examples/researcher/surface-bom/initial.cdx.json +188 -0
  154. package/package.json +45 -4
  155. package/plugins/n8r-surface/.codex-plugin/plugin.json +31 -0
  156. package/plugins/n8r-surface/LICENSE +202 -0
  157. package/plugins/n8r-surface/LICENSE-DOCS +395 -0
  158. package/plugins/n8r-surface/LICENSING.md +39 -0
  159. package/plugins/n8r-surface/assets/icon.svg +5 -0
  160. package/plugins/n8r-surface/plugin.json +27 -0
  161. package/plugins/n8r-surface/skills/research/SKILL.md +163 -0
  162. package/plugins/n8r-surface/skills/research/agents/openai.yaml +4 -0
  163. package/plugins/n8r-surface/skills/research/references/artifacts.md +152 -0
  164. package/plugins/n8r-surface/skills/research/references/cyclonedx.md +207 -0
  165. package/plugins/n8r-surface/skills/research/references/discovery-map.md +178 -0
  166. package/plugins/n8r-surface/skills/research/references/examples/bound-r1.json +346 -0
  167. package/plugins/n8r-surface/skills/research/references/examples/capability.json +325 -0
  168. package/plugins/n8r-surface/skills/research/references/examples/research-r1.json +300 -0
  169. package/plugins/n8r-surface/skills/research/references/examples/surface.cdx.json +188 -0
  170. package/plugins/n8r-surface/skills/research/references/first-use-access.md +97 -0
  171. package/plugins/n8r-surface/skills/research/references/first-use-overview.md +101 -0
  172. package/plugins/n8r-surface/skills/research/references/instance-first.md +125 -0
  173. package/plugins/n8r-surface/skills/research/references/model-meanings.md +55 -0
  174. package/plugins/n8r-surface/skills/research/references/skeleton-surface.md +105 -0
  175. package/plugins/n8r-surface/skills/research/references/working-notes.md +121 -0
  176. package/plugins/n8r-surface/skills/research/references/workspace.md +89 -0
  177. package/plugins/n8r-surface/skills/research/scripts/THIRD-PARTY-NOTICES.txt +273 -0
  178. package/plugins/n8r-surface/skills/research/scripts/artifacts.mjs +8348 -0
  179. package/plugins/n8r-surface/skills/research/scripts/cyclonedx.mjs +28113 -0
  180. package/plugins/n8r-surface/skills/research/scripts/surface.mjs +27800 -0
  181. package/plugins/n8r-surface/skills/research/scripts/workspace.mjs +120 -0
@@ -0,0 +1,161 @@
1
+ # STARTUP-01 verification record
2
+
3
+ **Result:** specified, implemented and verified for the read-only bare-startup
4
+ increment. This does not complete #16 or verify setup, status, discovery or an AI
5
+ conversation. [Settings, parser decisions and limits](startup.md) define the
6
+ implemented boundary. [PR #25](https://github.com/injectionator/n8r-surface/pull/25)
7
+ carries the increment originally developed on #15. This record preserves the
8
+ pre-integration verification revision and does not claim a release.
9
+
10
+ ## Human verification
11
+
12
+ Follow the [copy-and-paste human check](startup-human-check.md) for prerequisites,
13
+ PR checkout, a disposable installation and synthetic home, exact expected output,
14
+ interactive `y`/EOF steps, private-value checks and cleanup. Its expected exit 1
15
+ is explained explicitly. The automated commands later in this record support
16
+ that hands-on check.
17
+
18
+ On 4 November 2026, Codex rehearsed the guide's disposable installation, closed
19
+ input, terminal `y` and Ctrl-D, private-value/stderr checks and unchanged-file
20
+ comparison on Node 22.23.2, npm 11.5.2 and macOS ARM64. The expected output and
21
+ exit codes matched; all 43 tests and 20 installed startup checks also passed.
22
+ This is an agent rehearsal, not recorded human acceptance.
23
+
24
+ ## Revision and environment
25
+
26
+ - Date: 4 November 2026. Implementer/verifier: Codex; separate read-only agent
27
+ review found no important issues in the startup implementation.
28
+ - Baseline: `5f67dbea2be93a6ee6bedb9a029bc79be4b3997d`.
29
+ - Implementation and retained test revision:
30
+ `b90358aaf22fead155081bb00f6d837a0f8f59e7`. The matrix below was repeated from
31
+ this committed revision with a clean working tree before writing this record.
32
+ - macOS ARM64; Node.js **22.23.2, 24.22.2 and 26.13.0**; npm **11.5.2**;
33
+ Python **3.13.1** for the terminal rehearsal.
34
+ - Private package `n8r-surface@0.0.0-experimental.1`, built and packed locally,
35
+ then installed outside the checkout using `--offline --ignore-scripts`.
36
+ `npm ci` populated the dependency cache; no registry publication occurred.
37
+ Each matrix executable was the `node` binary in its own runtime directory.
38
+
39
+ ## Baseline and prepared state
40
+
41
+ At the baseline, `command -v n8r-surface` returned no path (exit 1) and the package
42
+ manifest contained no `bin` entry. The installed product interaction was therefore
43
+ **blocked by an absent executable**, not an observed failed startup. No research
44
+ or setup result was invented. After adding the process tests, 16 startup checks
45
+ failed on the missing built entry point while the existing 23 library tests passed.
46
+
47
+ The repeatable check creates a temporary home containing:
48
+
49
+ - `~/.n8r/n8r-surface.json`: version 1, `artefactRoot: "~/n8r/artifacts"`,
50
+ `surfaceFormat: "json"`, and synthetic private markers in ignored settings.
51
+ - `~/n8r/artifacts/librechat-uniqueid.json`: a valid synthetic `n8r.surface/0.1`
52
+ definition titled **LibreChat**. It is a prepared input, not Researcher output.
53
+ - No runner or Lab configuration. A synthetic credential marker in the process
54
+ environment must also be absent from output. A saved PID in ignored settings
55
+ must not imply runner liveness.
56
+
57
+ **Interaction:** invoke installed `n8r-surface` with no arguments from the
58
+ isolated home. First close stdin and capture output/exit. Then run the same
59
+ installed bin in a real POSIX terminal, wait for the guidance question, check the
60
+ already-received overview, and answer `y`. Repeat with terminal EOF (Ctrl-D).
61
+ No credentials or running Lab are required.
62
+
63
+ ## Observed terminal output
64
+
65
+ This is the installed PTY readback, with only the temporary home replaced by `~`,
66
+ PID/time represented by labelled placeholders, and readline cursor escapes removed.
67
+ The assertions use the real paths, compare the child PID with its process result,
68
+ and check the timestamp is present. File contents are independently reread.
69
+
70
+ ```text
71
+ Configuration
72
+ File: ~/.n8r/n8r-surface.json
73
+ Settings version: 1
74
+ Artefact folder: ~/n8r/artifacts
75
+ Surface output: JSON
76
+ AI runner: Not configured
77
+ Lab connection: Not configured
78
+
79
+ Processes
80
+ n8r-surface overview: running (PID <observed PID>); observed <UTC timestamp>
81
+ Runner/Lab processes: Status unknown (no live status source)
82
+
83
+ Local artefacts (1)
84
+ LibreChat | Surface definition | ~/n8r/artifacts/librechat-uniqueid.json
85
+
86
+ Setup and AI conversation are not implemented in this build. Research needs a supported AI runner.
87
+ Show setup requirements? [y/N] y
88
+ Research will require an explicitly selected runner, model and external credential reference. A Lab connection is optional. No settings have been changed.
89
+ ```
90
+
91
+ With closed input, the same overview appears, followed by the unavailable-capability
92
+ message and `Run in an interactive terminal for read-only setup guidance.` No
93
+ question appears and the process exits within the five-second test deadline.
94
+ Valid startup exits **1**, explicitly indicating unavailable setup/conversation;
95
+ inspection errors and arguments exit **2**. This is not research success.
96
+
97
+ ## Independent readback and repeatable evidence
98
+
99
+ | Expected outcome | Observed check |
100
+ | --- | --- |
101
+ | Readable settings and actual configured location | Output matches the prepared configuration path, `artifacts` override, JSON format and unconfigured runner/Lab. Defaults separately resolve to `artefacts`; relative paths resolve against the settings directory. |
102
+ | One logical row per entry | The supplied LibreChat definition appears exactly once with its title, type and filename. Two-entry cases also list HTML research metadata; YAML definitions are read. Controls in titles are escaped. |
103
+ | Private values stay private | Markers in nested/unknown settings, URL credentials, malformed input, artefact bodies and the credential environment are absent. Parser errors never echo source content. |
104
+ | Reliable status only | The displayed live overview PID equals the spawned child PID. Runner/Lab status remains unknown, including with a saved PID or declared runner/Lab configuration. |
105
+ | Read-only startup | Before/after bytes, modes and modification times match; the snapshot also checks the directory inventory. PTY `y` and EOF preserve the files and directories. |
106
+ | Empty differs from unavailable | Empty folders say empty; missing/unreadable folders report the path/problem. Invalid or unreadable configuration prevents corpus inspection and remains intact. |
107
+ | Unsupported entries do not disappear or hang | Unsupported, invalid, oversized, unreadable, symlink and directory entries retain a row with a limitation. FIFO configuration and entries finish without blocking. |
108
+ | Overview precedes interaction | PTY checks see configuration, processes and the artefact row before the live guidance question, then supply `y` or EOF. |
109
+ | Installed consumer needs no checkout | The tarball supplies the executable, library and assets. The same startup assertions invoke `n8r-surface` from its installed bin directory under a temporary home. |
110
+
111
+ All **43 tests** (23 existing library checks plus 20 startup checks) passed with
112
+ `npm test` on each supported Node major above, with no skips. The installed-package
113
+ matrix passed the library consumer check, all **20 startup checks**, and both PTY
114
+ interactions on each runtime. A separate reviewer also exercised terminal `n`,
115
+ Ctrl-D and Ctrl-C on Node 22 without raw diagnostics or a hang.
116
+
117
+ A validation regression found during implementation treated explicit null settings
118
+ as defaults. Two new checks failed before the fix; null folder/format values now
119
+ report invalid configuration without inspecting a fallback folder.
120
+
121
+ Reproduce from the repository:
122
+
123
+ ```sh
124
+ npm ci
125
+ npm test
126
+ npm run check:package
127
+ ```
128
+
129
+ For the supported runtime matrix, run `npm test` with each runtime on PATH, then:
130
+
131
+ ```sh
132
+ node scripts/check-package.mjs /path/to/node22/bin/node /path/to/node24/bin/node /path/to/node26/bin/node
133
+ ```
134
+
135
+ The paths above are placeholders. Use binaries named `node` in separate runtime
136
+ directories: the installed shebang resolves `node` from that directory on PATH.
137
+ A custom-named executable beside a different `node` would not establish the same
138
+ matrix. Retained evidence is ordinary code in
139
+ [startup.test.mjs](../../tests/startup.test.mjs),
140
+ [startup-pty.py](../../tests/startup-pty.py) and
141
+ [check-package.mjs](../../scripts/check-package.mjs), plus the observed readback
142
+ above. The checks remove their temporary installations/homes. No raw machine
143
+ paths or private logs are retained in the repository.
144
+
145
+ ## Remaining limits
146
+
147
+ Only the command's own process is directly known; there is no process registry or
148
+ proof of a live AI runner or Lab. Configured runner/Lab objects are declarations
149
+ whose contents are withheld. Missing setup is explained, not repaired.
150
+
151
+ The listing recognizes the experimental #15 profile. Older illustrative LibreChat
152
+ JSON, manually edited HTML, unknown formats and unsupported versions get a
153
+ limitation row; there is no universal Surface conformance claim. Files are bounded
154
+ per entry, but this increment does not provide a large-corpus index or total scan
155
+ time limit. Network-mounted folders were not exercised. Linux and Windows were
156
+ not exercised; PTY verification requires POSIX and Python. No inference, source
157
+ research, Lab compatibility, registry/npx download or release claim is made.
158
+
159
+ Next in #16: separately specify and verify `status`, then real setup, help/version,
160
+ source selection, guarded storage and unavailable-discovery handling. Actual
161
+ Researcher instructions and AI-driven repository research remain #17.
@@ -0,0 +1,151 @@
1
+ # Bare startup and local vault setup (#16)
2
+
3
+ Bare `n8r-surface` displays readable non-private configuration, legacy saved
4
+ artefacts and known own-process status. It then offers first-use vault setup or
5
+ reuses the configured vault. Setup does not start research, scan source contents,
6
+ use a network, launch a runner or require an account. Bare startup is unchanged by the separate [Codex discovery increment](codex-research-verification.md).
7
+ SOURCE-01 remains paused; the new discovery path does not incorporate that checkpoint. This increment does not complete #16 or #30.
8
+
9
+ The earlier read-only overview and guidance question were delivered by
10
+ [PR #25](https://github.com/injectionator/n8r-surface/pull/25).
11
+ [Historical STARTUP-01 evidence](startup-verification.md) applies to that revision.
12
+ The setup increment replaces its guidance question and exit behavior; see the
13
+ [current setup rehearsal and human tasks](vault-setup-verification.md).
14
+
15
+ ## Settings and parser decisions
16
+
17
+ One settings file: `~/.n8r/n8r-surface.json`, version 1, limited to 64 KiB.
18
+ The process home directory selects `~`, allowing an isolated verification home.
19
+ There are no project settings, command-line overrides or credential environment
20
+ reads. The repository's `.local/vault-path` remains an agent convention and is
21
+ not read by this command.
22
+
23
+ ```json
24
+ {
25
+ "version": 1,
26
+ "vaultRoot": "~/n8r/",
27
+ "artefactRoot": "~/n8r/artefacts",
28
+ "surfaceFormat": "json"
29
+ }
30
+ ```
31
+
32
+ `vaultRoot` is optional; absence means setup is pending. It stores the vault for
33
+ future research, containing `research/`, `artifacts/` and `surfaces/`.
34
+ `artefactRoot` remains the separate legacy structured-artefact location and defaults
35
+ to `~/n8r/artefacts`. No migration, renaming or inference from its parent occurs.
36
+ Both locations are displayed. Existing legacy content and every unknown settings
37
+ value are preserved. `surfaceFormat` defaults to `json` and also accepts `yaml`.
38
+ Optional `runner` and `lab` objects (or null) remain independent declarations;
39
+ only configuration presence is shown, never their private contents.
40
+
41
+ Expand `~/` against home. Stored relative paths resolve against the settings
42
+ folder. Newly entered relative vault paths resolve against invocation cwd;
43
+ first setup saves an absolute path. Validate the fully expanded/resolved path as
44
+ well as the input so that neither can introduce forbidden control characters.
45
+ Resolve pre-existing ancestors and an
46
+ explicitly selected vault-root symlink before showing the destination. Reject
47
+ empty custom paths, control characters, URL forms, non-directory collisions,
48
+ settings symlinks/special files and symlinked required vault children. Invalid
49
+ settings are retained for repair, never replaced with defaults.
50
+
51
+ Only zero arguments launches startup. Discovery, reopening and local help/version
52
+ have separate paths described in [the command inventory](command-outcomes.md#initial-public-command-inventory).
53
+ Unknown arguments exit 2 without echoing them or inspecting settings. No `setup`,
54
+ `--vault`, `--path` or `status` command is added.
55
+
56
+ ## First use, reuse and repair
57
+
58
+ The read-only overview precedes all questions. With both input and output attached
59
+ to terminals, first use asks:
60
+
61
+ ```text
62
+ Vault directory [~/n8r/]:
63
+ Vault directory: <resolved absolute path>
64
+ Create vault folders and save this location? [y/N]
65
+ ```
66
+
67
+ Enter at the location question chooses `~/n8r/`. Only `y` or `yes` (case insensitive)
68
+ at confirmation permits writes. Refusal, EOF and interruption before acceptance
69
+ exit 1 without writes. Acceptance creates only missing directories, then adds
70
+ `vaultRoot` to settings and prints `Vault ready: <resolved absolute path>`.
71
+ Existing JSON member bytes are retained when inserting the new field, including
72
+ unknown numeric literals outside JavaScript precision/range.
73
+ No source files are read or written. Reject writes to settings/vault paths inside
74
+ the invocation directory, including symlink aliases and missing descendants.
75
+ Also reject vault folders inside the legacy corpus: adding directories there
76
+ would break its next inspection. Running setup from home can therefore be refused; run from a separate source
77
+ folder. Complete configured reuse is read-only even from such a directory.
78
+
79
+ A complete configured vault exits 0 without questions, locks or settings rewrites.
80
+ Missing required folders need repair confirmation; repair creates folders without
81
+ rewriting settings. An occupied child path or inaccessible vault exits 2. Existing
82
+ vault files are never removed. A failed confirmed setup may leave empty folders;
83
+ retry reuses them. Setup does not create the legacy corpus when it is absent.
84
+
85
+ | Outcome | Exit | Writes |
86
+ | --- | --- | --- |
87
+ | Successful accepted setup/repair | 0 | Missing folders; settings only on first setup |
88
+ | Complete configured reuse | 0 | None |
89
+ | Decline, EOF or interrupt before confirmation | 1 | None |
90
+ | Setup/repair needed with nonterminal input or output | 1 | None |
91
+ | Invalid settings/arguments, filesystem or conflict error | 2 | No successful setup claim; partial confirmed folders may remain |
92
+ | Legacy inspection error except absent corpus | 2 | None; takes precedence before any setup question |
93
+
94
+ Closed-input setup/repair prints exactly:
95
+
96
+ ```text
97
+ Vault setup required; run n8r-surface in an interactive terminal.
98
+ ```
99
+
100
+ It finishes promptly without waiting. Missing legacy corpus is reported as
101
+ unavailable/absent (`ENOENT`) and permits setup/reuse; it is not reported empty.
102
+ Other legacy errors remain visible even when a complete vault exists.
103
+
104
+ ## Concurrency and recovery boundary
105
+
106
+ The user approved this cooperating-writer boundary on 5 November 2026. Other
107
+ editors must not write settings during confirmed setup. Directory/symlink topology
108
+ must stay stable while setup runs. This is not an adversarial filesystem or
109
+ power-loss durability guarantee, nor protection against arbitrary external writers.
110
+
111
+ After confirmation, exclusively create `~/.n8r/n8r-surface.json.lock`. Other setup
112
+ processes fail with exit 2 rather than wait or steal the lock. Compare the original
113
+ settings bytes under the lock before folder creation and again before publication.
114
+ Detected edits fail and retain the competing values. Write an exclusive temporary
115
+ sibling and close it only after all required folders are available. For absent
116
+ settings, publish with an exclusive hard link: a competing creator is preserved
117
+ even after the final byte check. For existing settings, atomically rename under
118
+ the lock. A writer ignoring that lock can still race the final check/rename;
119
+ no stronger guarantee is claimed.
120
+
121
+ Normal completion/failure removes only this invocation's temporary sibling and
122
+ lock. A killed process may leave these and empty folders. If a lock remains,
123
+ first establish that no setup process is active, inspect the saved settings and
124
+ vault, then remove the stale `n8r-surface.json.lock` manually and retry. Never
125
+ remove a lock while another setup may be running. Abandoned `.tmp` siblings may
126
+ be inspected and removed manually after establishing ownership; automatic setup
127
+ does not delete another invocation's files. No automatic age/PID-based lock theft.
128
+
129
+ ## Local inspection boundary
130
+
131
+ List direct legacy folder entries in filename order, one terminal-safe line each.
132
+ Read JSON/YAML definitions and HTML research records with existing bounded readers;
133
+ use title/type metadata, never source or extension contents. Unsupported, invalid,
134
+ oversized, unreadable, symlink and non-regular entries remain visible as errors.
135
+ Do not recurse, open source locations or execute HTML. Reads are bounded to 2 MiB
136
+ per artefact. Terminal controls, line separators and bidi characters are escaped.
137
+
138
+ The process identifies only its own PID and observation time. Runner/Lab process
139
+ status remains unknown; configured settings do not establish a live process.
140
+ There is no daemon, PID registry, source scan, network probe or inference.
141
+
142
+ ## Verification boundary
143
+
144
+ Transaction tests cover preserved values/bytes, malformed and oversized settings,
145
+ source overlap and symlinks, deterministic conflicting writes, a second real
146
+ process under a held lock, partial filesystem/publication failure and retry.
147
+ Process and PTY checks exercise the real command with independent filesystem
148
+ readback; the package check repeats them outside the checkout. See
149
+ [the verification record](vault-setup-verification.md) for exact revisions,
150
+ runtimes, human tasks and remaining limits. Automated rehearsal is not human
151
+ acceptance or proof of research, save/continue, or consumer compatibility.
@@ -0,0 +1,224 @@
1
+ # Capability and Bound Surface contract 0.2
2
+
3
+ This bounded library contract implements [#50](https://github.com/injectionator/n8r-surface/issues/50)
4
+ within the one AI Surface Model. It supports the [agreed delivery intent](surface-descriptions.md),
5
+ not a universal schema or a released Researcher workflow. The standalone skill
6
+ must not call or depend on the `n8r-surface` CLI. Skill artifact production is #51;
7
+ installed-workflow and human acceptance are #52. Observed Surface remains deferred.
8
+
9
+ For the revised #50 verification, start with [shared relationships 0.3](surface-relationships.md).
10
+ This earlier bounded profile and its fixtures remain readable without alteration;
11
+ `0.3` adds consistent node/edge metadata across both descriptions.
12
+
13
+ ## Versions and shared representation
14
+
15
+ `n8r.surface/0.2` requires `kind: "capability"` or `kind: "bound"`. It neither
16
+ reinterprets nor replaces `n8r.surface/0.1` selected definitions. Older readers
17
+ reject it. Do not change the version string to downgrade: doing so loses possible
18
+ versus configured meaning, exclusive alternatives, conflicts and instance identity.
19
+ There is no automatic conversion. Keep the original when making a separately
20
+ reviewed projection. Package versions and artifact contract versions are distinct.
21
+
22
+ Reuse the [0.1 envelope, research records and logical digests](contracts.md).
23
+ All fields below are required; empty arrays are permitted except where specified.
24
+ Objects are closed. This profile requires an empty `extensions` object and has
25
+ no arbitrary attributes or actual-setting fields. JSON is the only encoding;
26
+ `encode` and `decode` reject YAML for these descriptions. Research records retain
27
+ their existing JSON/YAML/HTML support. No new renderer is introduced here.
28
+
29
+ | Shared field | Meaning |
30
+ | --- | --- |
31
+ | `id`, `title`, `scope`, `revision`, `extensions` | Existing envelope; `extensions` must be `{}`. |
32
+ | `records` | Exact research `{id, revision, digest}` references. |
33
+ | `vocabularies` | Unique `{id, version}` entries; terms remain vocabulary-specific. |
34
+ | `nodes` | `{id, label, type: {vocabulary, term}}`; useful component/target identity only. |
35
+ | `coverage`, `gaps` | Explicit coverage limits, missing information and next research needs. |
36
+
37
+ A basis entry is `{record, revision, items}`. `items` is nonempty and unique,
38
+ referring to findings, or to decisions only in the dedicated `decisions` field.
39
+ Referenced research revisions must occur in `records`. Source identity, version,
40
+ date, locator, coverage and limitations live in the research record, not copied
41
+ raw configuration. All IDs are opaque, stable and case-sensitive. Labels are not
42
+ identity matching rules. An omitted node/edge/binding is unspecified, not absent.
43
+
44
+ ## Capability Surface
45
+
46
+ `kind: "capability"` adds `capabilities` and `exclusiveGroups`.
47
+
48
+ Each capability is `{id, from, to, type, state, basis, conditions, note}`. Endpoints
49
+ resolve to local nodes and type vocabulary resolves locally. Shared components,
50
+ parallel edges, cycles and self-loops are allowed. Each edge is a possible
51
+ relationship, never a selected composition. `conditions` lists material conditions
52
+ and `note` explains applicability and uncertainty. Empty conditions do not prove
53
+ unconditional support outside the stated scope.
54
+
55
+ | State | Evidence check |
56
+ | --- | --- |
57
+ | `possible` | Nonempty basis; all cited findings are `known`, subject equals `from`, property is `supports`, and every claim value equals the `to` node ID. |
58
+ | `absent` | Nonempty basis; all findings are `absent` with the same subject/property/target rule. This is scoped absence of support, not an unbound instance. |
59
+ | `conflicting` | Nonempty basis containing a conflicting finding; subject/property still match. Inspect all competing values in research. No target is selected. |
60
+ | `unknown`, `omitted`, `redacted`, `out-of-scope` | No support assertion. Any basis resolves to findings about that subject/property; notes explain the state. |
61
+
62
+ Each exclusive group is `{id, members}` with at least two distinct capability
63
+ IDs. It means **at most one** member may be configured in this bounded instance.
64
+ It does not require a selection, claim exhaustive alternatives, or resolve a
65
+ conflict. The synthetic authentication group is a fixture constraint, not a general
66
+ claim that every product makes OIDC and SAML mutually exclusive. Conditions and
67
+ other constraints remain human-readable; the checker does not execute them.
68
+
69
+ ## Bound Surface
70
+
71
+ `kind: "bound"` adds `capability`, `instance` and `bindings`:
72
+
73
+ - `capability` pins one Capability Surface `{id, revision, digest}`.
74
+ - `instance` is `{id, label}` with an opaque identity distinct from the capability
75
+ artifact and its components. It contains no location or credentials.
76
+ - Each binding is `{id, capability, state, claims, decisions, note}`. The inner
77
+ `capability` is an edge ID in the pinned Capability Surface. One entry per
78
+ capability is permitted in this bounded profile.
79
+ - Each claim is `{target, basis}`. `target` resolves to a local Bound node; basis
80
+ is nonempty. A useful target label may be `MongoDB Atlas` or `OIDC service`.
81
+ A target need not have the same ID as the product-level capability target.
82
+
83
+ | State | Required claims |
84
+ | --- | --- |
85
+ | `configured` | Exactly one target with known configuration evidence; capability state must be `possible`. |
86
+ | `conflicting` | At least two distinct targets, each evidenced; no selected target. |
87
+ | `unknown`, `omitted`, `redacted`, `out-of-scope` | No claims; the note explains why. |
88
+
89
+ A configuration finding has `subject` equal to the opaque instance ID, `property`
90
+ equal to the capability edge ID and claim values equal to target node IDs. It is
91
+ `known` or `conflicting`. Each cited finding must include the target it supports;
92
+ all of that finding's competing targets must be retained in the binding. All
93
+ known/conflicting findings for that same instance and capability in the Bound
94
+ description's referenced research are checked, including uncited basis items.
95
+ Multiple known findings supporting different targets also form a conflict. A configured
96
+ binding cannot cite a conflicting finding. Missing evidence cannot become an
97
+ unbound assertion. Explicit unbound/absence and multi-target configured slots are
98
+ outside this initial binding profile; preserve such source findings in research
99
+ and describe the coverage limit rather than forcing them into a supported state.
100
+
101
+ `decisions` refers only to research decisions, independently of source findings.
102
+ A human preference is not configuration evidence and cannot resolve a source
103
+ conflict by itself. Corrected source evidence belongs in a new research revision.
104
+ Configuration suffices; no reachability, runtime use or successful deployment is
105
+ asserted or checked. Target suitability and the truth/coverage of source prose
106
+ require inspection; matching references alone do not establish those facts.
107
+
108
+ ## Verification and revisions
109
+
110
+ The existing public APIs accept the new types:
111
+
112
+ - `validateArtefact(value)` checks closed shape, states, identity uniqueness,
113
+ local targets/vocabularies and declared research references.
114
+ - `verifyReferences(value, context)` additionally requires exact research and
115
+ Capability revisions/digests, checks evidence roles, subject/property/target
116
+ correspondence and exclusive groups. Include the Capability's research context
117
+ even when the Bound description cites a later research revision.
118
+ - `encode(value, 'json')` and `decode(text, 'json')` check structure and preserve
119
+ data. They do not imply that external references were checked.
120
+ - `verifySuccessor(previous, next)` checks parent revision/digest and retained
121
+ identities. Description kind cannot change. A retained node cannot change its
122
+ type; a retained capability cannot change endpoints/type. A retained binding
123
+ slot cannot change its capability ID, instance or capability-artifact identity.
124
+ A successor may pin a newer revision of the same Capability artifact and change
125
+ a binding target with new evidence. Check both references and succession.
126
+
127
+ A binding ID denotes the instance's slot for that capability, not an immutable
128
+ edge to one target. Target changes retain the slot ID and component IDs where
129
+ those components are the same. A different connection/capability needs a new ID.
130
+ Old bytes and old references stay unchanged; these pure library functions do not
131
+ write files or enforce history-wide ID reuse, atomic persistence or retention.
132
+ Cross-revision vocabulary changes and newly supplied source meaning still need
133
+ human review. Size/depth limits are the existing 2 MiB / 64-level codec limits,
134
+ not graph hop limits.
135
+
136
+ ## Privacy boundary
137
+
138
+ Supply only permitted, sanitized research. Do not copy actual URLs, IP addresses,
139
+ usernames, passwords, keys or raw settings into any note, label, identifier,
140
+ source locator, filename, HTML, JSON or retained evidence. Use opaque source
141
+ identifiers or sanitized snapshots whose digest describes those actual sanitized
142
+ bytes; never invent a digest of unseen raw material. A source that cannot be
143
+ inspected safely is a coverage limit. No raw-secret store is introduced.
144
+
145
+ Closed shapes and rejection of nonempty extensions prevent designated settings
146
+ fields from being stored, but **validation is not a secret detector**. A secret
147
+ could still be put in ordinary prose or an identifier. Producers must avoid
148
+ collecting it and check all output before retention; #51 owns that workflow.
149
+ Tests use synthetic sentinels, never real secrets. New-description validation and
150
+ reference errors omit input values/keys; parser syntax errors also omit source
151
+ snippets. Do not log raw rejected input or legacy research-validation exceptions.
152
+ Old research records allow arbitrary claim values and retain their existing
153
+ validation contract; sanitization remains essential before calling those APIs.
154
+
155
+ ## Human verification task list
156
+
157
+ Prerequisite: open this branch's [synthetic examples](../../examples/researcher/descriptions/README.md).
158
+ No CLI, inference, credentials, real configuration or live services are needed.
159
+
160
+ - [ ] Open `capability.json`. Expect MongoDB, OIDC and SAML as **possible**, an
161
+ authentication exclusive group and **unknown** inference support, without
162
+ instance bindings.
163
+ - [ ] Open `bound-r1.json` beside `sources.md` and `research-r1.json`. Expect a
164
+ **configured** MongoDB Atlas target, **conflicting** OIDC/SAML targets and
165
+ **unknown** inference. Find the separate OIDC preference; it must not erase
166
+ either source claim. Expect role/product identities, no actual settings.
167
+ - [ ] Open `bound-r2.json` and `research-r2.json`. Expect the same instance and
168
+ database binding ID, a self-hosted MongoDB target and exact predecessor
169
+ references. The original files still show Atlas and the earlier evidence.
170
+ - [ ] Report **Pass / Fail / Blocked**, inspected filenames and any incorrect
171
+ state, exposed value, lost conflict or broken reference. These are developer
172
+ fixtures; passing inspection is not installed Researcher acceptance.
173
+
174
+ ### Maintainer preparation and technical readback
175
+
176
+ From the repository root, use Node.js 22, 24 or 26. Run `npm ci` then
177
+ `npm run build` (exit 0; dependency installation uses the registry). This read-only
178
+ example exercises the library directly, not a skill dependency on a CLI:
179
+
180
+ ```sh
181
+ node --input-type=module <<'JS'
182
+ import {readFileSync} from 'node:fs';
183
+ import {decode, verifyReferences, verifySuccessor} from './dist/index.js';
184
+ const read = name => decode(readFileSync(
185
+ `examples/researcher/descriptions/${name}.json`, 'utf8'), 'json');
186
+ const context = ['research-r1', 'research-r2', 'capability'].map(read);
187
+ const before = read('bound-r1'), after = read('bound-r2');
188
+ verifyReferences(context[2], context);
189
+ verifyReferences(before, context);
190
+ verifyReferences(after, context);
191
+ verifySuccessor(before, after);
192
+ console.log(before.bindings.map(b => b.state).join(', '));
193
+ console.log(before.bindings[0].claims[0].target);
194
+ console.log(after.bindings[0].claims[0].target);
195
+ JS
196
+ ```
197
+
198
+ Expect exit 0 and exactly:
199
+
200
+ ```text
201
+ configured, conflicting, unknown
202
+ urn:target:atlas
203
+ urn:target:mongodb
204
+ ```
205
+
206
+ The readback changes no files; no cleanup is needed. A nonzero exit or different
207
+ states/targets fails this check. `npm test` covers malformed data, unsupported
208
+ YAML, privacy sentinels, conflicting/exclusive selections and revision/reference
209
+ drift. The package check exercises these assets through an installed library.
210
+
211
+ ## Baseline and evidence boundary
212
+
213
+ On 8 November 2026, inspection of installed Researcher skill **0.1.9** found its
214
+ explicit statement that it produces working notes and does not generate validated
215
+ research HTML or Surface definitions. This is a prerequisite blocker for the
216
+ requested installed-artifact journey, not an attempted AI investigation or proof
217
+ of generated artifacts. CLI availability is irrelevant to the standalone skill.
218
+ The authorized known gap is implemented here only at the contract/library layer.
219
+
220
+ The synthetic fixture journey above is the #50 agent rehearsal. It is not
221
+ Researcher-produced findings, an installed-skill rehearsal, human acceptance,
222
+ a real-instance inspection, or evidence of runtime use. #51 must package usable
223
+ standalone artifact production/checking resources; #52 must repeat the actual
224
+ installed conversation and independently read back its saved results.