* fix(memory-wiki): retry transient existing-page reads in wiki_apply and chatgpt import
A create_synthesis re-run and a ChatGPT conversations re-import swallowed
every existing-page read error and treated the page as brand-new, so one
transient read failure silently emptied the user's ## Notes block and
dropped hand-added frontmatter. Route both reads through a retry-once
helper that treats only a missing page as new and propagates persistent
failures, matching the ingest and imported-source fix from #98360.
* fix(memory-wiki): preserve fs-safe policy failures
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(memory-wiki): disambiguate the reserved index page stem for synthesis and ingest
A create_synthesis or source ingest whose title slugifies to index was
written to the auto-generated <dir>/index.md. That file is the only
compiler-owned page filename: compile writes it per page group, and
compile/query/status exclude it from page scanning. So the stored fact
was both unretrievable and clobbered by the generated directory-index on
the next compile.
The collision only happens at the direct page-stem boundary: synthesis
(syntheses/<slug>.md) and ingest (sources/<slug>.md) build a bare
<dir>/<slug>.md path. The bridge, unsafe-local, and OKF callers compose
slugifyWikiSegment output into prefixed and hashed identities that can
never equal a bare index.md, and OKF already guards its own write path
via OKF_RESERVED_FILENAMES.
Add a dedicated slugifyWikiPageStem helper that escapes the reserved
index stem and route only the two direct page writers through it,
leaving slugifyWikiSegment output stable for the composed callers so
their persisted page ids and paths do not churn on upgrade. Only index
is reserved: the compiler never owns <dir>/log.md in these directories
(the wiki log lives at .openclaw-wiki/log.jsonl), so a Log title keeps
its existing direct path. Additive and deterministic, no migration.
* fix(memory-wiki): preserve reserved-page ids
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* [AI] fix(memory-wiki): gracefully handle unparsable YAML frontmatter in vault scans (#96125)
toWikiPageSummary now catches YAML parse errors during vault-wide scans
(compile/lint/query/status) and returns a degraded WikiPageSummary with
frontmatterError set instead of letting the error propagate through
readPageSummaries -> compileMemoryWikiVault, which previously caused one
bad page to crash the entire vault.
Edit paths (apply, chatgpt-import) still throw on bad frontmatter to
prevent silent metadata loss on write.
- markdown.ts: add frontmatterError field to WikiPageSummary, extract
splitWikiFrontmatterBlock, catch YAML.parse in toWikiPageSummary
- lint.ts: add invalid-frontmatter lint code, skip frontmatter-derived
checks when frontmatterError is present
- markdown.test.ts: test degraded parse preserves body, empty frontmatter
- lint.test.ts: test invalid-frontmatter lint on broken page, healthy
page unaffected
Related to #96125
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(memory-wiki): isolate invalid frontmatter scans
* fix(memory-wiki): keep malformed lint reports fail-closed
* fix(memory-wiki): reject non-mapping frontmatter
* fix(memory-wiki): validate generated index targets
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
* fix(memory-wiki): strip fenced code blocks before wikilink extraction
extractWikiLinks runs OBSIDIAN_LINK_PATTERN against full markdown
including fenced code blocks and inline code spans, causing false
positive 'Broken wikilink target' warnings for bash [[...]] test
syntax and Scala generics inside code blocks.
Strip fenced code blocks and inline code before running the wikilink
regex to eliminate code-block false positives while preserving real
wikilinks in prose.
Fixes#97945
* fix(memory-wiki): strip fenced code blocks before wikilink extraction
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(wiki): discover nested source files in QUERY_DIRS
Two functions in the memory-wiki extension — listWikiMarkdownFiles
(wiki_get runtime lookup) and collectMarkdownFiles (wiki compile
indexing) — used fs.readdir without { recursive: true }. Nested
source files (e.g. sources/audi/car.md) were silently invisible to
both wiki_get and wiki compile.
Add recursive: true and adjust path construction using
entry.parentPath so nested .md files in all QUERY_DIRS are
discovered while preserving the index.md exclusion and backward
compatibility with flat vaults.
* fix(wiki): remove entry.path fallback, only parentPath is typed on Dirent
* fix(wiki): add recursive scan to status.ts and add nested-file regression tests
* fix(wiki): use toSorted instead of sort to pass lint
* style(memory-wiki): format recursive discovery fix
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* chore(release): close out 2026.6.10 on main
* chore(release): align native app metadata for 2026.6.10
* chore(release): sync Android 2026.6.10 notes
* docs(changelog): preserve 2026.6.9 history
* docs(changelog): preserve 2026.6.9 history
* fix(memory-wiki): preserve human notes block on source re-ingest
Re-ingesting an existing source regenerated the page with an empty
wrote inside the human-managed markers. This broke the documented
contract that human note blocks are preserved, and diverged from the
synthesis and chatgpt-import writers that already preserve the block.
When a source page already exists, read it and re-inject its human Notes
block before writing. The block is located by scanning past the fenced
the content, then taking the first human start marker and the last end
marker, so the whole Notes block is preserved verbatim even when the
source content or the note text contains the markers or Markdown
headings. The same preservation is applied to writeImportedSourcePage so
the bridge and unsafe-local source-update writers keep notes too. New
page creation is unchanged.
Adds regressions for plain re-ingest, marker text in source content,
marker text inside the note, a heading inside the note, and an imported
source page update.
* fix(memory-wiki): preserve notes on CRLF source pages
A concurrent atomic rewrite (write-temp + rename) of a memory-wiki source
page by the bridge re-export made fs-safe's opened-fd identity check fail
with `path-mismatch`, which the page write rethrew as a fatal "Refusing to
write" error and aborted the whole wiki_status / source-sync call. The race
is transient and benign: the file is replaced under the open handle and the
concurrent writer lands equivalent content.
Retry briefly on `path-mismatch` (the rename window closes sub-ms) and
rethrow unchanged on exhaustion, so persistent failures (directory
collision, not-file) and symlink/path-alias swaps still hard-fail exactly
as before. The identity guard is untouched; only the benign rename race is
retried, matching the sibling read path that already treats path-mismatch
as transient.
Extracts the guarded-write logic duplicated by source-page-shared.ts and
okf.ts into one writeGuardedVaultPage helper so both write paths get the
fix and the copy is removed.
Closes#92134
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Fixes#92207.
Normalize public memory artifacts at the memory host boundary so providers that omit agentIds produce an empty list instead of throwing during artifact cloning, sorting, or memory-wiki bridge import. The bridge now renders those artifacts with unknown agents while downstream consumers still receive stable array-shaped metadata.
Verification:
- node scripts/run-vitest.mjs src/plugins/memory-state.test.ts extensions/memory-wiki/src/bridge.test.ts --maxWorkers=1
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- Crabbox run_2a30de5d0a00 / cbx_3684cb0b7ea5: OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 corepack pnpm check:changed
- GitHub PR checks clean on 19678ed60f
Bumps OpenClaw release metadata to 2026.5.31 across package manifests, app version files, plugin metadata, changelog headings, and generated shrinkwraps.
Verification:
- pnpm plugins:sync:check
- pnpm ios:version:check
- pnpm deps:shrinkwrap:check
- git diff --check
- stale 2026.5.30/build-code scan across changed files
- autoreview clean: no accepted/actionable findings
- PR CI green for real gates: Checks, security scans, dependency guard, app lanes, real behavior proof
Known non-code workflow issue:
- label workflow failed because this PR hits GitHub's 100-label issue cap before the size-label step.
Summary:
- This PR adds an internal gateway active-run projection flag, clears it during terminal lifecycle handling be ... ons.list on that flag, adds gateway regression coverage, and tightens memory-wiki confidence normalization.
- PR surface: Source +29, Tests +131. Total +160 across 7 files.
- Reproducibility: yes. Source inspection shows current main can broadcast terminal sessions.changed before ch ... the abort-controller entry, and the before/after recording supports the visible stuck In progress symptom.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(gateway): preserve chat retry guard after terminal state
- PR branch already contained follow-up commit before automerge: fix(gateway): clear completed session active runs
Validation:
- ClawSweeper review passed for head 9b132bdc2b.
- Required merge gates passed before the squash merge.
Prepared head SHA: 9b132bdc2b
Review: https://github.com/openclaw/openclaw/pull/87810#issuecomment-4569094800
Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>