pan-wizard 3.5.1 → 3.7.10

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 (93) hide show
  1. package/README.md +10 -10
  2. package/agents/pan-executor.md +18 -0
  3. package/agents/pan-experiment-runner.md +126 -0
  4. package/agents/pan-phase-researcher.md +16 -0
  5. package/agents/pan-plan-checker.md +80 -0
  6. package/agents/pan-planner.md +19 -0
  7. package/agents/pan-reviewer.md +2 -0
  8. package/agents/pan-verifier.md +41 -0
  9. package/bin/install-lib.cjs +55 -0
  10. package/bin/install.js +71 -22
  11. package/commands/pan/debug.md +1 -1
  12. package/commands/pan/experiment.md +219 -0
  13. package/commands/pan/health.md +1 -1
  14. package/commands/pan/learn.md +15 -1
  15. package/commands/pan/optimize.md +13 -0
  16. package/commands/pan/patches.md +10 -1
  17. package/commands/pan/phase-tests.md +1 -4
  18. package/commands/pan/todo-add.md +1 -1
  19. package/commands/pan/todo-check.md +1 -1
  20. package/hooks/dist/pan-cost-logger.js +54 -4
  21. package/hooks/dist/pan-trace-logger.js +72 -3
  22. package/package.json +67 -66
  23. package/pan-wizard-core/bin/lib/commands.cjs +8 -0
  24. package/pan-wizard-core/bin/lib/config.cjs +13 -2
  25. package/pan-wizard-core/bin/lib/context-budget.cjs +73 -0
  26. package/pan-wizard-core/bin/lib/core.cjs +13 -0
  27. package/pan-wizard-core/bin/lib/doc-lint/frontmatter.js +270 -0
  28. package/pan-wizard-core/bin/lib/doc-lint/reporter.js +45 -0
  29. package/pan-wizard-core/bin/lib/doc-lint/schema.js +202 -0
  30. package/pan-wizard-core/bin/lib/doc-lint/validate.js +190 -0
  31. package/pan-wizard-core/bin/lib/doc-lint/walk.js +135 -0
  32. package/pan-wizard-core/bin/lib/doc-lint.cjs +287 -0
  33. package/pan-wizard-core/bin/lib/experiment.cjs +501 -0
  34. package/pan-wizard-core/bin/lib/learn-index.cjs +235 -0
  35. package/pan-wizard-core/bin/lib/learn-lint.cjs +292 -0
  36. package/pan-wizard-core/bin/lib/optimize.cjs +474 -1
  37. package/pan-wizard-core/bin/lib/runner.cjs +472 -0
  38. package/pan-wizard-core/bin/pan-tools.cjs +222 -2
  39. package/pan-wizard-core/learnings/README.md +70 -0
  40. package/pan-wizard-core/learnings/index.json +540 -0
  41. package/pan-wizard-core/learnings/internal/.gitkeep +2 -0
  42. package/pan-wizard-core/learnings/internal/experiment-runner.md +81 -0
  43. package/pan-wizard-core/learnings/internal/external-research.md +93 -0
  44. package/pan-wizard-core/learnings/internal/loop-design.md +33 -0
  45. package/pan-wizard-core/learnings/internal/pan-dev-bugs.md +181 -0
  46. package/pan-wizard-core/learnings/universal/.gitkeep +2 -0
  47. package/pan-wizard-core/learnings/universal/atomic-state.md +21 -0
  48. package/pan-wizard-core/learnings/universal/binary-io.md +21 -0
  49. package/pan-wizard-core/learnings/universal/comment-syntax.md +21 -0
  50. package/pan-wizard-core/learnings/universal/composition.md +33 -0
  51. package/pan-wizard-core/learnings/universal/concurrency.md +33 -0
  52. package/pan-wizard-core/learnings/universal/dag-scheduler.md +33 -0
  53. package/pan-wizard-core/learnings/universal/data-driven-design.md +21 -0
  54. package/pan-wizard-core/learnings/universal/design-process.md +21 -0
  55. package/pan-wizard-core/learnings/universal/empirical-spike.md +21 -0
  56. package/pan-wizard-core/learnings/universal/error-handling.md +23 -0
  57. package/pan-wizard-core/learnings/universal/error-paths.md +21 -0
  58. package/pan-wizard-core/learnings/universal/glob-semantics.md +21 -0
  59. package/pan-wizard-core/learnings/universal/idempotency.md +21 -0
  60. package/pan-wizard-core/learnings/universal/invariants.md +21 -0
  61. package/pan-wizard-core/learnings/universal/io-patterns.md +21 -0
  62. package/pan-wizard-core/learnings/universal/numeric-edge-cases.md +21 -0
  63. package/pan-wizard-core/learnings/universal/output-conventions.md +21 -0
  64. package/pan-wizard-core/learnings/universal/parser-design.md +21 -0
  65. package/pan-wizard-core/learnings/universal/phase-locking.md +21 -0
  66. package/pan-wizard-core/learnings/universal/pipe-friendly-cli.md +21 -0
  67. package/pan-wizard-core/learnings/universal/schema-design.md +21 -0
  68. package/pan-wizard-core/learnings/universal/secret-handling.md +21 -0
  69. package/pan-wizard-core/learnings/universal/streaming-io.md +21 -0
  70. package/pan-wizard-core/learnings/universal/test-patterns.md +57 -0
  71. package/pan-wizard-core/learnings/universal/test-strategy.md +33 -0
  72. package/pan-wizard-core/learnings/universal/unicode.md +21 -0
  73. package/pan-wizard-core/learnings/universal/vendor-pattern.md +21 -0
  74. package/pan-wizard-core/references/guardrails.md +58 -0
  75. package/pan-wizard-core/references/handoff-decisions.md +156 -0
  76. package/pan-wizard-core/references/schemas/pan-command.schema.yml +39 -0
  77. package/pan-wizard-core/references/verification-patterns.md +31 -0
  78. package/pan-wizard-core/templates/config.json +2 -1
  79. package/pan-wizard-core/templates/idea.md +52 -0
  80. package/pan-wizard-core/templates/summary-complex.md +14 -5
  81. package/pan-wizard-core/templates/summary-minimal.md +6 -0
  82. package/pan-wizard-core/templates/summary-standard.md +14 -3
  83. package/pan-wizard-core/workflows/discuss-phase.md +108 -1
  84. package/pan-wizard-core/workflows/exec-phase.md +37 -1
  85. package/pan-wizard-core/workflows/execute-plan.md +14 -0
  86. package/pan-wizard-core/workflows/health.md +23 -0
  87. package/pan-wizard-core/workflows/new-project.md +65 -81
  88. package/pan-wizard-core/workflows/plan-phase.md +58 -0
  89. package/pan-wizard-core/workflows/transition.md +102 -7
  90. package/pan-wizard-core/workflows/verify-phase.md +14 -0
  91. package/scripts/build-hooks.js +7 -1
  92. package/scripts/generate-skills-docs.py +10 -8
  93. package/scripts/release-check.js +184 -0
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: glob-semantics
3
+ last_updated: 2026-04-27T09:49:20.726Z
4
+ patterns:
5
+ - id: P-205
6
+ summary: Translate **/X glob to allow zero-segment match (root-level X), per gitignore/minimatch convention
7
+ promoted_at: 2026-04-27T09:49:20.726Z
8
+ source_experiments: [whooo]
9
+ ---
10
+
11
+ # Glob Semantics (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-205 — Translate **/X glob to allow zero-segment match (root-level X), per gitignore/minimatch convention
16
+
17
+ **Evidence:** whooo trace.jsonl 11:45Z (error major): globToRegex bug where **/foo.md regex required at least one slash so foo.md at root did not match. Fix: emit (?:.*/)? so the slash is optional. Caught by walk.test.js regression test.
18
+
19
+ **Rule:** When implementing glob-to-regex translation, follow gitignore/minimatch convention: **/X must match BOTH dir/sub/X AND root-level X (the **/ segment can match zero path segments). Translate the **/ prefix to (?:.*/)? NOT .*/ . The latter requires at least one slash and silently misses root-level files.
20
+
21
+ **Applies in:** exec-phase (any glob/walker implementation), plan-phase (when planning file-walking tools)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: idempotency
3
+ last_updated: 2026-05-03T06:32:22.183Z
4
+ patterns:
5
+ - id: P-IDEM-001
6
+ summary: Make resumable operations safe to retry by combining a deterministic action key, a check-before-do guard, and atomic state transitions — not retry counters
7
+ promoted_at: 2026-05-03T06:32:22.183Z
8
+ source_experiments: [external]
9
+ ---
10
+
11
+ # Idempotency (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-IDEM-001 — Make resumable operations safe to retry by combining a deterministic action key, a check-before-do guard, and atomic state transitions — not retry counters
16
+
17
+ **Evidence:** External research synthesis: AWS API design guidance (idempotency tokens), Google Cloud client-spec (request IDs), Stripe API (Idempotency-Key header), the database literature on exactly-once semantics. PAN's own dag-scheduler P-1206 retry-then-skip-downstream rule depends on tasks being retry-safe but never explains how to make them so. Real failure modes observed: a runner that re-creates a 'created_at' timestamp on retry breaks ordering; a CLI that re-pushes a commit on retry creates a divergent ref; an installer that re-copies on retry overwrites user edits if the destination has changed since the first attempt.
18
+
19
+ **Rule:** For any operation that may run more than once (resumable pipeline, retry loop, dropped-network replay, user-triggered re-run): (1) compute a STABLE action key from the inputs (e.g. sha256 of the args), not from a timestamp or counter; (2) before executing, check whether the destination already reflects this exact action (file present with same hash, row present with same key, ref pointing where we want); (3) make the state transition atomically (write-tmp-then-rename per P-1201; INSERT … ON CONFLICT for SQL; CAS for in-memory); (4) on success record the action key so future retries short-circuit. Never use 'retry counter == N → skip' as your safety net — the counter resets on process restart but the side effect persists. Idempotency is a property of the OPERATION, not of a wrapper around it.
20
+
21
+ **Applies in:** resumable installers, sync/upload jobs, replicated writes, message-queue consumers, retry middleware, CI rerun handling, any operation that crosses a network or process boundary and may be replayed
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: invariants
3
+ last_updated: 2026-04-27T10:50:44.078Z
4
+ patterns:
5
+ - id: P-901
6
+ summary: Round-trip tests (parse(write(x)) === x) catch asymmetric escape/decode bugs in format converters
7
+ promoted_at: 2026-04-27T10:50:44.078Z
8
+ source_experiments: [whoocsv]
9
+ ---
10
+
11
+ # Invariants (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-901 — Round-trip tests (parse(write(x)) === x) catch asymmetric escape/decode bugs in format converters
16
+
17
+ **Evidence:** whoocsv sess_20260427T143000 14:34Z surprise: round-trip preserves data through commas/quotes/newlines. Single property test covers what 5 unit tests would
18
+
19
+ **Rule:** When writing format converters (CSV, JSON, YAML, XML, custom), include at least one round-trip test: assert parse(write(input)) deepEquals input for a representative non-trivial input. Catches escape/decode asymmetries that unit tests miss.
20
+
21
+ **Applies in:** exec-phase (any parser/serializer pair)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: io-patterns
3
+ last_updated: 2026-04-27T10:15:00.878Z
4
+ patterns:
5
+ - id: P-401
6
+ summary: Synchronous stdin via fs.readFileSync(0) is the cleanest CLI pattern
7
+ promoted_at: 2026-04-27T10:15:00.877Z
8
+ source_experiments: [whoosort]
9
+ ---
10
+
11
+ # Io Patterns (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-401 — Synchronous stdin via fs.readFileSync(0) is the cleanest CLI pattern
16
+
17
+ **Evidence:** whoosort sess_20260427T130000 11:06Z decision: sync matches CLI shape, eliminates buffering bugs, plays well with spawnSync({input}) for tests. Async stdin only justified for streaming gigabytes.
18
+
19
+ **Rule:** When building a CLI that reads stdin, prefer fs.readFileSync(0, 'utf-8') over async stream consumption unless you actually need to process unbounded input. Sync I/O matches the shape of node-test spawnSync({input}), avoids buffering bugs, and keeps the CLI synchronous-by-default which simplifies error handling.
20
+
21
+ **Applies in:** exec-phase (CLI implementation), test-strategy (subprocess testing of stdin-driven tools)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: numeric-edge-cases
3
+ last_updated: 2026-04-27T10:22:49.117Z
4
+ patterns:
5
+ - id: P-601
6
+ summary: Test numeric-scaling code with all-equal-values, single-value, zero, and mixed-sign edge cases
7
+ promoted_at: 2026-04-27T10:22:49.117Z
8
+ source_experiments: [whoograph]
9
+ ---
10
+
11
+ # Numeric Edge Cases (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-601 — Test numeric-scaling code with all-equal-values, single-value, zero, and mixed-sign edge cases
16
+
17
+ **Evidence:** whoograph sess_20260427T133500 13:38Z error (major): scaleBars all-equal branch was bypassed because Math.max(...values, 0) inflated min/max range. Test 'zero range -> all bars length 1' caught it.
18
+
19
+ **Rule:** When implementing numeric scaling/normalization code (charts, percentages, ratios, gradients), write tests for ALL of: empty input, single value, all-equal values, all-zero values, mixed-sign values, and extreme range. The all-equal case is the most commonly missed because synthetic test data tends to have variation. Treat all-equal as a deliberate special case (visual indicator-only bars), not as a math edge case to silently absorb.
20
+
21
+ **Applies in:** exec-phase (any visualization, normalization, or scoring code)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: output-conventions
3
+ last_updated: 2026-04-27T10:15:00.961Z
4
+ patterns:
5
+ - id: P-402
6
+ summary: Always emit a trailing newline from CLI output
7
+ promoted_at: 2026-04-27T10:15:00.960Z
8
+ source_experiments: [whoosort]
9
+ ---
10
+
11
+ # Output Conventions (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-402 — Always emit a trailing newline from CLI output
16
+
17
+ **Evidence:** whoosort 13:12Z gap: trailing-newline convention enforced in joinLines but not documented in --help. Most Unix tools do this; downstream tooling expects it.
18
+
19
+ **Rule:** CLI tools should always emit a trailing newline at the end of output unless the user explicitly opts out. Mirrors POSIX text-file convention and matches downstream expectations (pipes, byte counters, line counters). Document the behavior in --help and tests can assert it deterministically.
20
+
21
+ **Applies in:** exec-phase (CLI implementation)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: parser-design
3
+ last_updated: 2026-05-02T15:25:33.484Z
4
+ patterns:
5
+ - id: P-1203
6
+ summary: Compile-once / evaluate-many: parse user predicates/keys/queries into a closure or AST at startup, reuse on every row. 10-100x speedup vs re-parsing per row
7
+ promoted_at: 2026-05-02T15:25:33.484Z
8
+ source_experiments: [whoolog, whoodb, whooschema]
9
+ ---
10
+
11
+ # Parser Design (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-1203 — Compile-once / evaluate-many: parse user predicates/keys/queries into a closure or AST at startup, reuse on every row. 10-100x speedup vs re-parsing per row
16
+
17
+ **Evidence:** whoolog where.js, resolve-key.js, time-filter.js: each compiles once and exports a closure. whoodb lexer/parser/analyzer is a 3-stage compile-once pipeline. Phase 1-02 summary: '109 lines: compileWhere(expr), lex(expr), parseRhs(raw). Operator order locked.' Performance contract: filter 1M lines in <10s requires this discipline.
18
+
19
+ **Rule:** When user input (a where-expr, a dotted key path, a SQL query, a regex) will be evaluated against many rows, parse it ONCE into a callable (closure, AST, or compiled regex), then call repeatedly. Don't re-tokenize/re-parse inside the per-row hot loop. Examples: whoolog compileKey('a.b.c') returns row => row.a?.b?.c; compileWhere('level=error') returns row => row.level === 'error'. Type-aware equality via JSON.stringify when comparing user-supplied literals to JSON values keeps the evaluator simple.
20
+
21
+ **Applies in:** predicate/expression evaluators, query engines, validators with reusable schema
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: phase-locking
3
+ last_updated: 2026-05-02T17:52:25.816Z
4
+ patterns:
5
+ - id: P-1208
6
+ summary: Lock cross-cutting decisions (module system, error contract, exit codes) in Plan 01 of Phase 1; downstream plans IMPORT from those locked modules instead of re-deciding
7
+ promoted_at: 2026-05-02T17:52:25.816Z
8
+ source_experiments: [whooflow, whoocache]
9
+ ---
10
+
11
+ # Phase Locking (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-1208 — Lock cross-cutting decisions (module system, error contract, exit codes) in Plan 01 of Phase 1; downstream plans IMPORT from those locked modules instead of re-deciding
16
+
17
+ **Evidence:** whooflow Plan 01-01 summary: 'ESM lock-in committed in package.json — no later plan revisits the module system question. Node 18.17 floor encoded — first cross-cutting prerequisite from context.md is satisfied. Error -> exit-code contract (CLI-10) defined and tested; Plans 02-05 import from src/errors.js instead of redefining.' whoocache 02-composition: 'lock.js: no-op pass-through shim; signature locked for Phase 2 body swap.' Both shipped clean phases without cross-plan rework.
18
+
19
+ **Rule:** When breaking work into multi-plan phases, the FIRST plan should establish cross-cutting contracts that all later plans depend on: package.json type (CJS vs ESM), Node version floor, error class hierarchy, exit code map. Use a 'pass-through shim' for forward-locked APIs — write the function signature in Plan 01 returning a no-op or pass-through, swap the body in Plan N. This prevents cross-plan churn ('which error format does plan 03 use?') and means plans can be revised in isolation.
20
+
21
+ **Applies in:** multi-plan phases, multi-module CLIs, any work decomposable into a stable foundation + extensions
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: pipe-friendly-cli
3
+ last_updated: 2026-05-02T17:52:45.798Z
4
+ patterns:
5
+ - id: P-1207
6
+ summary: Pipe-friendly CLI: handle EPIPE as exit-0, read stdin only when not a TTY, write one record per line with trailing newline
7
+ promoted_at: 2026-05-02T17:52:45.798Z
8
+ source_experiments: [whoolog, whoodb]
9
+ ---
10
+
11
+ # Pipe Friendly Cli (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-1207 — Pipe-friendly CLI: handle EPIPE as exit-0, read stdin only when not a TTY, write one record per line with trailing newline
16
+
17
+ **Evidence:** whoolog bin/whoolog.js: 67 lines including shebang, EPIPE-as-exit-0 handler, top-level help, subcommand dispatch. lib/source.js: Stdin only when not a TTY. Stream errors converted to clean exit 1 with stderr message. Verified by integration tests piping through head and confirming exit 0.
18
+
19
+ **Rule:** CLIs that compose with shell pipes need three behaviors: 1) EPIPE on stdout means downstream closed early (e.g. head -3 took 3 lines and exited) — listen for process.stdout error event, exit 0 not 1. 2) Read stdin ONLY when process.stdin.isTTY is false; if a TTY, stdin blocks waiting for typing. Use an explicit --files flag for files, fall back to stdin only when piped in. 3) Always write trailing newline (process.stdout.write(line + LF), not just line) so the next pipe stage sees a complete record.
20
+
21
+ **Applies in:** any zero-dep Node.js CLI intended for shell composition
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: schema-design
3
+ last_updated: 2026-04-27T09:48:41.048Z
4
+ patterns:
5
+ - id: P-202
6
+ summary: Infer schemas from real-file sampling pass; do not author them from imagination
7
+ promoted_at: 2026-04-27T09:48:41.048Z
8
+ source_experiments: [whooo]
9
+ ---
10
+
11
+ # Schema Design (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-202 — Infer schemas from real-file sampling pass; do not author them from imagination
16
+
17
+ **Evidence:** whooo trace.jsonl 11:52Z (gap major) and 11:53Z (gap minor): hand-authored name pattern rejected 44/52 PAN command files using pan: prefix; argument-hint field present in 30+ files was missing from schema entirely. 30+ unknown-field warnings as a result.
18
+
19
+ **Rule:** When authoring a schema for an existing corpus, run a sampling pass first: extract observed fields and value patterns from representative real files, THEN write the schema. Manual schemas guarantee a mismatch with reality. Provide a schema generate dir capability for any corpus-validation tool.
20
+
21
+ **Applies in:** plan-phase (designing validation tooling), exec-phase (schema authoring)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: secret-handling
3
+ last_updated: 2026-05-03T06:32:54.332Z
4
+ patterns:
5
+ - id: P-SEC-001
6
+ summary: Treat secrets as a typed boundary, not a string — redact at the logger, deny-list at the committer, never round-trip through prose-serialized state
7
+ promoted_at: 2026-05-03T06:32:54.332Z
8
+ source_experiments: [external]
9
+ ---
10
+
11
+ # Secret Handling (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-SEC-001 — Treat secrets as a typed boundary, not a string — redact at the logger, deny-list at the committer, never round-trip through prose-serialized state
16
+
17
+ **Evidence:** External research synthesis: OWASP Top-10 A02 (Cryptographic Failures), GitGuardian / TruffleHog state-of-secrets reports (2025: ~24M leaked credentials/year, half from logs and CI artifacts), Google Cloud Secret Manager design notes, the post-mortems of Stripe-key-in-stripe.com-Sentry incident (2017) and Uber GitHub key leak (2016). PAN-relevant baseline: PAN ships harvest.json that captures process output verbatim; pan-tools commit warns about .env (string match) but no agent codifies the rule. Internal observation: the recent notepadrs experiment harvested optimization traces (~100s of agent IO events) directly into the source repo without a redaction pass — fine for this experiment, dangerous as a general pattern as experiments grow to authenticated workflows.
18
+
19
+ **Rule:** Secrets must be three things at once: (1) a TYPED VALUE, not a string — wrap as Secret<T> / SecretString / opaque struct so toString() returns '[REDACTED]' and Display/Debug/JSON-serialize all respect the type. (2) DENY-LISTED at the persistence boundary — committer/publisher/uploader runs a regex sweep for known secret SHAPES (AWS AKIA, ghp_, sk-, JWT 3-part base64, PEM blocks, generic high-entropy 32+ char strings) AND a path deny-list (.env, *.pem, *.p12, credentials.json, config.local.*). Match → block, not warn. (3) NEVER ROUND-TRIPPED THROUGH PROSE STATE — agent traces, summary.md, harvest.json, plan.md must scrub secret-shaped tokens before write. Read-time scrubbing is not enough; an attacker who steals the file before scrubbing has the secret. Final rule: if a value is a secret, it goes through ONE pipe (env var → in-memory typed wrapper → consumer) and NEVER lands on disk under a path the committer can reach.
20
+
21
+ **Applies in:** any tool that captures process output (loggers, harvest, trace captures, AI agent transcripts), any tool that writes commits or publishes artifacts (git committers, npm/cargo publish, CI artifact uploaders), any framework that serializes state to disk (orchestrators, schedulers, replay buffers), any external integration handler
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: streaming-io
3
+ last_updated: 2026-05-02T15:25:23.330Z
4
+ patterns:
5
+ - id: P-1202
6
+ summary: Streaming JSONL via readline + for-await: per-line parse, never load whole file. Handles 100MB / 1M-line files in seconds without OOM
7
+ promoted_at: 2026-05-02T15:25:23.330Z
8
+ source_experiments: [whoolog, whoodb]
9
+ ---
10
+
11
+ # Streaming Io (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-1202 — Streaming JSONL via readline + for-await: per-line parse, never load whole file. Handles 100MB / 1M-line files in seconds without OOM
16
+
17
+ **Evidence:** whoolog source.js + filter.js processed 1M-line synthetic fixture in <10s with stable memory. whoodb evaluator uses the same pattern for streaming WHERE/projection. Both verified against real PAN tokens.jsonl.
18
+
19
+ **Rule:** For line-oriented inputs (JSONL, NDJSON, log files), use Node's readline.createInterface({input: createReadStream(path)}) with for-await-of iteration. Each line parses independently — malformed lines emit a stderr warning and continue, unless --strict. NEVER use fs.readFileSync(path).split('\n') for files of unknown size. Pair with a streaming output (process.stdout.write(JSON.stringify(row) + '\n')) so the whole pipeline is bounded memory.
20
+
21
+ **Applies in:** JSONL processors, log filters, line-oriented data tools
@@ -0,0 +1,57 @@
1
+ ---
2
+ topic: test-patterns
3
+ last_updated: 2026-05-03T03:29:54.837Z
4
+ patterns:
5
+ - id: P-001
6
+ summary: Assert non-deterministic CLI output by SHAPE not VALUE
7
+ promoted_at: 2026-04-27T09:26:19.280Z
8
+ source_experiments: [whooo]
9
+ - id: P-002
10
+ summary: Use execFileSync over execSync for CLI subprocess tests
11
+ promoted_at: 2026-04-27T09:26:26.755Z
12
+ source_experiments: [whooo]
13
+ - id: P-204
14
+ summary: Test the violation/error CONTRACT (codes + field names + severity), not message prose
15
+ promoted_at: 2026-04-27T09:49:02.194Z
16
+ source_experiments: [whooo]
17
+ - id: P-NPRS-004
18
+ summary: Pure-logic helper extracted from side-effect wrapper makes Win32/IO/network code testable without a real environment
19
+ promoted_at: 2026-05-03T03:29:54.837Z
20
+ source_experiments: [notepadrs]
21
+ ---
22
+
23
+ # Test Patterns (AI-derived)
24
+
25
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
26
+
27
+ ## P-001 — Assert non-deterministic CLI output by SHAPE not VALUE
28
+
29
+ **Evidence:** whooo build: a naive test asserting the exact ISO timestamp would have been flaky on every run. Asserting the regex shape /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z/ catches output regressions without flakiness.
30
+
31
+ **Rule:** When testing CLI output that contains non-deterministic data (timestamps, UUIDs, hashes, PIDs, paths), assert the SHAPE of the output via regex rather than the exact value. The shape is the contract; the value is incidental.
32
+
33
+ **Applies in:** exec-phase, focus-exec, plan-phase (when planning test cases)
34
+
35
+ ## P-002 — Use execFileSync over execSync for CLI subprocess tests
36
+
37
+ **Evidence:** whooo test/whooo.test.js used execFileSync('node', [BIN]) directly. Cross-platform safe, no shell-injection surface, no dependency on shell behavior.
38
+
39
+ **Rule:** When testing CLI binaries via subprocess, use execFileSync(bin, args) rather than execSync('command string'). execFileSync skips the shell, avoids shell-injection risk, and is portable across Windows/Unix without quoting differences.
40
+
41
+ **Applies in:** exec-phase (writing tests), test-file generation in plan-phase
42
+
43
+ ## P-204 — Test the violation/error CONTRACT (codes + field names + severity), not message prose
44
+
45
+ **Evidence:** whooo trace.jsonl 11:40Z (decision minor): Tests assert violation SHAPE not exact string messages. Cites P-001 and explicitly generalizes the timestamp-shape principle. All 9 validate.test.js tests follow this pattern: they assert code, field, severity but never the message text.
46
+
47
+ **Rule:** When testing structured error/violation/diagnostic output of the form {file, line, code, message, severity, ...}, assert on the stable contract fields (code, field, severity, type) and NEVER on the human-readable message text. Messages evolve for clarity; codes are the API consumers depend on. Generalizes P-001 (timestamp-shape): same principle, broader application.
48
+
49
+ **Applies in:** exec-phase (writing tests for any tool emitting structured diagnostics), plan-phase (test-case design)
50
+
51
+ ## P-NPRS-004 — Pure-logic helper extracted from side-effect wrapper makes Win32/IO/network code testable without a real environment
52
+
53
+ **Evidence:** notepadrs recurring split: dispatch_pure.rs (decision logic) + dispatch.rs (Win32 wiring); decide_next_wrap_state (pure) + apply_wrap (unsafe Win32); tab_close_decision pure fn + Tab Drop impl; categorize_open_error (pure) + open_path_external (Win32). 109 tests in Phase 2; 35 gap-coverage tests in Phase 3 verification — almost all hit the pure helpers headlessly via cargo test, no Windows desktop required.
54
+
55
+ **Rule:** When you write a function that mixes a NON-OBVIOUS DECISION (what to do) with a SIDE EFFECT (Win32 message, file write, network call), split it into two functions in two files: foo_pure.rs::decide_foo(&inputs) -> FooDecision (pure, headless-testable) + foo.rs::apply_foo(&hwnd_or_handle, decision) (the unsafe / I/O effect). Test the decision exhaustively at the unit layer; cover the wrapper with a thin smoke test (or skip it if it's just 5 lines of API plumbing). Cost: one extra file per side-effect family. Payoff: cargo test / npm test stays fast and reproducible across platforms, and the decision logic gets the test density it deserves.
56
+
57
+ **Applies in:** Win32 message dispatch, IPC handlers, network request encoding, database query construction, any code that mixes decision logic with a side effect
@@ -0,0 +1,33 @@
1
+ ---
2
+ topic: test-strategy
3
+ last_updated: 2026-04-27T10:25:32.100Z
4
+ patterns:
5
+ - id: P-201
6
+ summary: Test parsers and validators against real-world corpus fixtures from day one, not synthetic ones
7
+ promoted_at: 2026-04-27T09:48:31.640Z
8
+ source_experiments: [whooo]
9
+ - id: P-701
10
+ summary: When all tests pass first-run on a non-trivial build, that's a saturation signal — promoted patterns are constraining the design space
11
+ promoted_at: 2026-04-27T10:25:32.100Z
12
+ source_experiments: [whoodiff]
13
+ ---
14
+
15
+ # Test Strategy (AI-derived)
16
+
17
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
18
+
19
+ ## P-201 — Test parsers and validators against real-world corpus fixtures from day one, not synthetic ones
20
+
21
+ **Evidence:** whooo sess_20260427T113000 trace.jsonl 11:50Z surprise event: 252 errors on PAN dogfood despite 39/39 unit tests passing. Synthetic fixtures gave false green light; the block-style YAML list scope-cut in DESIGN_SPEC was wrong but invisible to unit tests.
22
+
23
+ **Rule:** When building any parser, validator, or schema-checker for a structured format, include at least one fixture sampled DIRECTLY from the real-world corpus before declaring v1 done. The dogfood gate runs BEFORE asserting passed, not after. Synthetic fixtures lie; real-corpus fixtures don't.
24
+
25
+ **Applies in:** plan-phase (fixture planning), exec-phase (parser/validator implementation), verify-phase (gate definition)
26
+
27
+ ## P-701 — When all tests pass first-run on a non-trivial build, that's a saturation signal — promoted patterns are constraining the design space
28
+
29
+ **Evidence:** whoodiff sess_20260427T135000 13:57Z surprise: 12 tests, all passed first run, zero deviations during a multi-file build with diff/format/parser logic. With 9 prior universal patterns (P-201..P-205, P-401..P-403, P-501, P-602) acting as default behavior, the space of wrong choices is heavily constrained. Compare to whooo (first run: 8 unit tests passed but 252 errors on dogfood) and whoosort (1 deviation).
30
+
31
+ **Rule:** Track per-experiment 'first-run pass rate' (% of tests passing without iteration) as a quality signal for the promote pipeline. Rising rate = patterns are saturating; design space is shrinking. Falling rate = need more diverse experiments to surface new failure modes. Saturation isn't slowdown — it's the point: the loop's job is to convert lessons into defaults, then the defaults work invisibly.
32
+
33
+ **Applies in:** promote workflow, /pan:learn analysis, post-experiment retrospective
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: unicode
3
+ last_updated: 2026-04-27T10:53:02.556Z
4
+ patterns:
5
+ - id: P-1001
6
+ summary: JS string .length counts UTF-16 code units, not characters; surrogate pairs are length 2 but visually one character
7
+ promoted_at: 2026-04-27T10:53:02.556Z
8
+ source_experiments: [whooemoji]
9
+ ---
10
+
11
+ # Unicode (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-1001 — JS string .length counts UTF-16 code units, not characters; surrogate pairs are length 2 but visually one character
16
+
17
+ **Evidence:** whooemoji 14:52Z surprise: rocket emoji is one emoji but '🚀'.length === 2. Test asserts both invariants explicitly to document the trap.
18
+
19
+ **Rule:** When code reasons about string length for VISUAL/USER-FACING purposes (column alignment, character limits, truncation), do NOT use String.prototype.length — it counts UTF-16 code units. Use [...str].length for code points (still wrong for grapheme clusters but better) or Intl.Segmenter for proper graphemes. When length must match user expectation (e.g. social-media char counts), document which definition you're using.
20
+
21
+ **Applies in:** exec-phase (any code that handles user-facing strings: CLIs, validators, formatters, truncators)
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: vendor-pattern
3
+ last_updated: 2026-04-27T10:28:48.403Z
4
+ patterns:
5
+ - id: P-801
6
+ summary: Vendoring small zero-dep modules into a project's bin/lib/ subdirectory works for downstream consumers without npm dep
7
+ promoted_at: 2026-04-27T10:28:48.403Z
8
+ source_experiments: [whoorun]
9
+ ---
10
+
11
+ # Vendor Pattern (AI-derived)
12
+
13
+ > Auto-maintained by `pan-tools learn promote`. Each pattern was extracted from one or more experiment runs (see source_experiments). Patterns are **advisory** — orchestrators should weight them against current context.
14
+
15
+ ## P-801 — Vendoring small zero-dep modules into a project's bin/lib/ subdirectory works for downstream consumers without npm dep
16
+
17
+ **Evidence:** whoorun sess_20260427T140500 14:08Z surprise (critical): META test passed first try. lib/taskfile.js requires d:/PanWizard/pan-wizard-core/bin/lib/doc-lint/frontmatter.js by absolute path. The vendored module: exists at the documented location, exports the documented API (parseFrontmatter), parses real task-file frontmatter correctly. No npm dep, no symlink, no package.json magic.
18
+
19
+ **Rule:** When a project ships a small (<300 LOC), zero-dep, structure-stable module that's likely to be useful to downstream consumers (parser, validator, formatter), vendor it under bin/lib/<topic>/ and document the require path. The vendor pattern works as an alternative to publishing-as-npm when (a) the module's surface is small, (b) the consumer can pin to a specific source-repo path, and (c) the project doesn't want the maintenance overhead of a separate package. Trade-off: consumers must update manually when the upstream module changes — versioned by the parent project's release tag.
20
+
21
+ **Applies in:** v3.7.x design (PAN's doc-lint vendor pattern), v3.8+ when shipping more vendored utilities
@@ -0,0 +1,58 @@
1
+ # AI Agent Guardrails for PAN Wizard
2
+
3
+ This document is read by AI agents (Claude, Codex, Gemini, OpenCode, Copilot)
4
+ executing PAN workflows. It encodes rules that prevent the most common shortcut
5
+ failures observed across PAN Wizard development. Re-read at the start of every
6
+ phase — context compaction may have dropped earlier sections.
7
+
8
+ ## Common Shortcuts to Resist
9
+
10
+ | Shortcut | Why it fails | Correct action |
11
+ |----------|--------------|----------------|
12
+ | "User's request is clear, no need to clarify" | You're guessing at intent. Phase 0 catches misunderstandings before scaffolding. | Run the Phase 0 4-question check (see `new-project.md` / `plan-phase.md`). |
13
+ | "Phase tests passed locally, /pan:verify-phase isn't needed" | One run isn't validation. verify-phase checks state consistency, doc sync, blockers, and the full suite — not just the phase's own tests. | Always run `/pan:verify-phase` before marking a phase complete. |
14
+ | "I'll skip /pan:focus-scan and pick the next item myself" | Manual selection ignores priority/budget logic in `focus.cjs`. You'll bias toward easy items and miss higher-priority work. | Use `/pan:focus-scan` → `/pan:focus-plan` → `/pan:focus-exec`. |
15
+ | "I'll bump the model / add a flag / refactor while I'm here" | Scope creep. The user asked for one change; surrounding cleanup belongs in a separate item. | Do only the requested change. Note unrelated cleanup as a TODO for a future focus-scan. |
16
+ | "I'll mark this phase complete; the docs can lag behind" | Doc/state drift compounds. By the next session, the agent reads stale docs and proceeds on false assumptions. | Run `/pan:sync` (or the equivalent doc-sync step) before phase completion. CHANGELOG and version bumps are part of the phase, not after it. |
17
+
18
+ ## Code Preservation Principle
19
+
20
+ Code modifications require surgical precision — alter only the lines directly
21
+ targeted by the user's request. Strictly preserve all surrounding code.
22
+
23
+ Before finalizing any edit, verify:
24
+
25
+ 1. **Target identification** — the exact lines to change, based solely on the user's instructions
26
+ 2. **Preservation check** — all code, config values (model, version, api_key), comments, and formatting outside the target are identical
27
+
28
+ If you must touch surrounding code (e.g., to fix an import a rename broke),
29
+ name it explicitly in your reply: "Also updating import in X because the
30
+ rename broke it." Never silently expand scope.
31
+
32
+ ## Stop-the-Line Rule
33
+
34
+ If a change breaks something that was working: **stop feature work and fix
35
+ the regression first.** Do not push forward with "I'll circle back" —
36
+ regressions compound across sessions and become 10x harder to localize later.
37
+
38
+ A failing test, a broken command, or a manifest-checksum mismatch is a
39
+ stop-the-line event. Resume feature work only after the line is restored.
40
+
41
+ ## Systematic Debugging Sequence
42
+
43
+ When something breaks, follow this sequence — don't shotgun fixes:
44
+
45
+ 1. **Reproduce** — exact failing command, full error output
46
+ 2. **Localize** — narrow to module, config, or environment
47
+ 3. **Fix one variable at a time** — changing instruction + tool + config simultaneously means you won't know what fixed it
48
+ 4. **Verify** — rerun the exact reproduction command
49
+ 5. **Guard** — if the bug was non-obvious, add a test to catch regressions
50
+
51
+ ## Cross-References
52
+
53
+ - `references/tdd.md` — test-driven development patterns
54
+ - `references/verification-patterns.md` — phase verification methodology
55
+ - `references/checkpoints.md` — human-in-the-loop checkpoint protocol
56
+ - `workflows/exec-phase.md` — phase execution checklist
57
+ - `workflows/verify-phase.md` — phase completion validation
58
+ - `workflows/plan-phase.md` — phase planning and decomposition
@@ -0,0 +1,156 @@
1
+ # Handoff Decisions Reference (P-RES-003)
2
+
3
+ This reference defines the schema for the **decisions trace** that flows
4
+ through PAN's serial pipeline:
5
+
6
+ ```
7
+ planner ─[plan.md "Plan Decisions"]──▶ executor ─[summary.md "Implementation Decisions"]──▶ verifier
8
+ ```
9
+
10
+ ## Why this exists
11
+
12
+ Cognition's "Don't build multi-agents" (Jun 2025) named the dominant failure
13
+ mode of pipeline-based AI: parallel sub-agents fail because every action
14
+ encodes unstated decisions that downstream agents reconcile blindly.
15
+ Anthropic's countervailing piece argues breadth-first **reads** parallelize
16
+ fine but **writes** need a single coherent trace. PAN is mostly serial, but
17
+ its file-mediated handoff carried only **artifacts** (plan.md, summary.md) —
18
+ not the **reasoning** behind them. This reference fixes that without changing
19
+ the file contract: it adds a structured section to each artifact that captures
20
+ what would otherwise stay in the agent's head.
21
+
22
+ ## Schema — `## Plan Decisions` (planner → executor handoff)
23
+
24
+ Lives in `plan.md`, between `<objective>` and `<tasks>`:
25
+
26
+ ```markdown
27
+ ## Plan Decisions
28
+
29
+ ### Locked (executor MUST follow)
30
+ - D-1: <statement>. Why: <rationale>. Source: <context.md REQ-X | research.md | architecture constraint>.
31
+
32
+ ### Open (executor's discretion within constraints)
33
+ - O-1: <decision space>. Constraints: <list>. Reason left open: <why planner did not lock>.
34
+
35
+ ### Considered and rejected
36
+ - R-1: <alternative>. Rejected because: <reason>.
37
+ ```
38
+
39
+ If the plan is mechanical and there genuinely are no notable decisions, write
40
+ this single line instead of empty buckets:
41
+
42
+ ```markdown
43
+ ## Plan Decisions
44
+
45
+ No decisions worth documenting — plan is mechanical implementation of must_haves.
46
+ ```
47
+
48
+ ### Bucket semantics
49
+
50
+ - **Locked** — Constraints the executor MUST follow. If the executor
51
+ diverges, that's a deviation and must be logged in the summary.
52
+ Examples: library choice, security pattern, naming convention,
53
+ protocol shape, error-handling style.
54
+
55
+ - **Open** — Choices left to the executor's judgment, but bounded.
56
+ The planner names the decision space and the constraints; the
57
+ executor picks within them. The executor should log which option
58
+ they took in the summary's `Decisions Taken`.
59
+ Example: "Hashing algorithm: bcrypt | argon2 | scrypt. Constraint:
60
+ zero-deps Node builtin. Reason left open: equivalent for this use case."
61
+
62
+ - **Considered and rejected** — Alternatives the planner explored and
63
+ ruled out. Helps the executor avoid re-deriving the same path and
64
+ helps the verifier understand why the implementation looks the way
65
+ it does.
66
+
67
+ ### When to use each bucket
68
+
69
+ | Bucket | When to fill |
70
+ |--------|--------------|
71
+ | Locked | Anything where executor divergence would break the plan |
72
+ | Open | Decisions where multiple correct answers exist; executor picks |
73
+ | Considered/rejected | Significant alternatives explored — only meaningful ones (not "I considered any random thing") |
74
+
75
+ ## Schema — `## Implementation Decisions` (executor → verifier handoff)
76
+
77
+ Lives in `summary.md`, after `## Files Changed`:
78
+
79
+ ```markdown
80
+ ## Implementation Decisions
81
+
82
+ ### Taken (within plan's discretion)
83
+ - DT-1: Chose <option> for O-N. Reason: <rationale>.
84
+
85
+ ### Deviations (from plan; must explain)
86
+ - DV-1: Plan said <X>; I did <Y>. Reason: <rationale>. Verification: <how I confirmed Y is acceptable>.
87
+
88
+ ### Open questions for verifier
89
+ - Q-1: <question>. Why it matters: <stake>.
90
+ ```
91
+
92
+ If implementation followed plan exactly with no notable items:
93
+
94
+ ```markdown
95
+ ## Implementation Decisions
96
+
97
+ No deviations or open questions — implementation followed plan exactly.
98
+ ```
99
+
100
+ ### Bucket semantics
101
+
102
+ - **Taken** — Which option the executor picked for each `Open` (O-N)
103
+ decision the plan declared. Reference the original `O-N` ID so the
104
+ verifier can cross-check.
105
+
106
+ - **Deviations** — Where the executor departed from a `Locked` (D-N)
107
+ decision. Must include the reason AND a verification step (how the
108
+ executor confirmed the deviation is acceptable). Without the
109
+ verification step, this is just an unauthorized change — the verifier
110
+ should treat such a deviation as a finding.
111
+
112
+ - **Open questions for verifier** — Decisions the executor consciously
113
+ punted to the verifier. NOT a substitute for the existing verification
114
+ dimensions; an EXTRA focus area. The verifier uses these to know
115
+ where to spend extra attention.
116
+
117
+ ## Reading order for downstream agents
118
+
119
+ - **Executor**, before writing any code:
120
+ 1. Read `## Plan Decisions` first
121
+ 2. Internalize the Locked bucket as constraints
122
+ 3. Note Open decisions to revisit when those task lines come up
123
+ 4. Skim Considered/rejected to avoid re-deriving rejected alternatives
124
+
125
+ - **Verifier**, before checking the code:
126
+ 1. Read `## Implementation Decisions` from each plan's summary
127
+ 2. For each Deviation, verify the executor's stated verification
128
+ 3. For each Open Question, spend extra time on that area
129
+ 4. Cross-reference Decisions Taken against the plan's Open bucket
130
+ (every plan-declared `O-N` should have a corresponding `DT-N` or
131
+ have been mooted)
132
+
133
+ ## Empty-bucket discipline
134
+
135
+ The schema MUST be machine-parseable. Forbidden:
136
+
137
+ - Section header present, all buckets silently empty (no "no decisions" line)
138
+ - Bucket header present with no items and no parenthetical "(none)"
139
+ - Out-of-order buckets
140
+
141
+ `pan-plan-checker` Dimension 12 (P-RES-003) enforces this on the planner side.
142
+
143
+ ## Versioning
144
+
145
+ Schema version: v1 (introduced v3.7.10).
146
+
147
+ If this schema ever changes, add a `decisions_schema: v2` field to the
148
+ plan.md frontmatter and document the new shape here. Older plans without
149
+ that field default to v1.
150
+
151
+ ## Source
152
+
153
+ - Cognition, "Don't Build Multi-Agents" (Jun 2025): https://cognition.ai/blog/dont-build-multi-agents
154
+ - Anthropic, "How we built our multi-agent research system": https://www.anthropic.com/engineering/multi-agent-research-system
155
+ - Internal: `pan-wizard-core/learnings/internal/external-research.md` P-RES-003
156
+ - Spec: this reference doc IS the spec; no separate doc.