Cortex: a bare-date updated on a note's created day makes every search fail with integrity_error

Open Beginner friendly
#2,496 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 9 days

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
bun, typescript
Domain
data, search

Research direction

Start in validateRecord in LIFEOS/TOOLS/Cortex.ts around line 115, and read validTimestamp at lines 104-110 to see how bare dates are accepted. Reproduce with the negative-control steps in the issue: a note with a millisecond created and a bare-date updated on the same day makes Cortex.ts search exit 4. Done means that search returns ok: true for that note, while a genuinely reversed timestamp pair is still rejected.

Written by the indexing model from the issue text.

Description

Version

LifeOS 8.761.0 · attestation: 36 system file(s) differ from danielmiessler/[email protected]:

  • hooks/MemoryTurnStart.hook.ts
  • hooks/LoadContext.hook.ts
  • hooks/SatisfactionCapture.hook.ts
  • hooks/lib/output-validators.ts
  • hooks/lib/learning-utils.ts
  • hooks/WorkCompletionLearning.hook.ts
  • hooks/handlers/VoiceNotification.ts
  • skills/Cortex/Tools/ContextSearch.ts
  • LIFEOS/TOOLS/ProposalScope.ts
  • LIFEOS/TOOLS/Upgrades.ts
  • LIFEOS/TOOLS/FalsePassDraft.ts
  • LIFEOS/TOOLS/MemoryRetriever.ts
  • LIFEOS/TOOLS/HarvestExecutor.ts
  • LIFEOS/TOOLS/KnowledgeHarvester.ts
  • LIFEOS/TOOLS/LearningPatternSynthesis.ts
  • LIFEOS/TOOLS/TranscriptParser.ts
  • LIFEOS/TOOLS/ISARender.ts
  • LIFEOS/TOOLS/MigrateScan.ts
  • LIFEOS/TOOLS/lib/IsaTestStrategy.ts
  • LIFEOS/TOOLS/lib/IsaTemplate.ts
  • LIFEOS/TOOLS/lib/IsaClaims.ts
  • LIFEOS/TOOLS/RecurrenceLedger.ts
  • LIFEOS/TOOLS/KnowledgeDistill.ts
  • LIFEOS/TOOLS/models.ts
  • LIFEOS/TOOLS/Cortex.ts
  • LIFEOS/TOOLS/ISAGate.ts
  • LIFEOS/TOOLS/MemoryGraph.ts
  • LIFEOS/TOOLS/IsaFrontier.ts
  • LIFEOS/TOOLS/SessionHarvester.ts
  • LIFEOS/TOOLS/ProposalGC.ts
  • LIFEOS/TOOLS/IsaGoverning.ts
  • LIFEOS/TOOLS/MemorySystem.ts
  • LIFEOS/TOOLS/model-pricing.json
  • LIFEOS/TOOLS/MemoryTypes.ts
  • LIFEOS/DOCUMENTATION/ARCHITECTURE_SUMMARY.md
  • LIFEOS/HERMES/Policy.ts
What is broken

validateRecord in LIFEOS/TOOLS/Cortex.ts (line 115) rejects a record when Date.parse(updated) < Date.parse(created). validTimestamp (lines 104-110) accepts a bare date (YYYY-MM-DD), and Date.parse reads a bare date as UTC midnight. MemorySystem.renderInitialNote writes created:/updated: to the millisecond (LIFEOS/TOOLS/MemorySystem.ts:555), while the Cortex guide tells the agent to set updated: with date +%Y-%m-%d when it develops or ingests a note (skills/Cortex/References/CompleteGuide.md:176 and :246). So a note born through MemorySystem and developed later the same UTC day ends up with updated before created, and that single note makes every Cortex.ts search fail with integrity_error ("Canonical record ... is updated before it was created"), whatever the query or its language. West of UTC, the local date +%Y-%m-%d can be the previous UTC day, which widens the window. KnowledgeLint and KnowledgeSchema do not check the order, so the note is accepted when written and only search breaks. On this install 15 of 129 notes mix the two formats; one tripped it.

Where (file:line)

LIFEOS/TOOLS/Cortex.ts:115

Repro on a clean tree
1. On a clean 8.761.0 tree, make a memory root holding one note in `KNOWLEDGE/Ideas/` whose frontmatter has `created: 2026-10-25T10:43:39.279Z` (the shape MemorySystem writes) and `updated: 2026-10-25` (a same-day develop per CompleteGuide.md:176).
2. Run `bun LIFEOS/TOOLS/Cortex.ts search probe --memory-root <that root>`.
3. Expected: `ok: true` with the note. Actual: exit 4 and `{"ok":false,...,"error":{"code":"integrity_error","message":"Canonical record kb_probe00000001 is updated before it was created"}}` (captured in the negative control). In a real archive, one such note stops every search until its date is edited by hand.
Negative control

Probe: d=$(mktemp -d); mkdir -p "$d/KNOWLEDGE/Ideas"; printf -- "---\nid: kb_probe00000001\ntype: idea\ntitle: \"probe\"\ntags: [test]\nquality: 5\ncreated: 2026-10-25T10:43:39.279Z\nupdated: 2026-10-25\nconvention: kb-v3\n---\n\nA note created to the millisecond, then developed the same day with a bare-date updated.\n" > "$d/KNOWLEDGE/Ideas/probe.md"; bun skills/LifeOS/install/LIFEOS/TOOLS/Cortex.ts search probe --memory-root "$d" · exit 4 · captured 2026-10-31T10:59:00.398Z

Red looks like: integrity_error

{"schema":"lifeos-cortex/v1","ok":false,"command":"search","data":null,"error":{"code":"integrity_error","message":"Canonical record kb_probe00000001 is updated before it was created"}}
Suggested fix

Treat a bare date as naming a day, not an instant. In validateRecord, when either side is a bare date, compare UTC days and flag only when the earlier side's day is more than one day before the other's; keep the exact comparison when both carry a time:

function bareDateWithinADay(updated: string, created: string): boolean {
  const bare = /^\d{4}-\d{2}-\d{2}$/;
  if (!bare.test(String(updated).trim()) && !bare.test(String(created).trim())) return false;
  const day = (value: string) => Math.floor(Date.parse(String(value).trim()) / 86400000);
  return day(created) - day(updated) <= 1;
}
// line 115
if (Date.parse(record.updated) < Date.parse(record.created) && !bareDateWithinADay(record.updated, record.created)) integrity(`Canonical record ${record.id} is updated before it was created`);

The one-day allowance covers a local date +%Y-%m-%d west of UTC. Having CompleteGuide.md write full ISO timestamps would stop new cases, but notes already in archives keep the mixed format. Line 116 compares valid_from/valid_until the same way and may need the same treatment.

Environment
  • OS: macOS 27.0.1 (arm64)
  • Harness: claude-code
  • bun: 1.4.0 · git: 2.50.1
  • Doctor broken: none
Dominant language
TypeScript
Stars
19.7k
Forks
2.5k
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from danielmiessler/LifeOS

All issues in danielmiessler/LifeOS

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.