Skip to content

eidetic-memory: refresh wrappers (eidetic 0.10) + memory-discipline convention#2

Open
OriNachum wants to merge 1 commit into
mainfrom
rollout/eidetic-memory-0.10
Open

eidetic-memory: refresh wrappers (eidetic 0.10) + memory-discipline convention#2
OriNachum wants to merge 1 commit into
mainfrom
rollout/eidetic-memory-0.10

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

Added

  • Memory-discipline "Conventions and workflow" section in CLAUDE.md — a
    per-task recall-before / remember-after convention (scope localized to this
    repo's nick) so the vendored remember / recall skills are actually used,
    not just present: /recall before non-trivial work to build on prior
    decisions instead of re-deriving them, and /remember when a non-obvious
    decision, constraint, fix-and-why, or hard-won gotcha surfaces. The section
    documents this repo's memory as in-repo and public — records resolve to
    <repo-root>/.eidetic/memory (committed, team- and mesh-shared). Inserted
    idempotently (skipped if already present), slotted under an existing
    "Conventions and workflow" heading when one exists, else appended.

Changed

  • Refreshed the remember + recall wrappers from eidetic-cli 0.10.0
    (cite-don't-import) — picks up eidetic's project-local store default: the
    files backend now resolves per record by visibility — PUBLIC records inside a
    git repo go to <repo-root>/.eidetic/memory (committed, team-shared), PRIVATE
    records (or any record outside a repo) go to $HOME/.eidetic/memory (never
    committed), an explicit EIDETIC_DATA_DIR still wins, and recall reads both
    stores and merges. Also carries the 0.9.3 hardening (interactive-stdin guard,
    help as a search term, SIGPIPE-safe suffix parsing). Recipe policy
    override (the wrappers here are NOT byte-verbatim):
    the injected default
    visibility is flipped from eidetic's private to public, so a plain
    /remember lands the note in ./.eidetic/memory in this repo, kept as part
    of the repo — pass --visibility private to route a record to $HOME
    instead. remember drives eidetic remember (idempotent upsert of one JSON
    record or an NDJSON batch on stdin); recall drives eidetic recall with
    four search modes (exact / approximate / keyword / hybrid). Each SKILL.md is
    localized only in the illustrative --scope <nick> examples (Provenance keeps
    "First-party to eidetic-cli"). Runtime dep: the eidetic CLI on PATH (else a
    local eidetic-cli checkout with uv) — eidetic >= 0.10.0 for the
    in-repo routing; on an older CLI the public records still work but are stored
    in $HOME/.eidetic/memory instead of in-repo. Propagated by rollout-cli's
    eidetic-memory recipe.

- **Memory-discipline "Conventions and workflow" section in `CLAUDE.md`** — a
  per-task *recall-before / remember-after* convention (scope localized to this
  repo's nick) so the vendored `remember` / `recall` skills are actually used,
  not just present: `/recall` before non-trivial work to build on prior
  decisions instead of re-deriving them, and `/remember` when a non-obvious
  decision, constraint, fix-and-why, or hard-won gotcha surfaces. The section
  documents this repo's memory as **in-repo and public** — records resolve to
  `<repo-root>/.eidetic/memory` (committed, team- and mesh-shared). Inserted
  idempotently (skipped if already present), slotted under an existing
  "Conventions and workflow" heading when one exists, else appended.

### Changed

- **Refreshed the `remember` + `recall` wrappers from eidetic-cli 0.10.0**
  (cite-don't-import) — picks up eidetic's **project-local store default**: the
  files backend now resolves per record by visibility — PUBLIC records inside a
  git repo go to `<repo-root>/.eidetic/memory` (committed, team-shared), PRIVATE
  records (or any record outside a repo) go to `$HOME/.eidetic/memory` (never
  committed), an explicit `EIDETIC_DATA_DIR` still wins, and recall reads both
  stores and merges. Also carries the 0.9.3 hardening (interactive-stdin guard,
  `help` as a search term, SIGPIPE-safe suffix parsing). **Recipe policy
  override (the wrappers here are NOT byte-verbatim):** the injected default
  visibility is flipped from eidetic's `private` to **`public`**, so a plain
  `/remember` lands the note in `./.eidetic/memory` in this repo, kept as part
  of the repo — pass `--visibility private` to route a record to `$HOME`
  instead. `remember` drives `eidetic remember` (idempotent upsert of one JSON
  record or an NDJSON batch on stdin); `recall` drives `eidetic recall` with
  four search modes (exact / approximate / keyword / hybrid). Each `SKILL.md` is
  localized only in the illustrative `--scope <nick>` examples (Provenance keeps
  "First-party to eidetic-cli"). Runtime dep: the `eidetic` CLI on PATH (else a
  local eidetic-cli checkout with `uv`) — **`eidetic >= 0.10.0`** for the
  in-repo routing; on an older CLI the public records still work but are stored
  in `$HOME/.eidetic/memory` instead of in-repo. Propagated by rollout-cli's
  `eidetic-memory` recipe.
@qodo-code-review

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test-publish

Failed stage: Build and publish to TestPyPI [❌]

Failed test name: ""

Failure summary:

The action failed during the uv publish step because GitHub Trusted Publishing to TestPyPI is not
correctly configured for this repository/workflow/environment.
- uv publish could not obtain an
OIDC-based publishing token (line 209) and TestPyPI returned 422 Unprocessable Entity (line 210).
-
TestPyPI reported invalid-publisher: the token was valid, but no publisher configuration matched the
token claims (line 211).
- The token claims indicate the publish attempt came from
repo:agentculture/refactor-cli:environment:testpypi and workflow ref
agentculture/refactor-cli/.github/workflows/publish.yml@refs/pull/2/merge (lines 214-223), which
likely does not match any publisher entry configured in the TestPyPI project (or trusted publishing
may not be set up for PR/merge refs or the testpypi environment).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

194:  ##[endgroup]
195:  Publishing 0.4.0.dev5 to TestPyPI
196:  ##[group]Run uv build
197:  �[36;1muv build�[0m
198:  �[36;1muv publish --publish-url https://test.pypi.org/legacy/ --trusted-publishing always --check-url https://test.pypi.org/simple/�[0m
199:  shell: /usr/bin/bash -e {0}
200:  env:
201:  UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
202:  DEV_VERSION: 0.4.0.dev5
203:  ##[endgroup]
204:  Building source distribution...
205:  Building wheel from source distribution...
206:  Successfully built dist/refactor_cli-0.4.0.dev5.tar.gz
207:  Successfully built dist/refactor_cli-0.4.0.dev5-py3-none-any.whl
208:  Publishing 2 files to https://test.pypi.org/legacy/
209:  error: Failed to obtain token for trusted publishing
210:  Caused by: Server returned error code 422 Unprocessable Entity, is trusted publishing correctly configured?
211:  Response: {"errors":[{"code":"invalid-publisher","description":"valid token, but no corresponding publisher (Publisher with matching claims was not found)"}],"message":"Token request failed"}
212:  Token claims, which must match the publisher configuration: GitHub(
213:  GitHubTokenClaims {
214:  sub: "repo:agentculture/refactor-cli:environment:testpypi",
215:  repository: "agentculture/refactor-cli",
216:  repository_owner: "agentculture",
217:  repository_owner_id: "277824871",
218:  job_workflow_ref: "agentculture/refactor-cli/.github/workflows/publish.yml@refs/pull/2/merge",
219:  ref: "refs/pull/2/merge",
220:  environment: Some(
221:  "testpypi",
222:  ),
223:  },
224:  )
225:  ##[error]Process completed with exit code 2.
226:  ##[group]Run echo "::notice::Test with: uv tool install --index-url https://test.pypi.org/simple/ --index-strategy unsafe-best-match refactor-cli==${DEV_VERSION}"

@sonarqubecloud

Copy link
Copy Markdown

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Refresh eidetic remember/recall wrappers (0.10) and document memory discipline
✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

Description

• Refresh vendored remember/recall wrappers to align with eidetic-cli 0.10 store routing.
• Default wrapper visibility to public and add safer CLI/arg-handling guardrails.
• Document recall-before/remember-after workflow and bump project to 0.4.0.
Diagram

graph TD
  U(("Developer")) --> RSH["recall.sh"] --> E["eidetic CLI"] --> PUB[("Repo memory (.eidetic/memory)")]
  U(("Developer")) --> MSH["remember.sh"] --> E["eidetic CLI"] --> PRI[("Home memory (~/.eidetic/memory)")]
  E["eidetic CLI"] --> OUT["Results/Exit codes"]
  subgraph Legend
    direction LR
    _actor(("Actor")) ~~~ _proc["Script/CLI"] ~~~ _db[("Store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep default visibility private (upstream behavior)
  • ➕ Minimizes risk of accidentally committing sensitive notes
  • ➕ Avoids policy divergence from eidetic-cli defaults
  • ➖ Undermines the stated goal of team-shared, in-repo memory by default
  • ➖ Requires more frequent explicit flags to contribute to shared memory
2. Require explicit --visibility for both wrappers
  • ➕ Makes privacy/visibility an intentional choice every time
  • ➕ Reduces ambiguity when culture.yaml suffix is missing
  • ➖ Adds friction; likely reduces adoption of remember/recall
  • ➖ Conflicts with the documented “plain /remember lands in repo” workflow
3. Centralize routing policy via EIDETIC_DATA_DIR + repo config
  • ➕ Keeps wrappers thinner and closer to upstream
  • ➕ Moves policy into environment/config management
  • ➖ Harder to ensure consistent behavior across ephemeral worktrees/agents
  • ➖ Less discoverable; the wrapper is the most visible enforcement point

Recommendation: Proceed with this PR’s approach: defaulting the wrappers to --visibility public matches the repo’s intended team-shared memory discipline and leverages eidetic-cli 0.10’s in-repo routing. The added warnings/guards reduce footguns (missing query, missing culture suffix, interactive-stdin hang). The main trade-off is policy divergence from upstream defaults; the explicit --visibility private escape hatch and the CLAUDE.md guidance adequately mitigate this.

Files changed (5) +142 / -27

Enhancement (2) +74 / -26
recall.shAlign recall wrapper with eidetic 0.10 and safer CLI/arg handling +35/-13

Align recall wrapper with eidetic 0.10 and safer CLI/arg handling

• Updates store-location documentation to match eidetic-cli 0.10’s per-visibility routing and two-store merge behavior. Tightens UX: '--help' is the only help alias, empty query is a hard error (so 'help' can be searched), and missing eidetic CLI prints a concise install hint. Improves robustness with SIGPIPE-safe suffix parsing and changes default injected visibility to 'public', plus a warning when no culture suffix resolves and no visibility was specified.

.claude/skills/recall/scripts/recall.sh

remember.shAlign remember wrapper with eidetic 0.10 and prevent interactive-stdin hangs +39/-13

Align remember wrapper with eidetic 0.10 and prevent interactive-stdin hangs

• Updates store-location documentation to match eidetic-cli 0.10 routing semantics and simplifies the “eidetic not found” error to a direct install hint. Adds a guard that shows usage when invoked with no args and interactive stdin (to avoid blocking on NDJSON). Makes suffix parsing SIGPIPE-safe and flips the wrapper’s default injected visibility to 'public', warning when no suffix resolves and visibility wasn’t explicitly chosen.

.claude/skills/remember/scripts/remember.sh

Documentation (2) +67 / -0
CHANGELOG.mdAdd 0.4.0 entry documenting memory discipline and wrapper refresh +39/-0

Add 0.4.0 entry documenting memory discipline and wrapper refresh

• Introduces a 0.4.0 changelog section capturing the new CLAUDE.md workflow guidance and the eidetic wrapper refresh, including the policy override to default visibility to public.

CHANGELOG.md

CLAUDE.mdDocument recall-before/remember-after memory-discipline workflow +28/-0

Document recall-before/remember-after memory-discipline workflow

• Adds a “Conventions and workflow” section that establishes the per-task habit of recalling before work and remembering after non-obvious decisions. Explicitly documents that this repo’s memory is in-repo/public by default (with opt-out via '--visibility private') and notes the eidetic-cli version dependency for in-repo routing.

CLAUDE.md

Other (1) +1 / -1
pyproject.tomlBump project version to 0.4.0 +1/-1

Bump project version to 0.4.0

• Updates the package version from 0.3.0 to 0.4.0 to reflect the release documented in the changelog.

pyproject.toml

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 17 rules

Grey Divider


Action required

1. recall.sh modified in vendored skill 📘 Rule violation ⚙ Maintainability
Description
This PR directly edits .claude/skills/recall/scripts/recall.sh and
.claude/skills/remember/scripts/remember.sh, which are vendored skill files that must not be
modified in-repo. These changes risk being overwritten by the next guildmaster re-sync and create
upstream drift/divergence unless made upstream and re-synced.
Code

.claude/skills/recall/scripts/recall.sh[R9-13]

+# The store is the files backend. Default location resolves per-operation:
+# PUBLIC records inside a git repo → <repo-root>/.eidetic/memory (committed,
+# team-shared); PRIVATE records, or any record outside a git repo →
+# $HOME/.eidetic/memory (never committed). Recall reads both stores and merges.
+# An explicit EIDETIC_DATA_DIR wins and short-circuits to that single dir.
Evidence
Compliance rule 920898 forbids direct modifications to files under .claude/skills/. The cited
ranges in .claude/skills/recall/scripts/recall.sh and
.claude/skills/remember/scripts/remember.sh show updated in-file documentation/content,
demonstrating that the PR makes in-place edits to vendored skill files rather than updating them
upstream and re-syncing.

Rule 920898: Do not directly modify files under .claude/skills/; re-sync vendored skills from guildmaster instead
.claude/skills/recall/scripts/recall.sh[9-13]
.claude/skills/remember/scripts/remember.sh[15-19]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
This PR includes direct edits to vendored skill files under `.claude/skills/` (`.claude/skills/recall/scripts/recall.sh` and `.claude/skills/remember/scripts/remember.sh`), which violates the policy against in-repo modifications of these synced assets.

## Issue Context
Vendored skills should be updated upstream and then re-synced from guildmaster (or by updating the sync configuration / upstream source). Otherwise, local edits will drift/diverge from upstream and may be overwritten on the next guildmaster re-sync.

## Fix Focus Areas
- .claude/skills/recall/scripts/recall.sh[9-13]
- .claude/skills/remember/scripts/remember.sh[15-19]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Flags-only remember can hang 🐞 Bug ☼ Reliability
Description
The new interactive-stdin guard only checks for zero arguments, so remember.sh --json (or any
flags-only call) still reaches eidetic remember with no record argument and an interactive stdin,
causing an indefinite block waiting for NDJSON. This can stall CI/agent runs and defeats the
intended hardening.
Code

.claude/skills/remember/scripts/remember.sh[R76-84]

+# No record argument AND stdin is an interactive terminal → `eidetic remember`
+# would block forever waiting for NDJSON. Show usage instead of hanging. A piped
+# or redirected stdin (`cat records.ndjson | remember.sh`) is not a TTY and
+# proceeds to the batch path normally.
+if [ "$#" -eq 0 ] && [ -t 0 ]; then
+    usage >&2
+    printf 'hint: pass a JSON record as an argument, or pipe NDJSON on stdin.\n' >&2
+    exit 1
+fi
Evidence
The guard currently only triggers when there are zero args, but the wrapper forwards all args to
eidetic remember; with flags-only and a TTY stdin there is still no record payload, so the
underlying CLI will wait on stdin indefinitely.

.claude/skills/remember/scripts/remember.sh[76-85]
.claude/skills/remember/scripts/remember.sh[51-66]
.claude/skills/remember/scripts/remember.sh[160-164]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`remember.sh` adds an interactive-stdin guard, but it only triggers when `$# == 0`. If the user passes only flags (e.g. `remember.sh --json`) and stdin is a TTY, `eidetic remember` will still block forever waiting for NDJSON.

## Issue Context
The wrapper’s contract is: either a single JSON record as the first argument, or NDJSON via stdin. When stdin is interactive and there is no JSON record argument, we should fail fast with usage.

## Fix Focus Areas
- .claude/skills/remember/scripts/remember.sh[76-85]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Remember usage text stale 🐞 Bug ⚙ Maintainability
Description
remember.sh now defaults to injecting --visibility public when a culture.yaml suffix is
resolved, but its usage() text still tells users the default is a private personal scope and that
--visibility public is needed for the shared pool. This contradicts the actual runtime behavior
and will mislead users.
Code

.claude/skills/remember/scripts/remember.sh[R62-64]

+Records default to this agent's PRIVATE personal scope (--scope from the
+culture.yaml suffix); pass --visibility public to contribute to the shared
+public pool. Every flag is forwarded verbatim to `eidetic remember`.
Evidence
usage() says records default to private and suggests passing --visibility public, but the
wrapper now injects --visibility public automatically when it finds a suffix. CLAUDE.md documents
the intended new public-default behavior, confirming the help text is stale.

.claude/skills/remember/scripts/remember.sh[51-67]
.claude/skills/remember/scripts/remember.sh[139-157]
culture.yaml[1-3]
CLAUDE.md[48-53]
.claude/skills/remember/SKILL.md[11-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The wrapper’s behavior changed to default `--visibility public`, but `usage()` still claims the default is private and that users should pass `--visibility public` to contribute to the shared pool.

## Issue Context
This repo’s CLAUDE.md documents the new policy as public/in-repo by default. The wrapper help and SKILL.md should match to avoid operator confusion.

## Fix Focus Areas
- .claude/skills/remember/scripts/remember.sh[51-67]
- .claude/skills/remember/scripts/remember.sh[139-157]
- .claude/skills/remember/SKILL.md[1-20]
- .claude/skills/remember/SKILL.md[89-101]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. Recall comments/docs stale 🐞 Bug ⚙ Maintainability
Description
recall.sh now injects --visibility public by default when a suffix is resolved, but the script’s
own comment block and the /recall SKILL.md still describe a private-default recall. This
inconsistency will confuse users when private notes don’t appear unless --visibility private is
explicitly passed.
Code

.claude/skills/recall/scripts/recall.sh[R139-145]

+        # rollout-cli eidetic-memory recipe POLICY OVERRIDE (not eidetic's
+        # upstream private default): default to PUBLIC, so a plain recall queries
+        # the in-repo public pool (<repo>/.eidetic/memory) this repo writes to.
+        # Pass --visibility private to also surface this agent's private ($HOME)
+        # notes. The two-store read model reads both dirs regardless.
+        has_flag --visibility "$@" || SCOPE_ARGS+=(--visibility public)
+    elif ! has_flag --visibility "$@"; then
Evidence
The code path now defaults --visibility public when culture.yaml provides a suffix, but the
wrapper’s comment block and SKILL.md still state the default is private/personal, which no longer
matches execution.

.claude/skills/recall/scripts/recall.sh[82-99]
.claude/skills/recall/scripts/recall.sh[134-154]
culture.yaml[1-3]
.claude/skills/recall/SKILL.md[12-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`recall.sh` behavior now defaults visibility to public, but inline documentation and SKILL.md still describe a private-default recall.

## Issue Context
The wrapper’s new policy is documented elsewhere (CLAUDE.md / CHANGELOG), so the remaining stale docs are local to the recall wrapper + SKILL.md.

## Fix Focus Areas
- .claude/skills/recall/scripts/recall.sh[82-99]
- .claude/skills/recall/scripts/recall.sh[134-154]
- .claude/skills/recall/SKILL.md[11-22]
- .claude/skills/recall/SKILL.md[114-129]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +9 to +13
# The store is the files backend. Default location resolves per-operation:
# PUBLIC records inside a git repo → <repo-root>/.eidetic/memory (committed,
# team-shared); PRIVATE records, or any record outside a git repo →
# $HOME/.eidetic/memory (never committed). Recall reads both stores and merges.
# An explicit EIDETIC_DATA_DIR wins and short-circuits to that single dir.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. recall.sh modified in vendored skill 📘 Rule violation ⚙ Maintainability

This PR directly edits .claude/skills/recall/scripts/recall.sh and
.claude/skills/remember/scripts/remember.sh, which are vendored skill files that must not be
modified in-repo. These changes risk being overwritten by the next guildmaster re-sync and create
upstream drift/divergence unless made upstream and re-synced.
Agent Prompt
## Issue description
This PR includes direct edits to vendored skill files under `.claude/skills/` (`.claude/skills/recall/scripts/recall.sh` and `.claude/skills/remember/scripts/remember.sh`), which violates the policy against in-repo modifications of these synced assets.

## Issue Context
Vendored skills should be updated upstream and then re-synced from guildmaster (or by updating the sync configuration / upstream source). Otherwise, local edits will drift/diverge from upstream and may be overwritten on the next guildmaster re-sync.

## Fix Focus Areas
- .claude/skills/recall/scripts/recall.sh[9-13]
- .claude/skills/remember/scripts/remember.sh[15-19]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +76 to +84
# No record argument AND stdin is an interactive terminal → `eidetic remember`
# would block forever waiting for NDJSON. Show usage instead of hanging. A piped
# or redirected stdin (`cat records.ndjson | remember.sh`) is not a TTY and
# proceeds to the batch path normally.
if [ "$#" -eq 0 ] && [ -t 0 ]; then
usage >&2
printf 'hint: pass a JSON record as an argument, or pipe NDJSON on stdin.\n' >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Flags-only remember can hang 🐞 Bug ☼ Reliability

The new interactive-stdin guard only checks for zero arguments, so remember.sh --json (or any
flags-only call) still reaches eidetic remember with no record argument and an interactive stdin,
causing an indefinite block waiting for NDJSON. This can stall CI/agent runs and defeats the
intended hardening.
Agent Prompt
## Issue description
`remember.sh` adds an interactive-stdin guard, but it only triggers when `$# == 0`. If the user passes only flags (e.g. `remember.sh --json`) and stdin is a TTY, `eidetic remember` will still block forever waiting for NDJSON.

## Issue Context
The wrapper’s contract is: either a single JSON record as the first argument, or NDJSON via stdin. When stdin is interactive and there is no JSON record argument, we should fail fast with usage.

## Fix Focus Areas
- .claude/skills/remember/scripts/remember.sh[76-85]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant