mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
studio
15
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cc328cfda8 |
fix(memory): a fact that cannot be read is not absent
loadMemory returned (false, nil) for a read error, so every caller treated a present-but-unreadable fact file as missing: it vanished from /memory, the desktop panel, the memory tool and recall, and a save by name then minted a new id at revision 1 over it with no snapshot, losing the old identity and history. loadMemory now returns a typed FactReadError. ListActive reports unreadable facts beside the readable ones, and the listing, read-by-name, panel, tool and recall audit all name them; recall still serves the readable facts and keeps its old sentence for a whole-directory failure. A save by that name refuses before snapshotting or writing anything. |
||
|
|
2c5ed024f5 |
fix(memory): re-check a delivered fact by reading its own file, not its stat
Problem: a fact saved through Controller.SaveMemory and then edited outside the
session is still recalled from the stale snapshot on the next turn; the per-turn
re-check that catches external edits compared each recalled fact with a stat, so
a rewrite that preserved the file's byte length and modification time stayed
invisible and the model kept reading the stale body; and the identity read behind
that stat, Store.Read, resolves a name by listing the whole store directory and
parsing every fact in it.
Root cause: the re-check set held only the previous recall's hits. A save queues
a turn-tail note, and a note suppresses recall for that turn, so a just-saved
fact was never a hit and so was never re-checked. Its check also rested on size
plus modification time, which is not semantic equality -- the repository's
context-projection rule says freshness detection must not rest on mtime.
Fix: baseline the facts the previous turn handed the model -- the previous
recall's hits, plus the facts a write note carried -- with a digest of each
fact's own file, read once at the canonical path its scope and slug name. Before
a recall tail is built those files are re-read directly and their digests
compared: different bytes reload the snapshot, identical bytes never do. The
stamp carries no size and no modification time, so no stat result can decide
that a fact is unchanged; the bytes are the semantic version because they are
exactly what the renderer turns into the model-visible fact. Store.Read stays as
the fallback for a fact whose file is not where its name says.
Cost: one read of each delivered fact's own file per recall, plus one when it is
baselined and, on that baseline, one parse of the same file to confirm the stamp
describes the delivered fact; a snapshot reload only when a delivered fact's
bytes differ or its file is gone. A formatting-only external rewrite re-reads the
fact into the snapshot even though the parsed fact is equal -- the safe
direction. A fact edited into relevance that the previous turn never handed over
stays invisible until the session reloads; no full scan, which
docs/SESSION_MEMORY_RETRIEVAL.md now states, along with the no-hit retention and
the identity fallback.
This extends the merged fix in
|
||
|
|
99fe3dbbf1 | fix(memory): re-read the facts the last recall returned before recalling again | ||
|
|
39a1e8b432 |
fix(memory): surface unreadable store directories
Problem: permission and storage failures can hide existing memory revisions, make restores report them as missing, and compute recovery revisions from an incomplete history. Root cause: directory discovery conflated every ReadDir error with absence. Fix: unify all eleven store walks behind a typed reader that treats only missing directories as empty. Propagate errors through reads, save guards, recovery, recall, controller commands, and HTTP responses. Complete recovery and legacy duplicate discovery before writing. Preserve persisted formats. Verification: failing-first permission fixture; eleven-site permission, I/O, and non-directory regressions; unchanged files on failed recovery or save; missing-directory compatibility; tool/controller/HTTP and bilingual error coverage; Go tests, vet, lint, repository checks, frontend tests and typecheck, and Windows memory test cross-compilation. Fixes #12950 |
||
|
|
9c3ab6ffda |
docs(memory): the saved-fact index is not in the stable prefix
|
||
|
|
8787ef30a2 | fix(memory): back up legacy memory files before the V2 migration rewrites them | ||
|
|
0e03a900b5 |
docs: bring the contract documents up to the docs standard
Add owner headers to twelve contract and design documents, split their over-wide paragraphs into rules, route their ownership to the primary named in CODEOWNERS, and treat the generated protocol index as a machine-read file. Baseline: doc-owner 40 -> 27, doc-prose 2276 -> 2147. |
||
|
|
9a999f7b7b |
docs: port the retired-Wails wording cleanup to studio
Wails stopped being the desktop shell when the Electron shell landed, but seven places on `studio` still describe it in the present tense. Six of them were already fixed on `main-v2` by #10018; they only need the same edit carried over here. - `CHECKPOINTS`: the desktop rewind control calls `controller.Rewind` over the desktop host protocol, not the Wails binding. - `TASK_CONTRACT`: the constraint keeps the desktop host JSON contract intact. - `RECOVERY`: `doctor` inspects install problems without loading the desktop shell, and macOS keeps LaunchServices launching the desktop app bundle. - `DESKTOP_CRASH_DIAGNOSTICS_RUNBOOK`: the budget is pre-shell work, and report/metric persistence runs after shell startup. - `SESSION_MEMORY_RETRIEVAL`: the example project file no longer points at `desktop/frontend/wailsjs/`, which went away with the Wails shell. Studio commits its generated files under `internal/ext/extension/protocol/`. - `REASONIX.md`: the frontends behind `control.Controller` are the chat TUI, HTTP/SSE serve and the Electron desktop. - `issue-auto-label`: the classifier prompt no longer tells the model the desktop app is Wails. |
||
|
|
45ff0be851 |
feat(memory): subject keys - the knowledge-conflict model
Duplicate prevention matched names, titles, and descriptions; a fact titled 'Package manager' saying npm and one titled 'Dependency tooling' saying pnpm were unrelated to the store and both stayed active. Text similarity is not identity. subject_key names the question a fact answers: project.package_manager, project.release_branch, user.response_style. One scope holds at most one active value per subject - saving a second fact for a held subject is rejected with the holder's id, revision, and current value, worded for the model to act on: re-issue as an update of that id and the new value lands as a revision of one fact, with the old value in history. Not a knowledge graph; a single-valued slot model, the smallest thing that stops silent contradictions. Subject keys join recallIdentityKeys, so FindOverrides, pinned project-over-global suppression, and recall dedup all treat facts answering the same question as equivalent regardless of names and titles - the same-subject project fact shadows its global counterpart everywhere at once. Keys normalize (lowercase, dotted segments) so punctuation variants cannot mint distinct identities; unkeyed facts are exempt from the conflict model entirely. remember gains subject_key (search first, reuse existing keys); /memory subjects lists the keys in use with their holders. Cross-fact save invariants consolidate into validateSave. Boot goldens regenerated for the schema. |
||
|
|
a5fa118cc0 |
feat(memory): volatility, expiry, and verification for freshness
Freshness was type + updated_at with hardcoded windows, but type is not volatility: a README location holds for years while a release branch dies in days. Three optional fields make aging a property of the fact. volatility (evergreen | stable | volatile) is self-describing and overrides the type windows - volatile 7/30 days, stable 90/365, evergreen never ages; unset keeps the legacy type defaults, so existing facts classify exactly as before. expires_at is a hard boundary, stronger than stale: past it a fact is 'expired' and automatic recall excludes it entirely - a dead release branch in the prompt is negative value - while explicit search and /memory still show it, annotated. remember accepts RFC3339 or a bare date, and "never" clears an inherited expiry (SaveOptions.ClearExpiry: dropping a boundary must be stated intent, not an omission side effect). last_verified_at renews the freshness clock without changing what updated_at means: the clock runs from the newer of content change and explicit confirmation. /memory verify <id-or-name> stamps it through the normal save path (revisioned, honestly recorded), and remember gains a verified flag for the model to use when it has just re-checked a fact against reality. Freshness classification moves to freshness.go (one concern per file, the render.go precedent); every consumer - recall demotion, /memory, diagnostics - already flowed through FreshnessFor and inherits the new semantics at the source. Boot goldens regenerated for the schema. |
||
|
|
43e39385ea |
feat(memory): activation dimension - pinned vs relevant facts
Scope said where a fact may be used but was doubling as whether its body rides every session's stable prefix: all global user/feedback bodies loaded unconditionally - no freshness gate, no cap, alphabetical order. Forty accumulated preferences meant prefix bloat plus unrelated- preference contamination on every request. Activation makes that an orthogonal, explicit choice. relevant (the default) is retrieval-only; pinned rides the stable prefix. A fact is in exactly one channel: pinnedGuidance snapshots pinned bodies (recency order, project-over-global suppression preserved, project pinned facts no longer self-shadow), and automatic recall's skip rule flips from 'global user/feedback' to 'pinned' - so unpinned guidance becomes recallable instead of unreachable. Pinned bodies are budgeted (1,500 runes) at write time, never truncated at read time: the prefix always equals exactly what the user curated, and overflow errors point to REASONIX.md/AGENTS.md, where always-binding rules belong. Legacy global user/feedback facts resolve pinned until explicitly unpinned (ResolveActivation), so upgrades change no behavior and over-budget stores surface at the next pin attempt. Surfaces: remember gains an activation enum (pinned only on explicit user request), /memory pin|unpin flip it through the normal save path (revisioned, budget-checked), the summary and prefix index mark pinned facts, docs updated bilingually, boot goldens regenerated for the schema and the renamed prefix section. |
||
|
|
8bca8fad2f |
feat(memory): CJK bigram retrieval and write-time recall keywords
Two ends of the same lexical gap in saved-fact recall. Tokenizer: CJK runs now index as overlapping bigrams (lone runes stay single terms) - the standard CJK FTS unit. Per-rune unigrams let a query match scattered common characters, which the auto-recall side patched with a 'three matched CJK runes' rule; that patch retires, because two matched bigrams already mean a shared word pair or three-character run. One tokenizer serves every FTS surface (memory recall, auto recall, history search, product docs), so all four inherit the fix at the source. The unigram length inflation that biased BM25 normalization against mixed-language documents goes away with it. Keywords: recall stays lexical on purpose, but the write side has a model in the loop. remember gains an optional space-separated keywords field - synonyms, translations of key terms, related commands - stored in frontmatter, searched by both recall paths, never rendered into the index or the recall block. An update omitting keywords preserves them (inheritOnUpdate, same contract as scope). A paraphrased or cross- language query now reaches facts whose own words it never uses. Frontmatter serialization moves to render.go; boot goldens regenerated for the schema's new optional property. |
||
|
|
32721fc0e1 |
feat(context): introduce Context Engine v2 / 引入上下文引擎 v2 (#7001)
* feat(memory): separate standing instructions from scoped facts * fix(memory): preserve scoped memory compatibility Problem: Omitted-scope updates could move legacy global memories into the current project, and global preferences or feedback were unavailable on the first turn. Mixed-version clients could also route independently scoped facts through the wrong directory. Root cause: Save normalized an empty scope before consulting the active file, the stable prompt only contained the memory index, and previous releases treated metadata.type as the routing signal. Fix: Preserve the effective scope of same-name updates, snapshot global user and feedback bodies into deterministic lower-priority guidance, retain a previous-release routing type alongside authoritative fact_type metadata, and queue complete save/revocation notes for the current session. Verification: ./scripts/cache-guard.sh go vet ./... env -u DEEPSEEK_API_KEY go test ./... (cd desktop) go test ./... (cd desktop/frontend) pnpm test (cd desktop/frontend) pnpm build gofmt -l . git diff --check * refactor(context): separate raw and provider user input * refactor(instructions): resolve scoped context with provenance * refactor(memory): add versioned fact storage Context: Memory facts were addressed by mutable slugs, trusted a separately maintained index, and had no durable update history or conflict protection. Change: Add stable IDs, monotonic revisions, atomic writes, derived indexes, deterministic legacy migration, scoped identity handling, revision restore, and optimistic update checks. Surface the metadata through tools and Desktop while preserving legacy frontmatter routing and Safe Mode behavior. Compatibility: Existing files remain readable, gain deterministic runtime metadata before migration, and keep metadata.type/fact_type/scope values that previous releases understand. Added Desktop JSON fields are optional. Verification: go test ./internal/memory; go test -race ./internal/memory; go test ./internal/boot -run Test.*Memory; go test ./... with provider credentials isolated; desktop go test ./...; frontend pnpm test and typecheck; go vet ./...; ./scripts/cache-guard.sh. * feat(memory): recall relevant facts per user turn Problem: Saved facts were only visible through a stable index and required the model or user to invoke memory search manually. Design: Add conservative host-side BM25 recall for real user turns with project-over-global deduplication, freshness labels, explainable scoring, strict character limits, and local-home redaction. Keep the system prompt and tool schemas stable by appending recall only to the provider user-turn tail, and exclude synthetic turns and already-loaded global guidance. Compatibility: Preserve Store.List behavior and add ListAll for scope-aware consumers. No persisted memory or session fields change; display fallbacks strip the new transient suffix. Verification: go test -count=1 ./internal/memory ./internal/agent ./internal/control go test -race -count=1 ./internal/memory go test -race -count=1 ./internal/control with focused recall tests go test -count=1 ./internal/tool/builtin/ ./internal/boot/ go vet ./... ./scripts/cache-guard.sh * feat(memory): auto-save low-risk project facts Problem: Every remember call required a fresh approval, including bounded project facts that were new, non-sensitive, and low impact. This made durable context expensive enough that agents and users often skipped it. Design: Classify interactive remember requests against the scoped store. Automatically allow only explicit project/reference creates that are bounded, non-sensitive, and not semantic duplicates. Keep global, user/feedback, sensitive, and overwrite requests on the existing fresh-human path; keep headless and sub-agent mutation fail closed. Safety: Issue one-shot hashed grants and enforce create-only again inside the serialized Store write, preventing an approval-to-write race from becoming an overwrite. Clear abandoned grants at turn completion. Expose revision history and audited restore through the controller. Compatibility: The remember description and schema are unchanged. RequireCreate is a runtime-only SaveOptions field; persisted memory and session formats are unchanged. Verification: DEEPSEEK_API_KEY= go test -count=1 ./... go test -count=1 ./... in desktop go test -race -count=1 ./internal/memory ./internal/control with memory/approval tests go vet ./... ./scripts/cache-guard.sh * feat(memory): recover archived facts safely Problem: Archived facts remained inspectable on disk but users could not recover them through Reasonix, and ad hoc restoration could overwrite active memory or lose revision provenance. Fix: Add store-validated archive recovery with collision checks, exclusive active-file creation, monotonic revisions, revision snapshots, controller turn-tail refresh, and a Desktop restore action. Compatibility: Existing active and archived Markdown files remain readable; recovery writes the established v2 frontmatter and hidden revision layout, while older binaries continue to read the restored active fact. Verification: go test ./internal/memory ./internal/control; go test ./... in desktop; pnpm test; pnpm exec tsc --noEmit; ./scripts/cache-guard.sh. * feat(context): expose memory recall diagnostics Expose scoped fact freshness, project-over-global conflict decisions, and the last automatic recall trace through the desktop contract. Add revision history and restore APIs while preserving non-null collection responses and remote-workspace isolation. This gives Context Center enough provenance to explain what was available, selected, suppressed, or restored without changing the stable prompt prefix. * feat(context): add provenance center to desktop Make scoped memories explainable in the desktop settings surface. Show stable identity, freshness, revision history, project-over-global resolution, automatic recall traces, instruction precedence, imports, and diagnostics. The suggestions workflow remains compatible while the Context Center gains zero-impact read paths and explicit restore actions for user-controlled recovery. * feat(memory): make suggestions zero-config Open the suggestions surface with automatic local-history scanning by default, removing the hidden localStorage setup switch. Keep every candidate behind explicit confirmation. Deduplicate against all scoped active facts and resolved instruction bodies so project and global memories cannot produce repeated guidance. * feat(memory): add CLI diagnostics and recovery Context: Context Engine v2 exposed revision, recall, and instruction provenance in the backend and desktop, but the CLI only listed legacy merged facts and archives. Changes: - add shared /memory diagnostics for scoped facts, recall traces, instruction precedence, revisions, and archives - add explicit revision restore and archive recovery commands with structured completion across CLI, desktop, and remote workspaces - preserve same-name facts across scopes and keep narrow TUI output bounded Verification: - go test ./internal/control ./internal/cli ./internal/remote/workbench/runtime ./internal/memory -count=1 - go test -race ./internal/control ./internal/memory - cd desktop && go test . -count=1 - ./scripts/cache-guard.sh Cache-impact: management diagnostics only; provider-visible prompt and tool schemas are unchanged. * docs(context): document instructions and memory v2 Context: Context Engine v2 changed instruction precedence, automatic recall, safe memory writes, revision recovery, and desktop suggestions, while the user docs still described the legacy approval-only retrieval model. Changes: - rewrite the context and memory contract around standing instructions versus background facts - document recall freshness, project-over-global resolution, zero-configuration writes and suggestions, revision/archive recovery, cache stability, privacy, and remote fail-closed behavior - add a complete Chinese companion and update Guide, CLI, migration, spec, approval, and README navigation in both languages Verification: - validated relative Markdown links, code fences, and final newlines across 14 changed files - scanned for stale approval/suggestion claims - git diff --cached --check - scanned the staged diff for secrets and machine-local paths * fix(context): preserve safe headless memory writes Allow controller-scoped low-risk project/reference creates to pass the non-interactive approval gate while keeping deny rules and all higher-risk memory operations fail-closed. Reject archive recovery through symlinked files or archive directories, with end-to-end regressions for both boundaries. * fix(memory): reject non-directory migration roots * fix(context): make instruction and memory references safe Problem: Provider-visible instruction paths exposed machine-local roots, memory results exposed store paths, and listed scoped references could not be used directly for read, update, revision, or archive operations. Root cause: Instruction rendering used absolute source paths and memory lookup treated display names as unqualified slugs. Symlink reads also crossed boundaries through a path-resolution gap, while scope-aware listing deduplicated same-name facts. Fix: Render stable workspace/user provenance, confine instruction and import reads to their owning roots, reject external symlinks, and support project/<name>.md and global/<name>.md references end to end. Preserve unqualified compatibility, stable-ID renames, revision snapshots, exact-scope archive behavior, low-risk create-only approval boundaries, and bilingual documentation. Verification: Focused instruction/memory tests and race tests; go test -count=1 ./...; go test -race ./...; go vet ./...; desktop go test/race/vet; pnpm test:all; pnpm build; go run ./cmd/remote-protocol-gen --check; ./scripts/cache-guard.sh (8/8 pass, long tool loop tail average 95%); staged privacy scan clean. * docs(contributors): attribute adopted context work Attribution: Record the authors whose prior pull request mechanisms were adapted by the Context Engine v2 integration. - cyq1017: feedback injection from #5710 and Markdown input normalization from #5603 - salarkhannn: Markdown input normalization from #5604 Scope: This metadata-only commit adds repository-level co-author attribution without changing runtime behavior. Verification: Confirmed source PR ownership and both public GitHub noreply identities. Co-authored-by: cyq <[email protected]> Co-authored-by: Salar <[email protected]> * test(desktop): allow slow Windows git metadata probe Problem: The Windows Desktop CI job failed when MetaForTab's asynchronous first git probe did not finish within the test's one-second deadline. Root cause: The production path intentionally launches the cold git branch lookup in the background so tab metadata never blocks. Windows runner process startup can exceed one second under normal CI load, making the test timing assumption platform-fragile. Fix: Keep the non-blocking metadata implementation unchanged and extend the cross-platform test observation window to five seconds, with a comment documenting the Windows process-startup variance. Verification: - GOCACHE=/tmp/reasonix-desktop-go-cache go test -count=1 -run 'TestMetaForTabIncludesWorkspaceContext|TestWorkspaceGitBranch' ./desktop - git diff --check --------- Co-authored-by: cyq <[email protected]> Co-authored-by: Salar <[email protected]> |
||
|
|
608527502a | Restrict remember/forget and plan approvals to fresh human-only flow | ||
|
|
92854c6a00 |
feat: lightweight local history + memory retrieval (#4071)
Pure-Go BM25 retrieval (no SQLite/CGO/embeddings) behind read-only, on-demand history and memory tools; archive-instead-of-delete for forgotten memories; fresh human approval (with content preview) for agent-initiated remember/forget; desktop Memory settings overhaul with heuristic candidate suggestions. Cache-first prefix stays stable, guarded by regression tests. |