cabloy 5.1.214 → 5.1.215

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.
@@ -116,6 +116,72 @@ A legacy suite with a different WBS or progress-table layout is not chart-compat
116
116
 
117
117
  These commands do not create planning authority, implement a WBS task, execute an ATP, produce acceptance evidence, or replace traceability/status review. Confirm the active root `package.json` and script input expectations before assuming equivalent behavior in Cabloy Start or another repository.
118
118
 
119
+ ## Evidence path sanitization
120
+
121
+ The dependency-free path tool lives in `repo-agent-governance/tools/evidence-paths/sanitize.mjs`. It sanitizes caller-supplied UTF-8 stdin, or independently checks explicitly selected files/directories without rewriting them:
122
+
123
+ ```bash
124
+ npm run --silent evidence:sanitize -- --help
125
+ npm run --silent evidence:check -- -- repo-specs/example/evidence
126
+ # Declare another checkout or external root; use the same mappings when checking.
127
+ npm run --silent evidence:sanitize -- --map '/synthetic/other-checkout=MAIN_CHECKOUT'
128
+ npm run --silent evidence:check -- --map '/synthetic/other-checkout=MAIN_CHECKOUT' -- evidence.pending.txt
129
+ ```
130
+
131
+ The last two commands illustrate a **synthetic** root, not a detected local location. `sanitize` waits for stdin; it does not run a producer. Use quiet npm output so npm banners are not mixed into the retained stream. Default checkout discovery comes from the tool's installed location, not the shell working directory; `--repo-root ROOT` overrides it. Repeatable `--map ROOT=ALIAS` declares additional absolute roots with stable uppercase aliases, such as `MAIN_CHECKOUT`. Longest matching roots win at path-segment boundaries. Checkout paths become repository-root-relative; explicit external mappings become `<ALIAS>/suffix`. Choose aliases that distinguish unrelated roots and review any sensitive suffixes.
132
+
133
+ ### Capture before retaining
134
+
135
+ Combine producer stdout/stderr **before** sanitization, never `tee` or spool raw output first. Use a new output filename, check sanitizer status, and retain the actual producer result, including failures. See [Verify narrowly and retain evidence](/ai/playbook-spec-execution#verify-narrowly-and-retain-evidence) for a Bash pipeline with immediate per-stage status capture. Zsh uses `pipestatus` instead of Bash `PIPESTATUS`. `pipefail` prevents a passing sanitizer from masking an upstream failure, but it does not preserve every stage's exact code. A failed sanitizer may leave earlier sanitized lines; partial output must not be accepted as evidence. The tool does not automatically intercept terminal or agent-tool output and does not authorize capturing secret-bearing streams.
136
+
137
+ ### Windows and PowerShell
138
+
139
+ The tool uses Node's native filesystem APIs on Windows, Linux and macOS; it requires the repository's Node.js version (`>=24.4.0`). Path-text recognition is cross-platform independently of the host OS. Native filesystem behavior is checked by the `evidence-platforms` CI matrix on Ubuntu, Windows and macOS. A configured matrix is not a successful run: inspect the actual job results before claiming all three platforms are verified.
140
+
141
+ From the repository root, PowerShell can invoke the CLI directly:
142
+
143
+ ```powershell
144
+ node .\repo-agent-governance\tools\evidence-paths\sanitize.mjs --help
145
+ node .\repo-agent-governance\tools\evidence-paths\sanitize.mjs check -- '.\evidence.pending.txt'
146
+ $checkExit = $LASTEXITCODE
147
+ # 0 = clean, 1 = paths found, 2 = incomplete/error
148
+ ```
149
+
150
+ For a **synthetic input smoke test only**, not evidence capture from a real producer:
151
+
152
+ ```powershell
153
+ $previousOutputEncoding = $OutputEncoding
154
+ try {
155
+ $OutputEncoding = [System.Text.UTF8Encoding]::new($false)
156
+ 'Unicode sample: café C:\Users\Synthetic\private\log.txt' |
157
+ node .\repo-agent-governance\tools\evidence-paths\sanitize.mjs sanitize
158
+ $sanitizeExit = $LASTEXITCODE
159
+ # Expected output: Unicode sample: café <PRIVATE_PATH>
160
+ } finally {
161
+ $OutputEncoding = $previousOutputEncoding
162
+ }
163
+ ```
164
+
165
+ Bash `pipefail`/`PIPESTATUS` and Zsh `pipestatus` are not PowerShell syntax. `$LASTEXITCODE` after a native pipeline is not a record of every stage's status. For real producer capture, use the Bash example in a Bash environment, or orchestration that explicitly observes both native processes and supplies UTF-8 bytes without a raw spool; do not claim the synthetic example preserves a producer exit code. Never accept evidence based only on the last pipeline command succeeding.
166
+
167
+ Prefer PowerShell 7.4+ for native byte-stream pipelines/redirection. Windows PowerShell 5.1 and text cmdlets can transcode output or create UTF-16 files; merely setting `$OutputEncoding` does not make all redirection byte-transparent. The sanitizer rejects invalid UTF-8/binary input rather than guessing an encoding. Avoid inserting text cmdlets into a byte-preserving capture pipeline, and preserve stderr and exit statuses deliberately. Do not change platform encoding globally.
168
+
169
+ POSIX mode-bit and unusual-filename tests are explicitly platform-specific. Windows permission failures are determined by native file-open/read errors, not simulated with POSIX `chmod(0)`. Symlink tests use Windows directory junctions where possible; unavailable file-symlink privileges are reported as capability skips, not successful coverage. The scan's no-symlink, no-environment-file and stable-filesystem requirements apply on every platform.
170
+
171
+ ### Coverage and result boundaries
172
+
173
+ Sanitization and checking share the same matcher. They recognize configured roots and bounded machine-local home/temp conventions, not every slash-prefixed path. Known private paths become `<PRIVATE_PATH>`; configured mappings take precedence so useful checkout-relative locations survive. Supported forms include POSIX home/temp paths, Windows drive/UNC paths, JSON-escaped backslashes and local `file:` URLs. Quote whitespace-containing path tokens; unquoted tokens end at whitespace or prose delimiters. Ordinary non-file URLs and generic API/container paths are not treated as filesystem paths. Other machine roots must be declared explicitly; unusual escaping, unknown filesystem locations, and sensitive relative suffixes still require manual review. This is **path-only tooling**, not a secret scanner or safe-publication certificate. Review credentials, tokens, customer data, and provider identifiers separately before retention/sharing.
174
+
175
+ Input must be UTF-8 text with lines no larger than 1 MiB; checked files are limited to 8 MiB each. Streaming handles split UTF-8/path chunks, CRLF and final unterminated lines; invalid encoding, NUL/non-text controls and oversized lines fail rather than emitting raw fragments. Disable producer color/terminal controls using its supported option (for example, `NO_COLOR=1` when honored); ANSI escape sequences are not silently stripped. The checker recursively visits explicit scopes in deterministic order, including hidden entries. It does not follow symlinks (including selected-scope ancestors), open special files, or read `.env*` files/directories. Select the canonical scope path when a system temp-directory alias is itself a symlink. Keep the scope tree stable while scanning; this is not an adversarial filesystem snapshot. Encountering unsupported, excluded or unreadable inputs means incomplete coverage, not clean success. Scope checks to reviewed evidence artifacts, not an arbitrary repository root. Diagnostics identify safe relative scope labels and line numbers, never matched source text or raw absolute scan roots.
176
+
177
+ | Exit | Meaning |
178
+ | ---- | ------------------------------------------------------------------------------------------------- |
179
+ | `0` | Sanitization completed, or the complete selected check scope has no recognized paths. |
180
+ | `1` | Checker detected recognized local paths. |
181
+ | `2` | Usage, I/O, encoding, size-limit or incomplete-scan failure; this takes precedence over findings. |
182
+
183
+ A clean check proves only declared path-recognition coverage. It does not prove producer success, ATP completion, approval, or release readiness. Preserve diagnostic codes, line/column locations, failures, exit codes and source hashes. Source hashes refer to original source bytes; label historical path-redacted diffs as non-byte-exact and not apply-ready. Tests run under `npm run test:agent-governance`; `spec:check` intentionally excludes evidence and is not a privacy checker.
184
+
119
185
  ## Agent-governance maintenance
120
186
 
121
187
  Use these Cabloy Basic maintenance commands when changing shared agent rules, root skill bundles, or adapter tooling:
@@ -10,6 +10,8 @@ const GOVERNANCE_SCRIPT_NAMES = [
10
10
  'spec:charts',
11
11
  'spec:charts:check',
12
12
  'spec:check',
13
+ 'evidence:sanitize',
14
+ 'evidence:check',
13
15
  'agent:governance:render',
14
16
  'agent:governance:check',
15
17
  'agent:governance:adopt',
@@ -294,6 +294,8 @@ function reconcileGovernancePackageJson(dryRun?: boolean): void {
294
294
  'test:agent-governance',
295
295
  'contract:gate',
296
296
  'spec:check',
297
+ 'evidence:sanitize',
298
+ 'evidence:check',
297
299
  ];
298
300
  const managedScripts = [...baselineScripts, ...governanceScripts];
299
301
  let changed = false;