Skip to content

feat(connect): fence the Org memory section and add --write - #191

Merged
kendrick merged 5 commits into
mainfrom
issue-175
Nov 10, 2026
Merged

kendrick merged 5 commits into
mainfrom
issue-175

Conversation

@kendrick

Copy link
Copy Markdown
Owner

ltm connect now wraps its ## Org memory section in <!-- ltm:connect:begin --> and <!-- ltm:connect:end -->, and ltm connect --write <file> replaces that region in place or appends it once. The documented step was ltm connect >> AGENTS.md, so every rerun added a second section and left the stale one behind. With the markers, a rerun after adding a Bank rewrites one region, and other tools that edit AGENTS.md, such as working-memory-kit's installer, can tell the region apart from hand-written text.

Closes #175

Start with src/core/connect.ts. It reuses findMarkers from src/core/init.ts, which now takes the begin and end patterns and a label instead of hard-coding the ltm:generated ones. The init.ts change is mechanical, and its error messages come out byte-identical for ltm:generated. The blank-line rule replaceRegion used for appending moved into appendGap so both callers share it.

--write matches on the markers alone, never on the heading text. A hand-written ## Org memory outside any markers stays put, and the fenced region goes below it. A file with a begin marker and no end marker exits 1, names the file, and writes nothing. A missing file is the first-connect case and gets created. Plain ltm connect still prints to stdout, unchanged except for the markers.

The design doc said no tool writes into Consumer repos. Its connect row now says --write is an explicit write a person runs, the same kind as promote's promoted_to stamp. README and guide/getting-started.md now show ltm connect --write AGENTS.md.

The part I'm least sure about is that --write calls writeFileSync straight onto the target rather than writing a temp file and renaming it. A crash mid-write could truncate AGENTS.md. ltm init's replaceRegion callers write the same way, so I matched them rather than adding a pattern only here.

Verification

A reproducer that didn't write the code reran each claim at HEAD 4f06469 against base 7cd6c4b. All 12 came back REPRODUCED. caller means it drove the real CLI (bun src/cli/bin.ts connect) in a scratch repo with its own .ltm.yaml and LTM_CONFIG. seam means no production caller applies, so the check ran on the file or suite directly.

  • AC1, markers (caller): bun src/cli/bin.ts connect gave rc=0, first line <!-- ltm:connect:begin -->, last line <!-- ltm:connect:end -->.
  • AC2, two writes on a file with no region (caller): bun src/cli/bin.ts connect --write A.md twice gave rc=0 both times, grep -c '## Org memory' A.md = 1.
  • AC3, a second Bank (caller): .ltm.yaml set to banks: [acme, second], text appended after the region, then connect --write A.md gave one heading, two Bank at lines, one begin marker, and the leading # Hello text and the trailing tail line unchanged.
  • AC4, falsifier (caller): connect --write B.md on a file starting ## Org memory / hand written left those lines first and gave 2 headings and 1 begin marker.
  • AC5, begin without end (caller): connect --write C.md gave rc=1, stderr ltm connect: C.md: the ltm:connect begin marker has no matching end marker; nothing written, and cmp shows C.md unchanged.
  • AC6, docs (seam, docs have no caller): grep -c 'ltm connect --write AGENTS.md' README.md guide/getting-started.md gave 1 and 1; git diff --stat shows the design doc changed by one line.
  • AC7, suite (seam, whole-suite run): bun run typecheck && bun test gave tsc clean, 1754 pass, 3 skip, 0 fail across 90 files. I reran it after the publish rebase, which was a no-op, with the same counts.
  • Regexes built from the constants (caller): connect --write on a file with an existing region replaced it in place, and on C.md it caught the unmatched begin marker. bun test test/core/connect.test.ts gave 9 pass, covering CRLF and the malformed-marker cases.
  • The CLI error path uses firstLine from core/text.ts (caller): the AC5 run above goes through it.
  • Relative imports use .ts, and imports are sorted (seam, static text): checked with grep and sed -n 3,8p src/cli/connect.ts.

The wave merge test also ran this branch together with #176's and #178's branches on origin/main 7cd6c4b: typecheck plus 1768 pass, 0 fail.

Not Independently Verified

Every claim ran a command, so none.

Plan Concerns

The plan allowed the README and guide prose to name the argument as ltm connect --write <file>. test/guide-commands.test.ts checks only flag names against the CLI, so the <file> placeholder passes it, and nothing else needed to change.

Left Out

  • No separate test for building BEGIN_LINE and END_LINE from the constants. The patterns are the same as the literals they replaced, since the constants hold no regex metacharacters, and the existing CRLF and malformed-marker tests in test/core/connect.test.ts cover them. The reproducer checked this against the code and agreed.
  • The trigger check for money, authz, and schema changes matched only the English word "where" in guide prose, so adversarial-review didn't run and has no advisories to list.

`ltm connect` needs a fenced region of its own (#175), and init's scanner already reports a duplicate block, an end marker with no begin, an end before its begin, and a begin with no end. `findMarkers` now takes the begin and end patterns plus a label for its messages, so connect reuses those rules from one place. `appendGap` holds the blank-line rule that `replaceRegion` had inline. Init passes `ltm:generated`, and its messages come out byte-identical.
Rerunning `ltm connect >> AGENTS.md` stacks a second `## Org memory` section on the first (#175), and nothing can find the old one to replace it. `connectRegion` wraps the section in `<!-- ltm:connect:begin -->` and `<!-- ltm:connect:end -->` with a blank line inside each marker, the padding Prettier and oxfmt add, so formatting the file afterward changes nothing. `spliceConnectRegion` finds the region by whole-line markers through init's `findMarkers`, never by the heading text, so a hand-written `## Org memory` stays put. It replaces the region in place, or appends it below one blank line, and throws on any malformed marker state rather than pair the wrong markers.
The documented `ltm connect >> AGENTS.md` duplicates the section on every rerun, for example after a second Bank goes into `.ltm.yaml` (#175). `ltm connect` now prints the section inside the `ltm:connect` markers, so working-memory-kit's installer and any other tool editing AGENTS.md can tell it apart from hand-written text. `--write <file>` replaces that region in place, appends it once, or creates the file, and prints nothing on success. A malformed marker state or an unreadable path exits 1 naming the file, without writing. Bank resolution runs first, so a repo with no Bank never gets its file touched.
The README and getting-started guide now point Consumer repos at `ltm connect --write AGENTS.md`, which replaces the fenced section on later runs instead of appending a copy. The design doc said no tool writes into consumer repos, but `ltm promote` already stamps `promoted_to` into one when a person runs it. The `connect` row now says `--write` is the same kind of explicit write, and that no tool writes there on its own.
Self-review caught the new connect code drifting from house style. Two imports used `.js` where the repo imports `.ts`, the CLI split the error's first line by hand when `firstLine` already does it, and the marker regexes spelled out the marker strings again, so they could drift from CONNECT_BEGIN/CONNECT_END. They're now built from those constants. The README and guide also named `--write` without its file argument.
@kendrick

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T21:56:24.178249Z 4f06469 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 4f064691db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kendrick

kendrick commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner Author

Deferred findings

# Source Finding Outside because Recommendation Status
1 worker Plan allowed README/guide prose to name the argument as ltm connect --write <file>; test/guide-commands.test.ts checks only flag names, so the placeholder passes and nothing else changed plan concern, not a code finding none needed: dismiss as informational dismissed: informational; the placeholder is fine and nothing changed

@kendrick
kendrick merged commit e085308 into main Nov 10, 2026
16 checks passed
@kendrick
kendrick deleted the issue-175 branch November 10, 2026 21:59
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.

ltm connect: the Org memory section has no markers, so every rerun of the documented step duplicates it

1 participant