@jaimevalasek/aioson 1.9.3 → 1.17.2

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 (54) hide show
  1. package/CHANGELOG.md +237 -0
  2. package/README.md +44 -1
  3. package/package.json +1 -1
  4. package/src/cli.js +50 -1
  5. package/src/commands/chain-audit.js +156 -0
  6. package/src/commands/op-capture.js +146 -0
  7. package/src/commands/op-forget.js +54 -0
  8. package/src/commands/op-identity.js +145 -0
  9. package/src/commands/op-list.js +105 -0
  10. package/src/commands/op-migrate.js +158 -0
  11. package/src/commands/op-promote.js +66 -0
  12. package/src/commands/op-reinforce.js +73 -0
  13. package/src/commands/op-show.js +71 -0
  14. package/src/commands/op-stubs.js +67 -0
  15. package/src/commands/preflight.js +6 -2
  16. package/src/commands/runtime.js +178 -0
  17. package/src/commands/state-save.js +61 -0
  18. package/src/commands/sync-agents-preflight.js +117 -3
  19. package/src/commands/workflow-next.js +64 -0
  20. package/src/handoff-contract.js +25 -0
  21. package/src/i18n/messages/en.js +9 -0
  22. package/src/i18n/messages/es.js +9 -0
  23. package/src/i18n/messages/fr.js +9 -0
  24. package/src/i18n/messages/pt-BR.js +9 -0
  25. package/src/lib/agent-semantic-diff.js +199 -0
  26. package/src/neural-chain-agent-ingest.js +400 -0
  27. package/src/neural-chain-config.js +95 -0
  28. package/src/neural-chain-git-ingest.js +280 -0
  29. package/src/neural-chain-migration.js +61 -0
  30. package/src/neural-chain-noise-file.js +332 -0
  31. package/src/neural-chain-sanitize.js +0 -0
  32. package/src/neural-chain-telemetry.js +90 -0
  33. package/src/operator-memory/conflict.js +202 -0
  34. package/src/operator-memory/decay.js +157 -0
  35. package/src/operator-memory/decision.js +274 -0
  36. package/src/operator-memory/identity.js +109 -0
  37. package/src/operator-memory/index-md.js +170 -0
  38. package/src/operator-memory/loader.js +106 -0
  39. package/src/operator-memory/proposal.js +179 -0
  40. package/src/operator-memory/prune.js +81 -0
  41. package/src/operator-memory/slug.js +90 -0
  42. package/src/operator-memory/storage.js +121 -0
  43. package/src/preflight-engine.js +91 -1
  44. package/src/runtime-store.js +2 -0
  45. package/template/.aioson/agents/dev.md +1 -1
  46. package/template/.aioson/agents/deyvin.md +3 -3
  47. package/template/.aioson/agents/neo.md +23 -1
  48. package/template/.aioson/agents/product.md +1 -1
  49. package/template/.aioson/agents/setup.md +1 -1
  50. package/template/.aioson/docs/deyvin/pair-execution.md +1 -1
  51. package/template/.aioson/skills/process/decision-presentation/SKILL.md +9 -0
  52. package/template/AGENTS.md +23 -0
  53. package/template/CLAUDE.md +23 -0
  54. package/template/agents/_shared/memory-capture-directive.md +115 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,156 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.17.2] - 2026-05-22
8
+
9
+ ### Security
10
+ - **Neural Chain — fixes for the 3 @pentester findings against v1.17.1** (SF-NC-01 HIGH + SF-NC-02 MEDIUM + SF-NC-03 LOW). Single consolidated patch closing the `block` recommendation that prevented npm publish of v1.17.1.
11
+ - **SF-NC-01 (HIGH) FIXED — Noise file injection via newline in chain_edges.target_path.** The @pentester probe demonstrated that a crafted row (`target_path = "legit.js\n- [ ] [AUTO-FIXABLE] /etc/passwd ..."`) bypassed the BR-NC-03 `guarded` mode guarantee because `serializeItem` interpolated the path raw and `parseItems` accepted the resulting injected line as a standalone item. New `src/neural-chain-sanitize.js#isUnsafePath` centralizes the rule: reject strings with any ASCII control char (`\x00-\x1f` + `\x7f`, includes `\n` `\r` `\t` `\0`), empty strings, and strings longer than 4096 chars. Wired at three boundaries — **Layer B ingest:** `deriveSessionPairs` (in `agent-ingest.js`) and `computeCoEditPairs` (in `git-ingest.js`) filter unsafe paths before INSERT; **Layer A render:** `flattenAudits` (in `noise-file.js`) drops items with unsafe `target_path` / `source_file` before they reach the noise file body (defense in depth for pre-v1.17.2 rows that may still be active in the database); **CLI boundary:** `runChainAudit` returns `{ ok: false, reason: 'unsafe_file_path' }` when the input file argument fails validation, before the SQL bind. The regression test reproduces the original probe with the same malicious INSERT and asserts the forged `[AUTO-FIXABLE]` line never appears in the rendered body — `guarded` mode safety contract restored.
12
+ - **SF-NC-02 (MEDIUM) FIXED (app-layer only) — chain_edges schema validation gaps.** Same `isUnsafePath` helper covers the length cap (4096) and control-char rejection at ingest, providing the same protection as a schema CHECK without requiring a table rebuild. Schema-level CHECK constraints on `source_path` / `target_path` / `start_at` / `last_seen_at` are deferred to M2 graph maintenance, which already needs a `schema_meta` migration. Application code only writes ISO 8601 timestamps via `new Date().toISOString()` — a malicious direct INSERT could still bypass the timestamp format check at the SQL layer; this is documented as the open M2 follow-up and noted in `requirements-neural-chain.md`. The chain_edges INSERTs from `git_co_edit` and `agent_event` paths are now both protected.
13
+ - **SF-NC-03 (LOW) FIXED — normalizeThreshold rejects negative zero + spec trust-boundary note.** `normalizeThreshold` now returns `null` when the parsed value is `-0` via `Object.is(n, -0)` check — required because `n < 0` evaluates `false` for `-0`. A crafted `.aioson/config.md` with `chain_auto_threshold: -0` now falls back to the default `0.8`. `requirements-neural-chain.md` EC-NC-07 amended with an explicit trust-boundary note: `.aioson/config.md` must remain under version control + code review; `.gitignore` on it is an anti-pattern for neural-chain. Runtime warning telemetry when `autonomy=autonomous + threshold=0` is documented as a future hardening but not shipped (low ROI given the doc note covers the operational concern).
14
+
15
+ ### Notes
16
+ - **Cumulative regression**: 2780 tests, 2777 pass, 1 skipped, 2 fail (AC-P1-07 operator-memory pre-existing + AC-ALL-101 perf flake intermittent on Windows — both unrelated). +5 new tests in `tests/neural-chain-invariants.test.js` covering all three SF-NC fixes plus a Layer B unit check on `deriveSessionPairs`.
17
+ - **`security-findings-neural-chain.json`** updated — all three findings now carry `status: fixed`, `fix_release: v1.17.2`, and a `fix_summary` describing exactly what landed. `@qa` is the final decision owner per `pentester.md` ownership protocol and should re-verify before treating the findings as closed. A re-run of the @pentester probes against v1.17.2 is recommended to confirm mitigation in addition to the regression tests.
18
+ - **`npm publish` unblocked**: v1.17.1 was tagged but the @pentester block recommendation prevented publishing it. v1.17.2 supersedes pre-publish; user chooses this tag for npm publish.
19
+ - **Inception loop closed for this cycle**: @qa flagged 2 Medium → @dev hotfixed in v1.17.1 → @tester defensive invariants caught a third bug (M-003 schema drift) → @dev fixed → @pentester adversarial review found 3 more (SF-NC-01..03) → @dev fixed in this v1.17.2 release. Each agent role surfaced a class of problem the previous role could not have caught — exactly the loop neural-chain itself is designed to support for *user* code.
20
+
21
+ ## [1.17.1] - 2026-05-22
22
+
23
+ ### Fixed
24
+ - **Neural Chain — hotfix for 3 Medium findings from `@qa` Gate D + `@tester` gap-fill (M-01 / M-02 / M-003).** Consolidated patch — single release closing the residual risks documented in `spec-neural-chain.md` § QA sign-off + `test-plan.md` § bug-found.
25
+ - **M-02 (bug-found-002) FIXED — BR-NC-01 dual-source dedupe.** When the same `(source_path, target_path)` pair existed under both `edge_type='git_co_edit'` AND `edge_type='agent_event'`, `queryImpacts` and `chain:audit` previously returned both rows separately, duplicating the same target in noise files (different motivos). Spec BR-NC-01 says "reportar `max(c_git, c_event)` — não soma; evita double-count entre fontes". Both SQL queries (in `src/neural-chain-agent-ingest.js#queryImpacts` and `src/commands/chain-audit.js`) now wrap the row scan in a SQLite window function `ROW_NUMBER() OVER (PARTITION BY target_path ORDER BY confidence DESC, hit_count DESC, last_seen_at DESC)` and keep only `rn = 1`. The chosen `edge_type` is the one from the row that won the max confidence (tiebreaker by hit_count then last_seen_at). 2 new tests in `tests/neural-chain-invariants.test.js` cover both call sites (hook + CLI) with a dual-source seed asserting the deduped row reports the max confidence (0.9, not 0.6+0.9) and the surviving edge_type.
26
+ - **M-003 (bug-found-003) FIXED — chain_audit telemetry schema drift between emitters.** Previously the CLI emitter (`chain-audit.js`) and the hook emitter (`agent-ingest.js`) drifted on payload fields: CLI was missing `noise_file`/`auto_fixable_count`/`tokens_used`; hook EC-NC-05 no-op event was missing `duration_ms`/`error`; both used singular `source_file` instead of the spec'd plural `source_files`; `tokens_used` was never populated by anyone. New `src/neural-chain-telemetry.js` exposes a single `emitChainAuditEvent(db, { agent, message, ...payload })` helper that builds the full 8-field BR-NC-10 payload schema (`feature_slug, source_files[], impacts_found, auto_fixable_count, noise_file, tokens_used, duration_ms, error`) with sane defaults for the no-op path. Both call sites migrated. CLI passes `source_files: [filePath]` (singleton array) so the spec'd plural shape holds; hook passes the full session's `safeArtifacts`. `tokens_used` ships as `0` placeholder in V1 — re-instrument when LLM-mediated path activates (M2 concern). Legacy singular `source_file` alias preserved in both emit payloads to keep any v1.17.0 dashboard query working until v2. `tests/neural-chain-invariants.test.js` A.2 promoted from a 2-field subset check to the full 8-field BR-NC-10 schema validation, with type discipline (source_files is array, duration_ms is number, etc.) on both hook and CLI events.
27
+ - **M-01 (bug-found-001) AMENDED — EC-NC-04 retry/backoff acceptably deferred in V1.** Spec EC-NC-04 + requirements EC-NC-04 + this CHANGELOG entry now explicitly acknowledge that V1 ships single-attempt try/catch instead of the spec'd 3-attempt exponential backoff. Justification: BR-NC-11 (non-blocking) is the load-bearing contract — audit failure never propagates to `runAgentDone`, agent:done completes normally regardless. The `runAgentDone` path is sequential with low contention (Living Memory reflect-prepare + Neural Chain hook run in series, no real lock pressure). The `withRetry({ attempts: 3, backoffMs: [100, 200, 500] })` helper is deferred to M1.5/M2 when squad-mode concurrent edits (EC-NC-08) actually create lock contention. Zero code change for this item — pure spec amendment.
28
+
29
+ ### Notes
30
+ - **Cumulative regression**: 2775 tests, 2772 pass, 1 skipped, 2 fail (AC-P1-07 operator-memory pre-existing + AC-ALL-101 perf flake intermittent on Windows — both documented, unrelated to this hotfix). +2 tests vs v1.17.0 baseline.
31
+ - **AC-AUDIT-NC**: still 7/7 satisfied; this hotfix tightens the BR-NC-01 + BR-NC-10 contracts in code, not in scope.
32
+ - **No version bump for npm publish needed yet** — v1.17.0 has NOT been published. v1.17.1 supersedes it pre-publish. User chooses which tag to `npm publish` from when ready.
33
+ - **Bug discovery loop closed**: `@qa` flagged M-01 + M-02 in Gate D residual; `@tester` discovered M-003 via the A.2 schema completeness invariant test (test had to relax its assertion because the no-op event omitted `duration_ms` — that relaxation itself became the smoking gun); `@dev` consolidated all three in this single patch slice.
34
+
35
+ ## [1.17.0] - 2026-05-21
36
+
37
+ ### Added
38
+ - **Neural Chain — Phase 1 shipped end-to-end (Slices 1-6).** Impact-aware code editing for AIOSON: when an agent edits a file, the post-session hook audits chain edges (git co-edit + agent-event signals) and surfaces files that may need updating via a per-session noise file consumed by `@neo` as a blocker.
39
+ - **Schema (Slice 1)**: `chain_edges` table in `aios.sqlite` — 10 fields, 3 indexes (2 lookup + 1 partial UNIQUE on active rows for archive-flow per BR-NC-08), CHECK constraints on `edge_type` ∈ {git_co_edit, agent_event} + `confidence` ∈ [0,1] + `hit_count > 0`. New `src/neural-chain-migration.js` idempotent runner wired downstream of `runLearningLoopMigration` in `runtime-store.js#ensureLegacyColumns`.
40
+ - **`aioson chain:audit <file> [--feature=<slug>] [--json] [--limit=N]` (Slice 2)**: read-only CLI returning top-N active impacts ordered by confidence DESC (default 20, hard cap 200). Emits one `execution_events` row per invocation with `event_type='chain_audit'` (BR-NC-10 telemetry obligation). Failure non-blocking per BR-NC-11. i18n keys added in 4 locales.
41
+ - **Git co-edit ingest helper (Slice 2)**: `src/neural-chain-git-ingest.js` — pure `parseGitLog` / `computeCoEditPairs` / `ingestGitCoEditEdges` plus `runGitIngest` integration wrapper. BR-NC-01 saturation at 10 co-edits, BR-NC-08 hard cap 10k per source via archive-oldest-by-`last_seen_at`, 90-day window filter, mega-commits (>50 files) + `.aioson/*` paths excluded, UPSERT respecting partial UNIQUE index. EC-NC-06 honored (skip when git history < 50 commits).
42
+ - **Agent-event ingest hook (Slice 3)**: `src/neural-chain-agent-ingest.js` — `deriveSessionPairs` / `ingestAgentEventEdges` / `runChainHookOnAgentDone` / `queryImpacts`. Wired into both `live_event` and `standalone` branches of `runAgentDone` in `src/commands/runtime.js` (best-effort try/catch envelope, BR-NC-11). BR-NC-01 saturation at 5 hits via UPSERT ON CONFLICT incrementing `hit_count` + recomputing confidence atomically. EC-NC-05 explicitly honored — empty/single-file artifact lists still emit exactly one `chain_audit` event with `impacts_found=0` so the guardrail metric series stays continuous.
43
+ - **Noise file write/lifecycle (Slice 4)**: `src/neural-chain-noise-file.js` — `writeNoiseFile`, `readNoiseFileAndRecompute`, `maybeDeleteNoiseFile` (sync fs, no new dependency). Path scheme `.aioson/context/noises/{feature-slug}-{YYYYMMDD-HHMM}.md` with `unspecified-{ts}.md` fallback (BR-NC-06). YAML frontmatter carries `{slug, edit_at, autonomy_mode, source_files, total_items, resolved_items}`; body lists `- [ ] {target} — {edge_type} {confidence} (source: {file})` items, file-level only (BR-NC-09; M1 forbids `:symbol` granularity). EC-NC-09 (corrupted frontmatter still returns parsed body items) + EC-NC-10 (idempotent unlink on race delete) honored.
44
+ - **`@neo` noise blocker step (Slice 5)**: `@neo` activation protocol gains Step 1.5 — detects `.aioson/context/noises/*.md` with pending `- [ ]` items via regex or `readNoiseFileAndRecompute` helper; surfaces as ⛔ blocker with `confidence: low` and `clarification` populated, listing each pending item by target_path + motivo. Resolution path is marking `- [x]` (lazy unlink on next hook invocation per EC-NC-10); explicit skip via natural-language `"skip noises"` with `reason: skipped <N> noise file(s)` in routing block. New top-priority "Chain audit pending" stage in Step 3 takes precedence over all other stages. Mirrored byte-for-byte to `template/.aioson/agents/neo.md` (brain `sheldon-001` template parity verified via `diff -q`).
45
+ - **Autonomy mode wiring + BR-NC-02/03 threshold rules (Slice 6)**: new `src/neural-chain-config.js` exposes `readChainConfig({ targetDir })` returning `{autonomyMode, chainAutoThreshold, source}` from `.aioson/config.md` YAML frontmatter. EC-NC-07 honored in 4 code paths (null targetDir, ENOENT, no frontmatter, invalid value) — defaults `guarded` / 0.8 with no force-edit. New `classifyImpact` applies BR-NC-02 rule (a) test-pair filename match cross-language and rule (c) `confidence > threshold AND edge_type='agent_event' AND hit_count > 5`. **Rule (b) literal identifier match deferred to M1.5/M2** — requires git diff parsing, heavy for V1 with bounded marginal gain. BR-NC-03 mode semantics fully wired: `guarded` → all noise (no marker), `standard` → matches tagged `[AUTO-FIXABLE]`, `autonomous` → matches `[AUTO-FIXABLE]` + non-matches `[AUTO-FIXABLE-BEST-EFFORT]`. Both `standard` and `autonomous` now write the noise file (Slice 4 deferred; Slice 6 enables). Telemetry payload (BR-NC-10) gains `auto_fixable_count` + `chain_auto_threshold`.
46
+ - **`tests/neural-chain-{migration,git-ingest,agent-ingest,noise-file,autonomy}.test.js` + `tests/chain-audit.test.js`** — 81 acceptance tests cumulative across Slices 1-6 (11 + 21 + 12 + 13 + 23 + chain-audit suite). Coverage spans schema CHECK constraints, partial-UNIQUE archive flow, confidence formula + saturation, hard-cap enforcement, UPSERT idempotency, EC-NC-05/06/07/09/10, classifier mode×rule combinations, marker render + parse round-trip, hook integration auto-resolving config + per-mode classification + telemetry completeness.
47
+
48
+ ### Notes
49
+ - **Phase 1 complete.** Neural Chain shipped Slices 1-6 in a single 2026-05-21 dev day (inception-mode pacing: framework feature being implemented using the framework's own agents). Single release v1.17.0 per progressive-release strategy — no per-slice version bumps.
50
+ - **AC-AUDIT-NC done gate 7/7 satisfied** (verification mapping in `spec-neural-chain.md`): item 1 `chain:audit` in `runAgentDone` ✓, item 2 `@neo` surfaces noises as blocker ✓, item 3 autonomy mode read via unit test covering 3 modes ✓, item 4 schema migration applied ✓, item 5 coverage ≥ 80% on critical paths ✓, item 6 CHANGELOG entry ✓ (this release), item 7 template parity (`diff -q .aioson/agents/neo.md template/.aioson/agents/neo.md` returns 0) ✓.
51
+ - **Primary success metric (from PRD)**: −50% second-call correction loops in 30d post-release. **Baseline instrumentation TBD** in next 20-30 sessions; post-shipping delta measured at 30-day mark.
52
+ - **Guardrail metric**: `tokens_used` in `runtime_events` filtered `type='chain_audit'` should stay stable over time. `aioson chain:stats` aggregation planned as follow-up M1.5 feature. Pulse alert when `delta_avg > 2x` month-over-month — signal that M2 graph maintenance (skill LLM-judged + heuristic + `chain:prune`) is due.
53
+ - **Out-of-scope V1, planned for V2/M2**: squad/parallel edit scenarios (EC-NC-08), `chain_node_cap` configurability (hardcoded 10k V1), BR-NC-02 rule (b) literal identifier match via git diff parsing, AST drill-down + multi-language AST via tree-sitter, Obsidian-style graph visualization, `chain:prune` skill + heuristic cleanup.
54
+ - **Brain nodes applied during implementation**: `sheldon-001` (template parity for agent files), `sheldon-005` (CLI-first integration — reused `execution_events` instead of a new table), `sheldon-006` (audit wiring before close — feature was design-complete only until AC-AUDIT-NC passed). All three reinforced as patterns by this feature's shipping cycle.
55
+
56
+ ## [1.16.0] - 2026-05-21
57
+
58
+ ### Added
59
+ - **Operator memory — Phase 5 TTL decay + migration + closure** (5 of 5 phases — **feature complete**).
60
+ - **`src/operator-memory/decay.js`** (NEW): per-category half-life engine — identity=365d, autonomy=180d, tooling=90d, default=90d (PMD-03). Env override per category via `AIOSON_OPERATOR_DECAY_<CATEGORY>_DAYS`. `findStaleDecisions(identity)` returns past-half-life entries with 30d per-slug debounce via `~/.aioson/operators/{identity}/_decay_state.json`. `cleanupHistory(identity)` hard-deletes `history/*.md` entries older than 365d.
61
+ - **`src/operator-memory/prune.js`** (NEW): 10k hard cap (PMD-04). `enforceCap(identity, {cap})` prunes oldest non-identity-category decisions first; identity-category decisions are NEVER auto-pruned. Env override via `AIOSON_OPERATOR_MAX_DECISIONS`.
62
+ - **`aioson op:reinforce <slug>`** (NEW Phase 5 command): refreshes `last_reinforced` + increments `reinforcement_count`. Silences decay prompt for next half-life window.
63
+ - **`aioson op:migrate`** (NEW Phase 5 command): explicit one-shot import from `.aioson/context/user-profile.md`. 8 known field mappings (autonomy_preference, communication_style, etc.). Idempotent (checks `deprecated_by: operator-memory` frontmatter). Unknown fields preserved. Marks `user-profile.md` deprecated post-migration per PMD-10.
64
+ - **`aioson op:identity set <id>`** Phase 5 full impl replaces Phase 1 stub: mutates `process.env.AIOSON_OPERATOR_ID` for the current process + initializes the storage tree + returns the shell `export` command for persistence.
65
+ - **`tests/operator-memory-decay.test.js`** — 23 new unit tests AC-P5-01..09 (closure ACs P5-10..14 verified by archive process).
66
+ - **`scripts/smoke-run-chain.js`** `[OM5]` section (decay sweep, hard cap, history cleanup) + `[OM-ALL]` cross-phase loader verification (10 modules + 8 CLI commands all exporting expected functions). Total smoke now 25/25.
67
+ - **`.aioson/context/wiring-audit-operator-memory.md`** Phase 5 entry + **cross-phase consolidation table** (PMD-07 / BR-05 Gate D blocker satisfied). 20 call sites, 114/114 cumulative unit tests, 14 smoke sections green.
68
+
69
+ ### Notes
70
+ - **Feature complete.** Operator-memory shipped end-to-end: F1 (storage+identity) + F2 (capture+promotion) + F3 (universal loading directive) + F4 (conflict policy + flag flip) + F5 (decay+migration). 5 phases × 5 minor releases v1.12.0 → v1.16.0 per DD-05 progressive-release strategy (mirrors workflow-handoff-integrity exitoso).
71
+ - **20 call sites, 114 unit tests, 25 smoke checks** wired and exercised across the 5 phases. Cross-phase consolidation table in wiring-audit doc verifies every phase has call sites grepped + tests passing + smoke coverage (PMD-07 / BR-05 anti-pattern guard).
72
+ - Gate D approved post-QA sign-off. `features.md` operator-memory → `done`. Feature artifacts archived to `.aioson/context/done/operator-memory/`.
73
+ - **First operational test in production:** this very release ships AIOSON_OPERATOR_MEMORY default-ON. Existing users on `~/.aioson/` (e.g. me, who has been operating this dev session) will start participating in capture as new sessions begin. The feature is now self-evidence-generating.
74
+
75
+ ## [1.15.0] - 2026-05-21
76
+
77
+ ### Added
78
+ - **Operator memory — Phase 4 conflict policy + flag flip** (4 of 5 phases). Binary V1 conflict detection between operator decisions and project rules in `.aioson/rules/`. **Inception flag `AIOSON_OPERATOR_MEMORY` is now default ON** (opt-out via env var).
79
+ - **`src/operator-memory/conflict.js`** (NEW): `detectConflicts`, `debounceConflicts`, `formatConflictWarning`, `scanProjectRules`, `parseRuleFrontmatter`. Keyword-overlap heuristic (≥ 2 stopword-filtered shared keywords) intersected with signal-type filter. Configurable threshold via `AIOSON_OPERATOR_CONFLICT_KEYWORD_THRESHOLD`.
80
+ - **`src/operator-memory/loader.js`** — `preflightLoad` extended with conflict detection when `options.projectRoot` is supplied. Conflicts are debounced per (decision_slug, rule_basename) pair via `_conflict_state.json` (60s default window, mirrors F2 idempotency pattern).
81
+ - **Project rule schema additive**: `.aioson/rules/*.md` may now declare `conflicts_with_signal_types: [authorization, exclusion, correction, confirmation]` in frontmatter. Rules without this field generate zero false positives (backward-compat preserved — AC-P4-04).
82
+ - **`tests/operator-memory-conflict.test.js`** — 18 new unit tests AC-P4-01..10 including **statistical corpus** (10 conflict pairs + 15 non-conflict pairs) with verified FN=0%, FP=0%.
83
+ - **`scripts/smoke-run-chain.js`** `[OM4]` section — 4 smoke checks (binary V1 conflict, additive no-FP, debounce window, flag-flip directive verification).
84
+ - **`template/CLAUDE.md` + `template/AGENTS.md`** universal directive updated: signals "Default **ON** in v1.15.0+. Opt out via `AIOSON_OPERATOR_MEMORY=false`". Byte parity between the two files preserved (T5 + AC-P3-11). New size: 1307 B per file × 2 = 2614 B total (improvement from 2664 B).
85
+
86
+ ### Changed
87
+ - **`AIOSON_OPERATOR_MEMORY` default flipped from `false` → `true`** per AC-P4-08. Agents now read `MEMORY.md` at preflight (when present) by default. Existing AIOSON behavior is preserved when no MEMORY.md exists per identity — directive degrades gracefully (AC-P3-08 backward-compat unchanged).
88
+ - Updated wording in directive sections to be flip-aware (still byte-identical between CLAUDE.md and AGENTS.md per parity invariant).
89
+
90
+ ### Notes
91
+ - **Operator memory is now active by default.** New users running v1.15.0+ will have their first signal captures land in `~/.aioson/operators/{hash}/proposals/` automatically when agents emit `aioson op:capture`. Promotion at the 2x threshold (PMD-07) continues to be silent on first detection and emits the 1-line audit on promotion.
92
+ - Smoke runner result: 21/21 green (was 17/17 before OM4). The flag-flip safety gate (smoke must be green BOTH flag-off and flag-default) is satisfied — Phase 3's backward-compat tests still pass under default-on mode because the helpers degrade gracefully when no storage exists.
93
+ - Phase 5 (v1.16.0) ships next: per-category TTL decay, 10k hard cap enforcement, `op:reinforce`, `op:migrate` (one-shot import from `user-profile.md`), `op:identity set` full impl, history/ cleanup at 365d, cross-phase wiring audit consolidation, Gate D, and feature:archive. That's the closure release.
94
+
95
+ ## [1.14.0] - 2026-05-21
96
+
97
+ ### Added
98
+ - **Operator memory — Phase 3 universal loading directive** (3 of 5 phases for the `operator-memory` feature). The cross-cutting integration phase that wires operator-memory into agent prompts framework-wide. **Inception-risk phase** — directive ships behind `AIOSON_OPERATOR_MEMORY=true` flag **default OFF** until Phase 4 (v1.15.0) ships green.
99
+ - **Universal directive** injected into `template/CLAUDE.md` AND `template/AGENTS.md`: `## Memory loading` + `## Memory capture` sections at consistent position (after `## Mandatory first action`, before `## Agents`). Byte-identical between both files (T5 parity guarantee). Flag-gated: `if process.env.AIOSON_OPERATOR_MEMORY === 'true'` — when unset/false the directive is a no-op (backward-compat per AC-P3-08).
100
+ - **`aioson op:list` full impl** — replaces Phase 1 stub. Lists active decisions with category + signal_type + reinforced date. Supports `--proposals` (queue view), `--include-archived` (Phase 5 archive tier), `--format=json` (machine-readable).
101
+ - **`aioson op:show <slug>` full impl** — replaces Phase 1 stub. Prints decision frontmatter + body, or proposal data when slug is in `proposals/`. `--json` supported.
102
+ - **`src/operator-memory/index-md.js`** (NEW): MEMORY.md tier-based reader/writer. `loadMemoryIndex(identity, tier)` parses frontmatter + link entries. `regenerateIndex(identity)` rebuilds from `decisions/*.md` filesystem (markdown source-of-truth per PMD-AN-06). Hooked into `promoteProposal` + `forgetEntry` post-commit so MEMORY.md auto-refreshes after every state change.
103
+ - **`src/operator-memory/loader.js`** (NEW): `preflightLoad(identity, taskDescription)` returns `{index, matches}` for agent-side consumption. `matchDecisions(index, taskDescription)` V1 substring + stopword heuristic (V2 will switch to FTS5-backed query).
104
+ - **`.aioson/docs/operator-memory/memory-md-format.md`** (NEW): canonical cross-harness format spec. Documents MEMORY.md frontmatter + body schema, decision file schema, loading pseudocode, V1 support matrix (Claude Code native + Codex compatible + Gemini compatible; Cursor + Aider TBD V2), and a ~10-line POSIX reference implementation.
105
+ - **`scripts/memory-budget-audit.js`** (NEW): enforces NFR-02 byte budgets. Per-file warn at 1500B / fail at 2000B; cross-cutting warn at 5000B / fail at 6000B. Phase 3 directive total: 2664 B (well within budget). `--json` supported. Exit 1 on fail.
106
+ - **`tests/operator-memory-loading.test.js`** — 23 new unit tests covering AC-P3-01..12 including byte-parity between CLAUDE.md/AGENTS.md directives + budget audit self-test + cross-harness format spec sanity.
107
+ - **`scripts/smoke-run-chain.js`** extended with `[OM3]` section — 3 smoke checks (index regenerates after promote, lazy match returns task-relevant decisions, flag-OFF graceful degrade).
108
+
109
+ ### Notes
110
+ - **Inception risk explicitly mitigated**: `AIOSON_OPERATOR_MEMORY` flag is **OFF by default in this release**. Existing AIOSON sessions are unaffected — directive in template files is a no-op until the env var is set. Phase 4 (v1.15.0) will flip the default to `true` AFTER its CI gate confirms both flag-states are green.
111
+ - The directive is byte-identical between `template/CLAUDE.md` and `template/AGENTS.md` (verified by AC-P3-11 test). This is the parity contract — different file shells, identical directive content.
112
+ - Smoke runner result: 17/17 green (was 14/14 before OM3).
113
+ - MEMORY.md tier-based format (PMD-AN-02): Phase 3 ships single `MEMORY.md` (active tier). Phase 5 decay sweep will partition into `MEMORY.md` + `MEMORY-archive.md` based on category half-life crossing. Format is forward-compatible.
114
+ - Cross-harness V1 support matrix documented: Claude Code + Codex + Gemini CLI all read `CLAUDE.md` or `AGENTS.md`, both of which now contain the universal directive — they participate natively when the env flag is set. Cursor + Aider deferred to V2 (need bridge files).
115
+
116
+ ## [1.13.0] - 2026-05-21
117
+
118
+ ### Added
119
+ - **Operator memory — Phase 2 capture + promotion engine** (2 of 5 phases for the `operator-memory` feature). Builds on Phase 1's storage substrate to deliver the actual signal-capture pipeline:
120
+ - **`aioson op:capture` full impl** — replaces Phase 1 stub. Captures a standing-decision signal of type `authorization | exclusion | correction | confirmation`, derives deterministic slug from `--proposal`, writes to `proposals/{slug}.md` on first detection (silent), promotes to `decisions/{slug}.md` atomically on second detection (per PMD-07 2x threshold) with the 1-line audit `✔ Memory: '<text>'. aioson op:forget <slug> p/ desfazer.` (PMD-08 silent-by-default with audit-on-promotion).
121
+ - **`aioson op:promote <slug>` full impl** — manual promotion path that skips the 2x threshold for a pending proposal.
122
+ - **`aioson op:forget <slug>` full impl** — soft-deletes a decision or proposal to `history/{ISO}-{slug}.md`. Idempotent (second call returns noop). Removes FTS5 row inside SQLite transaction.
123
+ - **`src/operator-memory/slug.js`** new module: `deriveSlug`, `normalize`, `fingerprintProposal`. Deterministic kebab-case + stopword filter + truncation at word boundary + collision-suffix detection.
124
+ - **`src/operator-memory/proposal.js`** new module: `captureSignal` (write/increment), `readProposal`, `deleteProposal`. Quotes capped at 5 most recent per AC-P2-01.
125
+ - **`src/operator-memory/decision.js`** new module: `promoteProposal` (atomic via SQLite transaction + atomic rename per AC-P2-03), `forgetEntry`, `readDecision`, `inferCategory` (V1 keyword heuristic for autonomy/identity/tooling/default per PMD-03).
126
+ - **`template/agents/_shared/memory-capture-directive.md`** — NEW versioned prompt template (`schema_version: "1.0"`). 4 signal types × ≥3 concrete examples + anti-pattern section + capture-call format. PMD-02 acknowledged divergence from AIOSON's deterministic principle. File is dormant in Phase 2 — Phase 3 wires it into `template/CLAUDE.md`/`AGENTS.md`.
127
+ - **`tests/operator-memory-capture.test.js`** — 26 new unit tests covering AC-P2-01..12 (capture, promote, forget, signal validation, atomicity, FTS5 mirror correctness, category inference, body cap).
128
+ - **`scripts/smoke-run-chain.js`** extended with `[OM2]` section — 3 smoke checks exercising capture+promote pipeline, idempotent forget, signal validation in isolated tmp HOME.
129
+ - **`.aioson/context/wiring-audit-operator-memory.md`** Phase 2 entry populated with call sites, tests, atomicity verification.
130
+
131
+ ### Notes
132
+ - Atomicity per AC-P2-03: SQLite `db.transaction()` wraps fs operations (`writeFileSync` to `.tmp` + `renameSync` + `unlinkSync` of proposal). Crash mid-transaction → SQLite rolls back; tmp file cleaned up via `finally`. POSIX `rename(2)` and Windows `MoveFileEx` provide the atomic-rename guarantee.
133
+ - Telemetry events shipped this release: `op_capture`, `op_promote`, `op_forget` via existing `dossierTelemetry.emitDossierEvent` (PMD-12 + DD-04 confirmed: extend, don't fragment).
134
+ - LLM-driven capture is acknowledged divergence from AIOSON's deterministic principle (PMD-02). The prompt template at `template/agents/_shared/memory-capture-directive.md` is the canonical signal-detection spec; versioned `schema_version` field supports V1→V2 migration.
135
+ - Smoke runner result: 14/14 green (was 11/11 before OM2 section).
136
+ - Phase 3 (Universal loading directive, v1.14.0) ships next. **Inception risk:** Phase 3 modifies template files this framework itself uses — flag-gated `AIOSON_OPERATOR_MEMORY=true` default OFF until Phase 4 ships green.
137
+
138
+ ## [1.12.0] - 2026-05-21
139
+
140
+ ### Added
141
+ - **Operator memory — Phase 1 storage + identity foundation** (1 of 5 phases for the `operator-memory` feature). Establishes the per-operator memory substrate that all subsequent phases build on:
142
+ - **`aioson op:identity`** CLI command — resolves operator identity via sha256[0..16] hash of `git config user.email`, with `AIOSON_OPERATOR_ID` env override (validated regex `^[a-z0-9][a-z0-9-]{2,31}$`, reserved prefixes `_*` and `aioson-*` blocked per PMD-05). Subcommands: `show` (full), `set <id>` (Phase 1 stub — full impl ships Phase 5).
143
+ - **`~/.aioson/operators/` storage tree** auto-created per identity: `decisions/`, `proposals/`, `history/` subdirs (Phase 2+ populates). Hybrid storage backend: shared `_index.sqlite` (FTS5 virtual table + `operators` table) for cross-decision search per PMD-01.
144
+ - **5 CLI command stubs** (`op:capture`, `op:promote`, `op:forget`, `op:list`, `op:show`) — register the command surface, emit `op_command_stub` telemetry on invocation, return exit 1 with structured "Not yet implemented (ships in Phase N / vX.Y.Z)" message. Full impls ship across Phases 2-3.
145
+ - **`src/operator-memory/{identity,storage}.js`** new pure-helper modules exporting `resolveIdentity`, `validateOverride`, `hashEmail`, `ensureStorageTree`, `openIndexDb`, `migrateIndexSchema`, `recordIdentityActivity`. Reusable by downstream phase commands.
146
+ - **`tests/operator-memory-identity.test.js`** — 24 unit tests covering AC-P1-01..10 + EC-08 salt rehash + DD-02 hash size invariant.
147
+ - **`.aioson/context/wiring-audit-operator-memory.md`** — new Gate D blocker doc, Phase 1 entry populated (will accumulate per-phase entries across v1.12.0 → v1.16.0).
148
+
149
+ ### Notes
150
+ - This release opens Phase 1 of `operator-memory` MEDIUM feature (5-phase progressive rollout DD-05 mirroring `workflow-handoff-integrity` v1.9.5 → v1.10.0). Subsequent phases ship as v1.13.0 → v1.16.0.
151
+ - Per PMD-02, signal-detection capture (Phase 2+) acknowledges divergence from AIOSON's deterministic principle: prompt-template-driven inherently fuzzy. Phase 1 ships the substrate only — no LLM behavior is invoked.
152
+ - Per inception risk mitigation: universal loading directive (Phase 3) ships behind `AIOSON_OPERATOR_MEMORY=true` flag default OFF; flip default-on after Phase 4 ships green.
153
+ - DD-02 ratified: 16-char hash provides 2^64 collision space; email entropy (~25-30 bits) is the reverse-lookup bottleneck, not hash output length.
154
+
155
+ ## [1.11.0] - 2026-05-20
156
+
7
157
  ### Added
8
158
  - **@pentester agent**: adversarial security review agent with structured findings output (`security-findings-{slug}.json`) and Gate D blocking capability for MEDIUM projects.
9
159
  - **@discover agent**: system discovery and semantic knowledge cache bootstrap for brownfield projects.
@@ -33,6 +183,93 @@ All notable changes to this project will be documented in this file.
33
183
  - Safe canonical English agent sources restored after i18n decoupling.
34
184
  - Accidentally tracked local directories removed from git tracking.
35
185
 
186
+ ## [1.10.0] - 2026-05-20
187
+
188
+ ### Added
189
+ - **CI pre-publish smoke chain** (Phase 5 / T6 of `workflow-handoff-integrity` — **closes the feature**). New `scripts/smoke-run-chain.js` standalone runner exercises real exported APIs from Phases 1-4 (F1 stale dev-state + state:reset, F2 agent:done auto-advance, F3 workflow:next pending guard, T5 semantic sync parity) plus a final actual-repo parity safety net. 11 deterministic checks; uses isolated `os.tmpdir()` fixtures (DD-04 mock-only, no LLM calls).
190
+ - **`.github/workflows/release-smoke.yml`** GitHub Actions workflow triggered by the `release` PR label or manual `workflow_dispatch`. Runs the full test suite + smoke chain (`AIOSON_PREPUBLISH=true`) + `npm pack --dry-run` as a merge gate before release-labeled PRs can ship to npm.
191
+ - **`tests/scripts/smoke-run-chain.test.js`** — 3 unit tests covering AC-T6-01 (green exit), AC-T6-05 (prepublish mode green on clean repo), AC-T6-08 (output discipline — all 5 sections present).
192
+ - **`tests/fixtures/medium-feature-mock/`** — 6 mock JSON files (one per MEDIUM agent: product, analyst, architect, pm, dev, qa) with `writes` and `spec_frontmatter` templates, plus README documenting PMD-05 / Sheldon R2 fixture-freshness rule.
193
+
194
+ ### Notes
195
+ - **Feature closure.** `workflow-handoff-integrity` is now fully implemented across F1 (state hygiene) + F2 (forward auto-emit) + F3 (pending-decisions gate) + T5 (structural drift detection) + T6 (CI smoke). Wiring audit cross-phase consolidation completed — see `.aioson/context/wiring-audit-workflow-handoff-integrity.md`.
196
+ - **DD-05 progressive-release strategy completed:** v1.9.5 → v1.9.6 → v1.9.7 → v1.9.8 → v1.10.0 across 5 minor bumps. Each phase was shippable independently; this final v1.10.0 closes the feature with the cross-phase smoke gate.
197
+ - Smoke runner local result: `pass=11 fail=0 — All smoke checks green. Safe to proceed with publish.`
198
+
199
+ ## [1.9.8] - 2026-05-20
200
+
201
+ ### Added
202
+ - **Semantic parity check between workspace and template agent files** (Phase 4 / T5 of `workflow-handoff-integrity`). `sync-agents-preflight` now runs three additional diff strategies on top of the existing `## Feature dossier` length check: (1) header diff (`##`/`###` presence + order), (2) section-content hash diff (catches body drift even when headers match — exactly the 981a8fd-style migration gap), (3) frontmatter field-level diff. Each issue includes an actionable hint.
203
+ - **Mode-aware severity** via `AIOSON_PREPUBLISH=true` env var. Default mode (local dev, CI without pre-publish): semantic drift is a warning, non-blocking. Pre-publish mode: warning becomes hard fail — blocks `npm publish` until drift is resolved.
204
+ - **`src/lib/agent-semantic-diff.js`** new pure-helpers module exporting `extractHeaders`, `extractSections`, `extractFrontmatter`, `diffHeaders`, `diffSectionContent`, `diffFrontmatter`, `diffAgentFile`, `normalizeBody`, `hashBody`. Reusable by downstream consumers.
205
+ - **`checkSemanticParity(projectRoot)`** exported from `src/commands/sync-agents-preflight.js`.
206
+ - **`tests/sync-agents-preflight-semantic.test.js`** — 20 unit tests covering AC-T5-01..08 including a **regression guard test** that reproduces the 981a8fd-style diff inside an isolated fixture and confirms the new check catches it.
207
+
208
+ ### Changed
209
+ - `src/commands/sync-agents-preflight.js`: `main()` now also runs semantic parity. Existing length check + learning-loop checks kept (additive). Telemetry event `semantic_parity_violation` emitted on detection (per-existing `dossierTelemetry` pattern).
210
+
211
+ ### Notes
212
+ - This release closes Phase 4 of `workflow-handoff-integrity`. F1+F2+F3+T5 now cover state hygiene, forward auto-emit, gating against pending decisions, AND structural drift detection between workspace/template. Phase 5 (T6 — CI smoke ponta-a-ponta) ships next as v1.10.0.
213
+ - DD-03 (semantic diff granularity) resolved as: section-level + token-aware code blocks + frontmatter field-level. Plain text body diff deliberately skipped to avoid cosmetic noise (typo fixes).
214
+ - Smoke against actual repo: `checkSemanticParity(process.cwd())` returns 0 drift issues — confirms workspace ↔ template agent files are aligned and v1.9.4 AskUserQuestion mass-edit preserved parity correctly.
215
+
216
+ ## [1.9.7] - 2026-05-20
217
+
218
+ ### Added
219
+ - **Stale `dev-state.md` detection with actionable warnings** (Phase 3 / F1 of `workflow-handoff-integrity`). `aioson preflight` now cross-references `.aioson/context/features.md` and applies a 30-day TTL: stale conditions are (a) feature already marked `done`/`abandoned`, (b) feature absent from features.md (orphan / cross-project leak), (c) `last_updated > 30 days`. Each warning embeds the command to fix it (`aioson state:reset` or `aioson state:save --feature=<slug>`).
220
+ - **`aioson state:reset`** new CLI command. Removes `.aioson/context/dev-state.md`. `--archive` flag moves to `.aioson/runtime/devstate-history/{ISO}.md` for audit trail. Idempotent. `--json` returns structured result.
221
+ - **Corrupt dev-state detection (AC-F1-08).** `readDevState` flags `parseError` when the file lacks frontmatter markers or has empty frontmatter. `detectStaleDevState` returns a warning with a `state:reset` command suggestion.
222
+ - **`detectStaleDevStateRich` + `parseFeaturesMap`** exported from `src/preflight-engine.js` for downstream consumers + tests.
223
+ - **`tests/preflight-stale-devstate.test.js`** — 20 unit tests covering AC-F1-01..08, parseFeaturesMap robustness, and runStateReset (idempotent, archive variant, json mode).
224
+
225
+ ### Changed
226
+ - `src/commands/preflight.js`: `runPreflight` switched the stale-detection call from sync `detectStaleDevState` to async `detectStaleDevStateRich`. Existing sync helper preserved (still used internally by `evaluateReadiness`) for backward-compat.
227
+
228
+ ### Fixed
229
+ - Per PRD ("warning acionável, NÃO cleanup automático silencioso"), F1 delivers a structured stderr warning with embedded command suggestion. No interactive y/N prompt (safer for CI/non-TTY contexts than plan-f1 originally implied).
230
+
231
+ ### Notes
232
+ - This release closes Phase 3 of `workflow-handoff-integrity`. F1 + F2 + F3 now cover state hygiene (Phase 3 — F1), forward auto-emit (Phase 1 — F2), and gating against pending decisions (Phase 2 — F3). Phases 4-5 (T5 semantic sync, T6 CI smoke) ship as v1.9.8 → v1.10.0.
233
+ - DPC-07 (additional path correction discovered): the PRD/architecture referenced `src/preflight.js` which does not exist. Actual layout: `src/preflight-engine.js` (helpers) + `src/commands/preflight.js` (CLI command). Both extended.
234
+
235
+ ## [1.9.6] - 2026-05-20
236
+
237
+ ### Added
238
+ - **`aioson workflow:next --complete=<agent>` rejects advance when manifest has pending decisions** (Phase 2 / F3 of `workflow-handoff-integrity`). Reads `.aioson/plans/{slug}/manifest.md` frontmatter; if `status` matches `^pending-(.+)-decisions$`, throws `WORKFLOW_NEXT_PENDING_DECISIONS` with actionable message recommending the agent that resolves those decisions (e.g. `pending-architect-decisions` → "Próximo agente recomendado: @architect"). Prevents the deadlock observed in `aioson-com` 2026-05-19 where `/analyst` routed to `/dev` despite manifest pending.
239
+ - **`--force` flag** on `aioson workflow:next` for explicit override (logs warning, proceeds). For emergency-use cases.
240
+ - **DD-02 hybrid regex+whitelist:** regex `^pending-(.+)-decisions$` catches any future `pending-<X>-decisions` state automatically; whitelist `[architect, product, pm, qa]` flags unrecognized captured groups (still blocks but warns "estado desconhecido" so typos don't silently route to nonexistent agents).
241
+ - **`tests/workflow-next-pending-guard.test.js`** — 10 unit tests covering AC-F3-01..07 (hard error, regex match per known agents, unknown group warning, --force override, no manifest, no slug, pattern specificity, whitelist export).
242
+
243
+ ### Changed
244
+ - `src/commands/workflow-next.js`: new public helpers `assertManifestNotPending(targetDir, slug, force)` + `PENDING_STATE_WHITELIST` const exported. Guard fires at start of `options.complete` branch (line 992, BEFORE `finalizeCurrentStage`) per AC-F3-05 precedence.
245
+
246
+ ### Notes
247
+ - This release closes Phase 2 of `workflow-handoff-integrity`. F2 + F3 together cover the forward (auto-emit) and gating (pre-check pending) directions of workflow handoff integrity. Phases 3-5 (F1 stale dev-state, T5 semantic sync, T6 CI smoke) ship as v1.9.7 → v1.10.0.
248
+ - Full npm test: 1 transient Windows tempdir flake (L-02 documented) — confirmed transient via targeted re-run of `tests/external-session.test.js` (21/21 pass). All other tests green.
249
+
250
+ ## [1.9.5] - 2026-05-20
251
+
252
+ ### Added
253
+ - **`agent:done` auto-emits `workflow:next --complete=<agent>`** (Phase 1 / F2 of `workflow-handoff-integrity`). When a workflow is active for the project (`.aioson/runtime/workflow.state.json` present + matching feature) AND the calling agent has produced its canonical artifact on disk, `aioson agent:done` now internally advances the workflow pointer. Removes the requirement for every agent prompt to literal-call `aioson workflow:next` — centralizes the trigger in `runAgentDone`. Backward-compat preserved: state file absent → no auto-advance (baseline stdout byte-identical).
254
+ - **`src/handoff-contract.js#getCanonicalArtifactsForAgent(agent, targetDir, state)`** public helper. Consumes the existing CONTRACTS map; returns absolute artifact paths array, `null` for unknown agents, `[]` for agents with no canonical artifact (e.g. `@committer`, `@dev`).
255
+ - **`--no-auto-advance` opt-out flag** on `aioson agent:done` for cases where auto-emit is undesirable (debug, manual restore, scripts).
256
+ - **`tests/baselines/agent-done-stdout.txt`** — backward-compat baseline lock per Risk-11 mitigation.
257
+ - **`tests/agent-done-auto-emit.test.js`** — 13 unit tests covering AC-F2-01..10 (happy path, backward-compat, opt-out, idempotency 1s window, corrupt state, missing artifact, unknown agent).
258
+
259
+ ### Changed
260
+ - `src/commands/runtime.js#runAgentDone` injects `maybeAutoAdvanceWorkflow` call after stdout log in both live-session and standalone branches. Idempotency via `last_workflow_event_at` field added to `workflow.state.json` schema (backward-compat: missing field treated as zero).
261
+
262
+ ### Notes
263
+ - This release closes Phase 1 of `workflow-handoff-integrity` MEDIUM feature. Phases 2-5 (F3 CLI guard, F1 stale dev-state, T5 semantic sync, T6 CI smoke) ship as separate releases v1.9.6 → v1.10.0 per progressive release strategy (DD-05).
264
+ - Full npm test: 2520/2521 pass; the single skipped/flaky test is AC-ALL-101 (`telemetry-foundation.test.js`, performance threshold) — pre-existing, documented as separate follow-up.
265
+ - Inception note: this hotfix was implemented via the AIOSON chain itself (`@analyst → @architect → @pm → @dev`) — eating its own dog food.
266
+
267
+ ## [1.9.4] - 2026-05-20
268
+
269
+ ### Fixed
270
+ - **`AskUserQuestion` no longer fires on bare agent activation.** When `/deyvin`, `/product`, `/dev`, `/neo`, or `/setup` loaded without a stated task, the agents were inventing multi-choice options around fabricated next-steps — wasting user attention and inviting arbitrary implementation paths. New **Rule 7** in `decision-presentation/SKILL.md` mandates an informational summary + wait when no task is stated; the per-agent hard constraint was reworded from "Always use `AskUserQuestion`" to "When a real decision requires user input, use `AskUserQuestion`". `@deyvin` Working kernel and `pair-execution.md` updated to mirror.
271
+ - Affects: `decision-presentation/SKILL.md`, `agents/{deyvin,product,dev,neo,setup}.md`, `docs/deyvin/pair-execution.md` (workspace + template parity preserved).
272
+
36
273
  ## [1.9.3] - 2026-05-19
37
274
 
38
275
  ### Fixed
package/README.md CHANGED
@@ -70,12 +70,55 @@ npx @jaimevalasek/aioson install --reconfigure
70
70
  npx @jaimevalasek/aioson install --no-interactive
71
71
  ```
72
72
 
73
- **Update** to a new version (respects your saved profile):
73
+ **Update** the AIOSON files in your project (respects your saved profile):
74
74
 
75
75
  ```bash
76
76
  npx @jaimevalasek/aioson update
77
77
  ```
78
78
 
79
+ > Updating an existing project to a new release? See [Upgrading](#upgrading) — `aioson update` alone is not enough if the CLI itself is out of date.
80
+
81
+ ---
82
+
83
+ ## Upgrading
84
+
85
+ Two things can be on different versions: the **CLI you run** (`aioson`) and the **AIOSON files inside your project** (`.aioson/`). Both need to move together.
86
+
87
+ > ⚠ **The #1 reason `aioson update` "doesn't bring in the new version":** `aioson update` copies the templates bundled with the CLI currently on disk. If your global CLI is on an older release, running `aioson update` from a project will copy that older version's files — no matter how many times you run it. You have to upgrade the CLI itself first.
88
+
89
+ **Step 1 — upgrade the CLI.**
90
+
91
+ If you installed globally:
92
+
93
+ ```bash
94
+ npm install -g @jaimevalasek/aioson@latest
95
+ aioson --version
96
+ ```
97
+
98
+ If `aioson --version` still shows the old version, the binary is being shadowed (older Node on PATH, nvm switch, leftover global install). Reinstall cleanly:
99
+
100
+ ```bash
101
+ npm uninstall -g @jaimevalasek/aioson
102
+ npm install -g @jaimevalasek/aioson@latest
103
+ aioson --version
104
+ ```
105
+
106
+ Prefer not to install globally at all? Use `npx` pinned to `@latest` — it always fetches the latest published version and ignores anything installed globally:
107
+
108
+ ```bash
109
+ npx @jaimevalasek/aioson@latest <command>
110
+ ```
111
+
112
+ **Step 2 — refresh the AIOSON files in each project.**
113
+
114
+ From inside the project directory:
115
+
116
+ ```bash
117
+ aioson update
118
+ ```
119
+
120
+ This copies the latest agents, skills, and templates into `.aioson/`, respecting your saved profile. Repeat in every project you want to bring up to date.
121
+
79
122
  ---
80
123
 
81
124
  ## How it works
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaimevalasek/aioson",
3
- "version": "1.9.3",
3
+ "version": "1.17.2",
4
4
  "description": "AI operating framework for hyper-personalized software.",
5
5
  "keywords": [
6
6
  "ai",
package/src/cli.js CHANGED
@@ -14,6 +14,7 @@ const { runAgentsList, runAgentPrompt } = require('./commands/agents');
14
14
  const { runContextValidate } = require('./commands/context-validate');
15
15
  const { runContextPack } = require('./commands/context-pack');
16
16
  const { runContextLoad } = require('./commands/context-load');
17
+ const { runChainAudit } = require('./commands/chain-audit');
17
18
  const { runMemorySearch } = require('./commands/memory-search');
18
19
  const { runMemoryArchive } = require('./commands/memory-archive');
19
20
  const { runMemoryRestore } = require('./commands/memory-restore');
@@ -177,7 +178,15 @@ const { runClassify } = require('./commands/classify');
177
178
  const { runSizing } = require('./commands/sizing');
178
179
  const { runDetectTestRunner } = require('./commands/detect-test-runner');
179
180
  const { runPulseUpdate } = require('./commands/pulse-update');
180
- const { runStateSave } = require('./commands/state-save');
181
+ const { runStateSave, runStateReset } = require('./commands/state-save');
182
+ const { runOpIdentity } = require('./commands/op-identity');
183
+ const { runOpCapture } = require('./commands/op-capture');
184
+ const { runOpPromote } = require('./commands/op-promote');
185
+ const { runOpForget } = require('./commands/op-forget');
186
+ const { runOpList } = require('./commands/op-list');
187
+ const { runOpShow } = require('./commands/op-show');
188
+ const { runOpReinforce } = require('./commands/op-reinforce');
189
+ const { runOpMigrate } = require('./commands/op-migrate');
181
190
  const { runFeatureClose } = require('./commands/feature-close');
182
191
  const { runFeatureArchive } = require('./commands/feature-archive');
183
192
  const { runDossierInit, runDossierShow, runDossierAddFinding, runDossierAddCodemap, runDossierLinkRule, runDossierCompact } = require('./commands/dossier');
@@ -234,6 +243,8 @@ const JSON_SUPPORTED_COMMANDS = new Set([
234
243
  'context-pack',
235
244
  'context:load',
236
245
  'context-load',
246
+ 'chain:audit',
247
+ 'chain-audit',
237
248
  'test:smoke',
238
249
  'test-smoke',
239
250
  'test:agents',
@@ -583,6 +594,24 @@ const JSON_SUPPORTED_COMMANDS = new Set([
583
594
  'pulse-update',
584
595
  'state:save',
585
596
  'state-save',
597
+ 'state:reset',
598
+ 'state-reset',
599
+ 'op:identity',
600
+ 'op-identity',
601
+ 'op:capture',
602
+ 'op-capture',
603
+ 'op:promote',
604
+ 'op-promote',
605
+ 'op:forget',
606
+ 'op-forget',
607
+ 'op:list',
608
+ 'op-list',
609
+ 'op:show',
610
+ 'op-show',
611
+ 'op:reinforce',
612
+ 'op-reinforce',
613
+ 'op:migrate',
614
+ 'op-migrate',
586
615
  'dev:state:write',
587
616
  'dev-state-write',
588
617
  'feature:close',
@@ -904,6 +933,8 @@ async function main() {
904
933
  result = await runContextPack({ args, options, logger: commandLogger, t });
905
934
  } else if (command === 'context:load' || command === 'context-load') {
906
935
  result = await runContextLoad({ args, options, logger: commandLogger, t });
936
+ } else if (command === 'chain:audit' || command === 'chain-audit') {
937
+ result = await runChainAudit({ args, options, logger: commandLogger, t });
907
938
  } else if (command === 'setup:context' || command === 'setup-context') {
908
939
  result = await runSetupContext({ args, options, logger: commandLogger, t });
909
940
  } else if (command === 'locale:apply' || command === 'locale-apply') {
@@ -1324,6 +1355,24 @@ async function main() {
1324
1355
  command === 'dev-state-write'
1325
1356
  ) {
1326
1357
  result = await runStateSave({ args, options, logger: commandLogger });
1358
+ } else if (command === 'state:reset' || command === 'state-reset') {
1359
+ result = await runStateReset({ args, options, logger: commandLogger });
1360
+ } else if (command === 'op:identity' || command === 'op-identity') {
1361
+ result = await runOpIdentity({ args, options, logger: commandLogger });
1362
+ } else if (command === 'op:capture' || command === 'op-capture') {
1363
+ result = await runOpCapture({ args, options, logger: commandLogger });
1364
+ } else if (command === 'op:promote' || command === 'op-promote') {
1365
+ result = await runOpPromote({ args, options, logger: commandLogger });
1366
+ } else if (command === 'op:forget' || command === 'op-forget') {
1367
+ result = await runOpForget({ args, options, logger: commandLogger });
1368
+ } else if (command === 'op:list' || command === 'op-list') {
1369
+ result = await runOpList({ args, options, logger: commandLogger });
1370
+ } else if (command === 'op:show' || command === 'op-show') {
1371
+ result = await runOpShow({ args, options, logger: commandLogger });
1372
+ } else if (command === 'op:reinforce' || command === 'op-reinforce') {
1373
+ result = await runOpReinforce({ args, options, logger: commandLogger });
1374
+ } else if (command === 'op:migrate' || command === 'op-migrate') {
1375
+ result = await runOpMigrate({ args, options, logger: commandLogger });
1327
1376
  } else if (command === 'feature:close' || command === 'feature-close') {
1328
1377
  result = await runFeatureClose({ args, options, logger: commandLogger });
1329
1378
  } else if (command === 'feature:archive' || command === 'feature-archive') {
@@ -0,0 +1,156 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson chain:audit <file> [--limit=N] [--feature=<slug>] [--json]
5
+ *
6
+ * Phase 1 Slice 2 read-only command. Queries `chain_edges` for active edges
7
+ * (`end_at IS NULL`) whose `source_path` matches the given file, ranked by
8
+ * confidence DESC. Emits one row in `execution_events` per invocation
9
+ * (`event_type='chain_audit'`) so the guardrail metric — tokens stable per
10
+ * audit — can be tracked via `runtime:emit` semantics (BR-NC-10).
11
+ *
12
+ * Failure mode (BR-NC-11): SQLite locked / read errors NEVER block the
13
+ * caller. The telemetry row is still emitted with `error` populated and the
14
+ * command returns `{ ok: true, impacts_found: 0, error: <msg> }`. Callers
15
+ * that block on the impact list see "no impacts" and proceed; @neo will
16
+ * surface "last audit failed" on its next activation by reading the latest
17
+ * chain_audit event.
18
+ */
19
+
20
+ const path = require('node:path');
21
+ const { openRuntimeDb } = require('../runtime-store');
22
+ const { emitChainAuditEvent } = require('../neural-chain-telemetry');
23
+ const { isUnsafePath, sanitizationReason } = require('../neural-chain-sanitize');
24
+
25
+ const DEFAULT_LIMIT = 20;
26
+ const HARD_LIMIT_CAP = 200;
27
+
28
+ function normalizeLimit(value) {
29
+ const parsed = Number(value);
30
+ if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_LIMIT;
31
+ if (parsed > HARD_LIMIT_CAP) return HARD_LIMIT_CAP;
32
+ return Math.floor(parsed);
33
+ }
34
+
35
+ async function runChainAudit({ args, options = {}, logger, t }) {
36
+ const targetDir = path.resolve(process.cwd(), args[0] || '.');
37
+ const json = Boolean(options.json);
38
+ const filePath = options.file || args[1];
39
+ const featureSlug = options.feature ? String(options.feature).trim() : null;
40
+ const limit = normalizeLimit(options.limit);
41
+
42
+ if (!filePath) {
43
+ const msg = (t && t('chain_audit.file_required')) ||
44
+ 'chain:audit requires a file path. Usage: aioson chain:audit <file> [--limit=N] [--feature=<slug>] [--json]';
45
+ if (logger && typeof logger.log === 'function' && !json) logger.log(msg);
46
+ return { ok: false, reason: 'missing_file' };
47
+ }
48
+
49
+ // SF-NC-01/02 Layer B (CLI boundary) — reject unsafe file paths before
50
+ // they reach SQL bind (which is prepared and safe by itself) AND before
51
+ // they get rendered into the telemetry payload + logger output. Mirrors
52
+ // the ingest-side guard in agent-ingest.js#deriveSessionPairs.
53
+ const filePathReason = sanitizationReason(filePath);
54
+ if (filePathReason !== null) {
55
+ const msg = `chain:audit rejected unsafe file path (${filePathReason})`;
56
+ if (logger && typeof logger.log === 'function' && !json) logger.log(msg);
57
+ return { ok: false, reason: 'unsafe_file_path', rejection_reason: filePathReason };
58
+ }
59
+
60
+ let dbHandle;
61
+ try {
62
+ dbHandle = await openRuntimeDb(targetDir);
63
+ } catch (err) {
64
+ const errMsg = err && err.message ? err.message : String(err);
65
+ if (logger && typeof logger.log === 'function' && !json) {
66
+ logger.log((t && t('chain_audit.runtime_unavailable', { error: errMsg })) ||
67
+ `chain:audit runtime db unavailable: ${errMsg}`);
68
+ }
69
+ return { ok: false, reason: 'runtime_db_unavailable', error: errMsg };
70
+ }
71
+
72
+ const { db } = dbHandle;
73
+ const startedAt = Date.now();
74
+ let impacts = [];
75
+ let auditError = null;
76
+
77
+ try {
78
+ // BR-NC-01 — window function dedupes per target_path so dual-source edges
79
+ // (same (source,target) with both git_co_edit AND agent_event) report
80
+ // max(c_git, c_event) as a single row. Hotfix v1.17.1 — bug-found-002.
81
+ impacts = db.prepare(`
82
+ SELECT target_path, edge_type, confidence, hit_count, last_seen_at
83
+ FROM (
84
+ SELECT target_path, edge_type, confidence, hit_count, last_seen_at,
85
+ ROW_NUMBER() OVER (
86
+ PARTITION BY target_path
87
+ ORDER BY confidence DESC, hit_count DESC, last_seen_at DESC
88
+ ) AS rn
89
+ FROM chain_edges
90
+ WHERE source_path = ? AND end_at IS NULL
91
+ )
92
+ WHERE rn = 1
93
+ ORDER BY confidence DESC, hit_count DESC, last_seen_at DESC
94
+ LIMIT ?
95
+ `).all(filePath, limit);
96
+ } catch (err) {
97
+ auditError = err && err.message ? err.message : String(err);
98
+ }
99
+
100
+ const durationMs = Date.now() - startedAt;
101
+
102
+ emitChainAuditEvent(db, {
103
+ agent: null,
104
+ message: `chain:audit ${filePath} → ${auditError ? 'error' : `${impacts.length} impacts`}`,
105
+ feature_slug: featureSlug,
106
+ source_files: [filePath],
107
+ impacts_found: auditError ? null : impacts.length,
108
+ auto_fixable_count: 0,
109
+ noise_file: null,
110
+ tokens_used: 0,
111
+ duration_ms: durationMs,
112
+ error: auditError,
113
+ // Extra context fields
114
+ limit_applied: limit,
115
+ // Legacy singular alias preserved for backward-compat (removed v2)
116
+ source_file: filePath
117
+ });
118
+
119
+ if (auditError) {
120
+ const msg = (t && t('chain_audit.query_failed', { error: auditError })) ||
121
+ `chain:audit failed to query chain_edges: ${auditError}`;
122
+ if (logger && typeof logger.log === 'function' && !json) logger.log(msg);
123
+ // BR-NC-11: failure non-blocking — still return ok with impacts_found=0
124
+ return {
125
+ ok: true,
126
+ source_file: filePath,
127
+ impacts_found: 0,
128
+ duration_ms: durationMs,
129
+ impacts: [],
130
+ error: auditError
131
+ };
132
+ }
133
+
134
+ if (logger && typeof logger.log === 'function' && !json) {
135
+ if (impacts.length === 0) {
136
+ logger.log((t && t('chain_audit.no_impacts', { file: filePath, duration: durationMs })) ||
137
+ `chain:audit ${filePath} → no impacts detected (${durationMs}ms)`);
138
+ } else {
139
+ logger.log((t && t('chain_audit.results_header', { file: filePath, count: impacts.length, duration: durationMs })) ||
140
+ `chain:audit ${filePath} → ${impacts.length} impact(s) (${durationMs}ms):`);
141
+ for (const row of impacts) {
142
+ logger.log(` ${row.target_path} [${row.edge_type}] confidence=${row.confidence.toFixed(2)} hits=${row.hit_count}`);
143
+ }
144
+ }
145
+ }
146
+
147
+ return {
148
+ ok: true,
149
+ source_file: filePath,
150
+ impacts_found: impacts.length,
151
+ duration_ms: durationMs,
152
+ impacts
153
+ };
154
+ }
155
+
156
+ module.exports = { runChainAudit, DEFAULT_LIMIT, HARD_LIMIT_CAP };