@jaimevalasek/aioson 1.9.3 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +188 -0
  2. package/README.md +44 -1
  3. package/package.json +1 -1
  4. package/src/cli.js +45 -1
  5. package/src/commands/op-capture.js +146 -0
  6. package/src/commands/op-forget.js +54 -0
  7. package/src/commands/op-identity.js +145 -0
  8. package/src/commands/op-list.js +105 -0
  9. package/src/commands/op-migrate.js +158 -0
  10. package/src/commands/op-promote.js +66 -0
  11. package/src/commands/op-reinforce.js +73 -0
  12. package/src/commands/op-show.js +71 -0
  13. package/src/commands/op-stubs.js +67 -0
  14. package/src/commands/preflight.js +6 -2
  15. package/src/commands/runtime.js +151 -0
  16. package/src/commands/state-save.js +61 -0
  17. package/src/commands/sync-agents-preflight.js +117 -3
  18. package/src/commands/workflow-next.js +64 -0
  19. package/src/handoff-contract.js +25 -0
  20. package/src/lib/agent-semantic-diff.js +199 -0
  21. package/src/operator-memory/conflict.js +202 -0
  22. package/src/operator-memory/decay.js +157 -0
  23. package/src/operator-memory/decision.js +274 -0
  24. package/src/operator-memory/identity.js +109 -0
  25. package/src/operator-memory/index-md.js +170 -0
  26. package/src/operator-memory/loader.js +106 -0
  27. package/src/operator-memory/proposal.js +179 -0
  28. package/src/operator-memory/prune.js +81 -0
  29. package/src/operator-memory/slug.js +90 -0
  30. package/src/operator-memory/storage.js +121 -0
  31. package/src/preflight-engine.js +91 -1
  32. package/template/.aioson/agents/dev.md +1 -1
  33. package/template/.aioson/agents/deyvin.md +3 -3
  34. package/template/.aioson/agents/neo.md +1 -1
  35. package/template/.aioson/agents/product.md +1 -1
  36. package/template/.aioson/agents/setup.md +1 -1
  37. package/template/.aioson/docs/deyvin/pair-execution.md +1 -1
  38. package/template/.aioson/skills/process/decision-presentation/SKILL.md +9 -0
  39. package/template/AGENTS.md +23 -0
  40. package/template/CLAUDE.md +23 -0
  41. package/template/agents/_shared/memory-capture-directive.md +115 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,107 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.16.0] - 2026-05-21
8
+
9
+ ### Added
10
+ - **Operator memory — Phase 5 TTL decay + migration + closure** (5 of 5 phases — **feature complete**).
11
+ - **`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.
12
+ - **`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`.
13
+ - **`aioson op:reinforce <slug>`** (NEW Phase 5 command): refreshes `last_reinforced` + increments `reinforcement_count`. Silences decay prompt for next half-life window.
14
+ - **`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.
15
+ - **`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.
16
+ - **`tests/operator-memory-decay.test.js`** — 23 new unit tests AC-P5-01..09 (closure ACs P5-10..14 verified by archive process).
17
+ - **`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.
18
+ - **`.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.
19
+
20
+ ### Notes
21
+ - **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).
22
+ - **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).
23
+ - Gate D approved post-QA sign-off. `features.md` operator-memory → `done`. Feature artifacts archived to `.aioson/context/done/operator-memory/`.
24
+ - **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.
25
+
26
+ ## [1.15.0] - 2026-05-21
27
+
28
+ ### Added
29
+ - **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).
30
+ - **`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`.
31
+ - **`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).
32
+ - **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).
33
+ - **`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%.
34
+ - **`scripts/smoke-run-chain.js`** `[OM4]` section — 4 smoke checks (binary V1 conflict, additive no-FP, debounce window, flag-flip directive verification).
35
+ - **`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).
36
+
37
+ ### Changed
38
+ - **`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).
39
+ - Updated wording in directive sections to be flip-aware (still byte-identical between CLAUDE.md and AGENTS.md per parity invariant).
40
+
41
+ ### Notes
42
+ - **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.
43
+ - 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.
44
+ - 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.
45
+
46
+ ## [1.14.0] - 2026-05-21
47
+
48
+ ### Added
49
+ - **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.
50
+ - **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).
51
+ - **`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).
52
+ - **`aioson op:show <slug>` full impl** — replaces Phase 1 stub. Prints decision frontmatter + body, or proposal data when slug is in `proposals/`. `--json` supported.
53
+ - **`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.
54
+ - **`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).
55
+ - **`.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.
56
+ - **`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.
57
+ - **`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.
58
+ - **`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).
59
+
60
+ ### Notes
61
+ - **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.
62
+ - 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.
63
+ - Smoke runner result: 17/17 green (was 14/14 before OM3).
64
+ - 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.
65
+ - 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).
66
+
67
+ ## [1.13.0] - 2026-05-21
68
+
69
+ ### Added
70
+ - **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:
71
+ - **`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).
72
+ - **`aioson op:promote <slug>` full impl** — manual promotion path that skips the 2x threshold for a pending proposal.
73
+ - **`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.
74
+ - **`src/operator-memory/slug.js`** new module: `deriveSlug`, `normalize`, `fingerprintProposal`. Deterministic kebab-case + stopword filter + truncation at word boundary + collision-suffix detection.
75
+ - **`src/operator-memory/proposal.js`** new module: `captureSignal` (write/increment), `readProposal`, `deleteProposal`. Quotes capped at 5 most recent per AC-P2-01.
76
+ - **`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).
77
+ - **`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`.
78
+ - **`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).
79
+ - **`scripts/smoke-run-chain.js`** extended with `[OM2]` section — 3 smoke checks exercising capture+promote pipeline, idempotent forget, signal validation in isolated tmp HOME.
80
+ - **`.aioson/context/wiring-audit-operator-memory.md`** Phase 2 entry populated with call sites, tests, atomicity verification.
81
+
82
+ ### Notes
83
+ - 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.
84
+ - Telemetry events shipped this release: `op_capture`, `op_promote`, `op_forget` via existing `dossierTelemetry.emitDossierEvent` (PMD-12 + DD-04 confirmed: extend, don't fragment).
85
+ - 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.
86
+ - Smoke runner result: 14/14 green (was 11/11 before OM2 section).
87
+ - 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.
88
+
89
+ ## [1.12.0] - 2026-05-21
90
+
91
+ ### Added
92
+ - **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:
93
+ - **`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).
94
+ - **`~/.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.
95
+ - **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.
96
+ - **`src/operator-memory/{identity,storage}.js`** new pure-helper modules exporting `resolveIdentity`, `validateOverride`, `hashEmail`, `ensureStorageTree`, `openIndexDb`, `migrateIndexSchema`, `recordIdentityActivity`. Reusable by downstream phase commands.
97
+ - **`tests/operator-memory-identity.test.js`** — 24 unit tests covering AC-P1-01..10 + EC-08 salt rehash + DD-02 hash size invariant.
98
+ - **`.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).
99
+
100
+ ### Notes
101
+ - 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.
102
+ - 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.
103
+ - 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.
104
+ - 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.
105
+
106
+ ## [1.11.0] - 2026-05-20
107
+
7
108
  ### Added
8
109
  - **@pentester agent**: adversarial security review agent with structured findings output (`security-findings-{slug}.json`) and Gate D blocking capability for MEDIUM projects.
9
110
  - **@discover agent**: system discovery and semantic knowledge cache bootstrap for brownfield projects.
@@ -33,6 +134,93 @@ All notable changes to this project will be documented in this file.
33
134
  - Safe canonical English agent sources restored after i18n decoupling.
34
135
  - Accidentally tracked local directories removed from git tracking.
35
136
 
137
+ ## [1.10.0] - 2026-05-20
138
+
139
+ ### Added
140
+ - **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).
141
+ - **`.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.
142
+ - **`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).
143
+ - **`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.
144
+
145
+ ### Notes
146
+ - **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`.
147
+ - **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.
148
+ - Smoke runner local result: `pass=11 fail=0 — All smoke checks green. Safe to proceed with publish.`
149
+
150
+ ## [1.9.8] - 2026-05-20
151
+
152
+ ### Added
153
+ - **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.
154
+ - **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.
155
+ - **`src/lib/agent-semantic-diff.js`** new pure-helpers module exporting `extractHeaders`, `extractSections`, `extractFrontmatter`, `diffHeaders`, `diffSectionContent`, `diffFrontmatter`, `diffAgentFile`, `normalizeBody`, `hashBody`. Reusable by downstream consumers.
156
+ - **`checkSemanticParity(projectRoot)`** exported from `src/commands/sync-agents-preflight.js`.
157
+ - **`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.
158
+
159
+ ### Changed
160
+ - `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).
161
+
162
+ ### Notes
163
+ - 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.
164
+ - 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).
165
+ - 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.
166
+
167
+ ## [1.9.7] - 2026-05-20
168
+
169
+ ### Added
170
+ - **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>`).
171
+ - **`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.
172
+ - **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.
173
+ - **`detectStaleDevStateRich` + `parseFeaturesMap`** exported from `src/preflight-engine.js` for downstream consumers + tests.
174
+ - **`tests/preflight-stale-devstate.test.js`** — 20 unit tests covering AC-F1-01..08, parseFeaturesMap robustness, and runStateReset (idempotent, archive variant, json mode).
175
+
176
+ ### Changed
177
+ - `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.
178
+
179
+ ### Fixed
180
+ - 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).
181
+
182
+ ### Notes
183
+ - 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.
184
+ - 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.
185
+
186
+ ## [1.9.6] - 2026-05-20
187
+
188
+ ### Added
189
+ - **`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.
190
+ - **`--force` flag** on `aioson workflow:next` for explicit override (logs warning, proceeds). For emergency-use cases.
191
+ - **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).
192
+ - **`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).
193
+
194
+ ### Changed
195
+ - `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.
196
+
197
+ ### Notes
198
+ - 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.
199
+ - 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.
200
+
201
+ ## [1.9.5] - 2026-05-20
202
+
203
+ ### Added
204
+ - **`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).
205
+ - **`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`).
206
+ - **`--no-auto-advance` opt-out flag** on `aioson agent:done` for cases where auto-emit is undesirable (debug, manual restore, scripts).
207
+ - **`tests/baselines/agent-done-stdout.txt`** — backward-compat baseline lock per Risk-11 mitigation.
208
+ - **`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).
209
+
210
+ ### Changed
211
+ - `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).
212
+
213
+ ### Notes
214
+ - 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).
215
+ - 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.
216
+ - Inception note: this hotfix was implemented via the AIOSON chain itself (`@analyst → @architect → @pm → @dev`) — eating its own dog food.
217
+
218
+ ## [1.9.4] - 2026-05-20
219
+
220
+ ### Fixed
221
+ - **`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.
222
+ - Affects: `decision-presentation/SKILL.md`, `agents/{deyvin,product,dev,neo,setup}.md`, `docs/deyvin/pair-execution.md` (workspace + template parity preserved).
223
+
36
224
  ## [1.9.3] - 2026-05-19
37
225
 
38
226
  ### 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.16.0",
4
4
  "description": "AI operating framework for hyper-personalized software.",
5
5
  "keywords": [
6
6
  "ai",
package/src/cli.js CHANGED
@@ -177,7 +177,15 @@ const { runClassify } = require('./commands/classify');
177
177
  const { runSizing } = require('./commands/sizing');
178
178
  const { runDetectTestRunner } = require('./commands/detect-test-runner');
179
179
  const { runPulseUpdate } = require('./commands/pulse-update');
180
- const { runStateSave } = require('./commands/state-save');
180
+ const { runStateSave, runStateReset } = require('./commands/state-save');
181
+ const { runOpIdentity } = require('./commands/op-identity');
182
+ const { runOpCapture } = require('./commands/op-capture');
183
+ const { runOpPromote } = require('./commands/op-promote');
184
+ const { runOpForget } = require('./commands/op-forget');
185
+ const { runOpList } = require('./commands/op-list');
186
+ const { runOpShow } = require('./commands/op-show');
187
+ const { runOpReinforce } = require('./commands/op-reinforce');
188
+ const { runOpMigrate } = require('./commands/op-migrate');
181
189
  const { runFeatureClose } = require('./commands/feature-close');
182
190
  const { runFeatureArchive } = require('./commands/feature-archive');
183
191
  const { runDossierInit, runDossierShow, runDossierAddFinding, runDossierAddCodemap, runDossierLinkRule, runDossierCompact } = require('./commands/dossier');
@@ -583,6 +591,24 @@ const JSON_SUPPORTED_COMMANDS = new Set([
583
591
  'pulse-update',
584
592
  'state:save',
585
593
  'state-save',
594
+ 'state:reset',
595
+ 'state-reset',
596
+ 'op:identity',
597
+ 'op-identity',
598
+ 'op:capture',
599
+ 'op-capture',
600
+ 'op:promote',
601
+ 'op-promote',
602
+ 'op:forget',
603
+ 'op-forget',
604
+ 'op:list',
605
+ 'op-list',
606
+ 'op:show',
607
+ 'op-show',
608
+ 'op:reinforce',
609
+ 'op-reinforce',
610
+ 'op:migrate',
611
+ 'op-migrate',
586
612
  'dev:state:write',
587
613
  'dev-state-write',
588
614
  'feature:close',
@@ -1324,6 +1350,24 @@ async function main() {
1324
1350
  command === 'dev-state-write'
1325
1351
  ) {
1326
1352
  result = await runStateSave({ args, options, logger: commandLogger });
1353
+ } else if (command === 'state:reset' || command === 'state-reset') {
1354
+ result = await runStateReset({ args, options, logger: commandLogger });
1355
+ } else if (command === 'op:identity' || command === 'op-identity') {
1356
+ result = await runOpIdentity({ args, options, logger: commandLogger });
1357
+ } else if (command === 'op:capture' || command === 'op-capture') {
1358
+ result = await runOpCapture({ args, options, logger: commandLogger });
1359
+ } else if (command === 'op:promote' || command === 'op-promote') {
1360
+ result = await runOpPromote({ args, options, logger: commandLogger });
1361
+ } else if (command === 'op:forget' || command === 'op-forget') {
1362
+ result = await runOpForget({ args, options, logger: commandLogger });
1363
+ } else if (command === 'op:list' || command === 'op-list') {
1364
+ result = await runOpList({ args, options, logger: commandLogger });
1365
+ } else if (command === 'op:show' || command === 'op-show') {
1366
+ result = await runOpShow({ args, options, logger: commandLogger });
1367
+ } else if (command === 'op:reinforce' || command === 'op-reinforce') {
1368
+ result = await runOpReinforce({ args, options, logger: commandLogger });
1369
+ } else if (command === 'op:migrate' || command === 'op-migrate') {
1370
+ result = await runOpMigrate({ args, options, logger: commandLogger });
1327
1371
  } else if (command === 'feature:close' || command === 'feature-close') {
1328
1372
  result = await runFeatureClose({ args, options, logger: commandLogger });
1329
1373
  } else if (command === 'feature:archive' || command === 'feature-archive') {
@@ -0,0 +1,146 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson op:capture — record a standing-decision signal (Phase 2, v1.13.0).
5
+ *
6
+ * Usage:
7
+ * aioson op:capture --signal=authorization --quote="..." --proposal="..." --source-agent=dev
8
+ *
9
+ * Flow (architecture-operator-memory.md § Phase 2 capture pipeline):
10
+ * 1. Validate --signal in {authorization, exclusion, correction, confirmation}
11
+ * 2. Resolve identity (Phase 1)
12
+ * 3. deriveSlug(--proposal) — deterministic kebab + truncate
13
+ * 4. Check proposals/{slug}.md:
14
+ * - absent: write proposal with detected_count=1, exit 0 silent
15
+ * - present: detected_count++
16
+ * - count >= 2: promoteProposal (atomic) + stdout audit line
17
+ * - count < 2: update proposal, exit 0 silent
18
+ * 5. Telemetry op_capture before file write
19
+ */
20
+
21
+ const fs = require('node:fs');
22
+ const path = require('node:path');
23
+ const { resolveIdentity } = require('../operator-memory/identity');
24
+ const { ensureStorageTree, recordIdentityActivity, openIndexDb, getStorageRoot } = require('../operator-memory/storage');
25
+ const { deriveSlug, fingerprintProposal } = require('../operator-memory/slug');
26
+ const { captureSignal, readProposal, VALID_SIGNAL_TYPES } = require('../operator-memory/proposal');
27
+ const { promoteProposal } = require('../operator-memory/decision');
28
+ const { emitDossierEvent } = require('../lib/dossier-telemetry');
29
+
30
+ const PROMOTION_THRESHOLD = 2;
31
+
32
+ function existsCheckFactory(identity) {
33
+ return (slug) => {
34
+ const existing = readProposal(identity, slug);
35
+ if (!existing) return null;
36
+ return existing.proposal_fingerprint || fingerprintProposal(existing.proposal || '');
37
+ };
38
+ }
39
+
40
+ async function runOpCapture({ args = [], options = {}, logger }) {
41
+ const targetDir = process.cwd();
42
+ const helpRequested = options.help === true || args.includes('--help') || args.includes('-h');
43
+ if (helpRequested) {
44
+ const msg = `op:capture — capture a standing-decision signal into the proposals queue.
45
+ Usage:
46
+ aioson op:capture --signal=<type> --quote=<verbatim> --proposal=<paraphrase> --source-agent=<agent>
47
+ Signal types: ${VALID_SIGNAL_TYPES.join(', ')}
48
+ First detection writes to proposals/{slug}.md. Second detection promotes to decisions/{slug}.md atomically.`;
49
+ if (options.json) return { ok: true, help: true };
50
+ if (logger) logger.log(msg);
51
+ return { ok: true };
52
+ }
53
+
54
+ const signal = options.signal;
55
+ const quote = options.quote;
56
+ const proposal = options.proposal;
57
+ const sourceAgent = options['source-agent'] || options.sourceAgent || 'unknown';
58
+
59
+ if (!signal || !proposal) {
60
+ const err = `op:capture — required: --signal=<type> --proposal=<paraphrase>. Got signal=${signal}, proposal=${proposal ? 'present' : 'missing'}.`;
61
+ if (options.json) return { ok: false, error: err };
62
+ if (logger && logger.error) logger.error(err);
63
+ return { ok: false, exitCode: 1, error: err };
64
+ }
65
+ if (!VALID_SIGNAL_TYPES.includes(signal)) {
66
+ const err = `op:capture — invalid --signal='${signal}'. Must be one of: ${VALID_SIGNAL_TYPES.join(', ')}.`;
67
+ if (options.json) return { ok: false, error: err };
68
+ if (logger && logger.error) logger.error(err);
69
+ return { ok: false, exitCode: 1, error: err };
70
+ }
71
+
72
+ const resolved = resolveIdentity();
73
+ ensureStorageTree(resolved.identity);
74
+ const db = openIndexDb();
75
+ try {
76
+ recordIdentityActivity(db, { identity: resolved.identity, source: resolved.source });
77
+ } finally {
78
+ db.close();
79
+ }
80
+
81
+ const slug = deriveSlug(proposal, existsCheckFactory(resolved.identity));
82
+
83
+ await emitDossierEvent(targetDir, {
84
+ agent: 'op-capture',
85
+ type: 'op_capture',
86
+ summary: `${signal}: ${slug}`,
87
+ meta: { identity_prefix: resolved.identity.slice(0, 8), signal_type: signal, slug, source_agent: sourceAgent }
88
+ });
89
+
90
+ let result;
91
+ try {
92
+ result = captureSignal({
93
+ identity: resolved.identity,
94
+ slug,
95
+ signal_type: signal,
96
+ quote,
97
+ proposal,
98
+ source_agent: sourceAgent
99
+ });
100
+ } catch (err) {
101
+ const errMsg = `op:capture failed: ${err.message}`;
102
+ if (options.json) return { ok: false, error: errMsg };
103
+ if (logger && logger.error) logger.error(errMsg);
104
+ return { ok: false, exitCode: 1, error: errMsg };
105
+ }
106
+
107
+ const count = result.proposal.detected_count;
108
+
109
+ if (count >= PROMOTION_THRESHOLD) {
110
+ // Promote to decision
111
+ let decision;
112
+ try {
113
+ decision = promoteProposal({ identity: resolved.identity, proposal: result.proposal });
114
+ } catch (err) {
115
+ const errMsg = `op:capture promotion failed: ${err.message}`;
116
+ if (options.json) return { ok: false, error: errMsg };
117
+ if (logger && logger.error) logger.error(errMsg);
118
+ return { ok: false, exitCode: 1, error: errMsg };
119
+ }
120
+
121
+ await emitDossierEvent(targetDir, {
122
+ agent: 'op-capture',
123
+ type: 'op_promote',
124
+ summary: `promoted ${slug} (${signal})`,
125
+ meta: { identity_prefix: resolved.identity.slice(0, 8), slug, signal_type: signal, category: decision.category }
126
+ });
127
+
128
+ const auditLine = `✔ Memory: '${proposal}'. aioson op:forget ${slug} p/ desfazer.`;
129
+ if (options.json) {
130
+ return { ok: true, promoted: true, slug, identity: resolved.identity, category: decision.category };
131
+ }
132
+ if (logger) logger.log(auditLine);
133
+ return { ok: true, promoted: true, slug };
134
+ }
135
+
136
+ // First detection (or below threshold) — silent
137
+ if (options.json) {
138
+ return { ok: true, promoted: false, slug, detected_count: count, identity: resolved.identity };
139
+ }
140
+ return { ok: true, promoted: false, slug, detected_count: count };
141
+ }
142
+
143
+ module.exports = {
144
+ runOpCapture,
145
+ PROMOTION_THRESHOLD
146
+ };
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson op:forget <slug> — soft-delete a decision or proposal to history/.
5
+ * Phase 2 (v1.13.0).
6
+ */
7
+
8
+ const path = require('node:path');
9
+ const { resolveIdentity } = require('../operator-memory/identity');
10
+ const { ensureStorageTree } = require('../operator-memory/storage');
11
+ const { forgetEntry } = require('../operator-memory/decision');
12
+ const { emitDossierEvent } = require('../lib/dossier-telemetry');
13
+
14
+ async function runOpForget({ args = [], options = {}, logger }) {
15
+ const targetDir = process.cwd();
16
+ const positional = (args || []).filter((a) => typeof a === 'string' && !a.startsWith('-') && a !== '.');
17
+ const slug = positional[0];
18
+
19
+ if (options.help === true || args.includes('--help') || args.includes('-h')) {
20
+ if (logger) logger.log('op:forget <slug> — soft-delete a decision or proposal to history/. Idempotent.');
21
+ return { ok: true };
22
+ }
23
+
24
+ if (!slug) {
25
+ const err = 'op:forget — required argument: <slug>. Usage: aioson op:forget <slug>';
26
+ if (options.json) return { ok: false, error: err };
27
+ if (logger && logger.error) logger.error(err);
28
+ return { ok: false, exitCode: 1, error: err };
29
+ }
30
+
31
+ const resolved = resolveIdentity();
32
+ ensureStorageTree(resolved.identity);
33
+ const result = forgetEntry(resolved.identity, slug);
34
+
35
+ await emitDossierEvent(targetDir, {
36
+ agent: 'op-forget',
37
+ type: 'op_forget',
38
+ summary: `${result.mode}: ${slug}`,
39
+ meta: { identity_prefix: resolved.identity.slice(0, 8), slug, mode: result.mode }
40
+ });
41
+
42
+ if (options.json) {
43
+ return { ok: true, mode: result.mode, archived: result.archivedPath };
44
+ }
45
+ if (result.mode === 'noop') {
46
+ if (logger) logger.log(`op:forget — '${slug}' not found (idempotent no-op).`);
47
+ } else {
48
+ const archivedRel = result.archivedPath ? path.basename(result.archivedPath) : null;
49
+ if (logger) logger.log(`op:forget — '${slug}' archived as history/${archivedRel} (${result.mode}).`);
50
+ }
51
+ return { ok: true, mode: result.mode };
52
+ }
53
+
54
+ module.exports = { runOpForget };