Skip to content

feat(ctx): add CTX AI context engine to lingo.dev#2061

Open
Bhavya031 wants to merge 14 commits intolingodotdev:mainfrom
Bhavya031:main
Open

feat(ctx): add CTX AI context engine to lingo.dev#2061
Bhavya031 wants to merge 14 commits intolingodotdev:mainfrom
Bhavya031:main

Conversation

@Bhavya031
Copy link
Copy Markdown

@Bhavya031 Bhavya031 commented Mar 28, 2026

Summary

Adds demo/ctx — an agentic CLI that generates and maintains lingo-context.md for lingo.dev projects using Claude.

Changes

  • Added demo/ctx/ package with full agentic pipeline: research → context generation → JSONC injection → provider sync
  • Supports fresh scan, incremental update (uncommitted changes), and commit-range modes
  • Generates per-locale brand voices via --voices flag
  • Integrates demo/ctx into the monorepo workspace

Testing

Business logic tests added:

  • ctx runs a fresh scan and produces a valid lingo-context.md
  • ctx detects no changes when source files are unchanged and exits cleanly
  • ctx --dry-run previews what would run without writing any files
  • ctx --voices generates per-locale brand voices into i18n.json
  • All tests pass locally

Visuals

N/A — CLI tool, no UI changes.

Checklist

  • Changeset added (if version bump needed)
  • Tests cover business logic (not just happy path)
  • No breaking changes (or documented below)

Closes #2056

Summary by CodeRabbit

  • New Features

    • New ctx CLI to generate and maintain project translation context (fresh/update/commit modes, dry-run) with interactive review flows and per-locale brand-voice generation.
    • AI-assisted research brief generation and automatic insertion of translator notes into localization files; sync/update of translation provider settings.
  • Documentation

    • Comprehensive README describing workflows, CLI usage, modes, review UI, and operational details.
  • Chores

    • Added .gitignore rules for demo context.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

Adds a new CLI-driven Node.js tool "ctx" under demo/ctx that generates and maintains lingo-context.md, injects translator notes into JSONC localization files, updates i18n.json provider settings and voices, and provides interactive research, review, and voice-generation flows via the Anthropic API.

Changes

Cohort / File(s) Summary
Project config & docs
demo/ctx/.gitignore, demo/ctx/package.json, demo/ctx/README.md
New package, CLI entry config, ignore rules, and extensive README documenting purpose, modes, CLI usage, and prerequisites.
CLI entrypoint
demo/ctx/agent.ts
Primary CLI orchestration: modes (fresh/update/commit), change detection, optional research, context generation/updating, JSONC injection, provider sync, and state recording.
Agent loop & tools
demo/ctx/src/agent-loop.ts
Agent runtime and tool execution loop, safe-path enforcement, tool routing, and interactive per-file review flow for write_file.
Research & voices
demo/ctx/src/research.ts, demo/ctx/src/voices.ts
Research agent (web/file/questionnaire) to produce briefs; voice-generation flow to produce/review per-locale brand voices and write to i18n.json.
I/O, git, and state
demo/ctx/src/files.ts, demo/ctx/src/state.ts
Filesystem and git wrappers (read/write/list, changed files), MD5-based persistent state, file hashing, filtering, and recording processed files.
i18n & JSONC processing
demo/ctx/src/jsonc.ts, demo/ctx/src/i18n.ts
Generate translator notes via Anthropic, inject // CTX: comments into JSONC keys with review loop, parse/compare context sections, and update i18n.json provider prompt/voices.
CLI/UI helpers
demo/ctx/src/cli.ts, demo/ctx/src/ui.ts
Argument parsing, TTY utilities (selectMenu, textPrompt, die) and ANSI-formatted terminal UI helpers (headers, progress, review boxes, colored status lines).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as agent.ts
    participant Agent as Agent Loop
    participant Anthropic as Anthropic API
    participant FS as File System
    participant Git as Git

    User->>CLI: run `ctx` (args)
    CLI->>Git: git status / diff (changed files)
    Git-->>CLI: changed file list
    CLI->>Agent: start generation/update (i18n.json, contextPath)
    Agent->>Anthropic: request context / research / voices
    Anthropic-->>Agent: replies (may request tools)
    Agent->>FS: list/read/write files (tool calls)
    FS-->>Agent: file contents / write results
    Agent->>User: prompt review for writes/notes
    User-->>Agent: accept / skip / request changes
    alt Accepted
        Agent->>FS: write final files
    end
    Agent->>CLI: completed updates
    CLI->>FS: inject JSONC comments, update i18n provider
    CLI->>Git: record state (hashes)
    CLI-->>User: summary / exit
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested labels

community

Suggested reviewers

  • sumitsaurabh927
  • vrcprl

Poem

🐰 Hopped through files both near and far,
I stitched a context, light as a star.
Voices tuned and notes slipped in place,
Translators hum with an on‑brand grace.
Cheers — the ctx warren found its space.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding CTX AI context engine to lingo.dev.
Description check ✅ Passed The description covers Summary, Changes, and Testing sections with business logic tests checked off, but Changeset and additional test documentation remain incomplete.
Linked Issues check ✅ Passed The PR addresses the primary objectives from #2056: integrates CTX into the repository at demo/ctx, provides agentic pipeline, implements required modes, and includes business logic tests.
Out of Scope Changes check ✅ Passed All changes are directly related to adding the CTX AI context engine. No unrelated modifications or refactoring detected outside the demo/ctx package scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (2)
demo/ctx/src/files.ts (1)

7-15: Error strings embedded in content could propagate to LLM prompts.

When readFile fails, it returns [Error: ${e}] which could be sent to the AI model as file content. Consider whether callers should handle this case explicitly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/src/files.ts` around lines 7 - 15, The readFile function currently
returns an error string ("[Error: ${e}]") which can leak into LLM prompts;
change readFile (and its callers) to avoid embedding errors in file content by
either rethrowing the caught error or returning a clear non-content sentinel
(e.g., null | undefined or a Result object) instead of a string; update
references to readFile(filePath: string) so callers check for the sentinel/error
and handle/report it explicitly rather than treating the return as file content.
demo/ctx/README.md (1)

61-61: Add language specifiers to fenced code blocks.

Multiple code blocks are missing language identifiers (e.g., lines 61, 90, 134, 156, 164, 202, 326). Adding text or plaintext satisfies linters and improves rendering.

Also applies to: 90-90, 134-134, 156-156, 164-164, 202-202, 326-326

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/README.md` at line 61, Several fenced code blocks in the README are
missing language specifiers; update each triple-backtick block that has no
language identifier to include a language such as "text" or "plaintext" so
linters and renderers can correctly format them (i.e., locate each ```...```
block with no specifier and change to ```text or ```plaintext).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demo/ctx/agent.ts`:
- Around line 151-159: The candidate selection filters out i18n.json because
only bucket-matching files are kept; modify the construction of candidates
(where gitChanged is filtered by matchesBucket) to also include files named
"i18n.json" (or whose basename is i18n.json) so that files returned by
getChangedFiles() still make it through; update the expression that builds
candidates (the array combining gitChanged.filter(matchesBucket) and
resolveBucketFiles()) to use gitChanged.filter(f => matchesBucket(f) ||
path.basename(f) === 'i18n.json') (or equivalent) before passing to
filterNewFiles and assigning earlyChangedFiles.

In `@demo/ctx/package.json`:
- Around line 5-7: The package's CLI is registered via the "bin" entry pointing
to agent.ts but the file relies on a TypeScript runner (tsx) that lives in
devDependencies and will be missing for global installs; either update the
shebang in agent.ts from its current tsx invocation to use npx (e.g., use
"/usr/bin/env -S npx tsx") so the local tool is discovered at runtime, or move
"tsx" from devDependencies into dependencies in package.json so it gets
installed for global users, or instead compile agent.ts to a JS file and update
the "bin" entry to point to the compiled JS; locate the "bin" entry in
package.json and the shebang in agent.ts to apply the chosen change.

In `@demo/ctx/README.md`:
- Around line 27-29: The README currently claims "Built with Bun" (badge text
"Built with Bun") but the project uses tsx/Node as shown in package.json
(scripts referencing "tsx"); update the documentation and badges to reflect the
actual runtime by removing or replacing the Bun badge and any "Built with Bun"
text with "Built with Node.js" or "Built with tsx/Node", and ensure other
occurrences (the repeated badge/text mentions) are updated consistently; search
for the badge alt/text "Built with Bun" and the literal "Built with Bun" string
in the README and replace them with the correct runtime wording matching
package.json's use of tsx.

In `@demo/ctx/src/agent-loop.ts`:
- Around line 45-50: executeTool currently accepts model-provided paths and
calls listFilesFn, readFile, and writeFile directly, allowing path traversal
outside the project; modify executeTool to accept an allowedRoot (or rootPath)
parameter, resolve and normalize the target path for each case (use the same
resolver for list_files/listFilesFn(input.directory), readFile(input.file_path),
writeFile(input.file_path)), and reject any path whose resolved absolute path is
not inside allowedRoot (return an error like "Path outside project root").
Update callers to pass the project root into executeTool and ensure
listFilesFn/readFile/writeFile are only invoked with validated, resolved paths.

In `@demo/ctx/src/cli.ts`:
- Around line 65-68: The current code calls process.stdin.setRawMode(true) which
will throw in non-TTY environments; update the logic around the Promise in
cli.ts to first check process.stdin.isTTY and only call
process.stdin.setRawMode(true) when true, otherwise fall back to a
non-interactive path (e.g., skip raw mode and resolve/exit gracefully or switch
to line-oriented input). Ensure you still call process.stdin.resume() and
setEncoding("utf-8") in the TTY case, and handle the non-TTY branch by resolving
the Promise or invoking the existing non-interactive handler so the process
doesn't crash.

In `@demo/ctx/src/files.ts`:
- Around line 41-61: getChangedFiles currently parses git status --porcelain
lines with slice(3).trim(), which yields "old -> new" for renames and breaks
path resolution; update the mapping used when commits === null to detect rename
entries from git status (lines starting with 'R' or with a rename token), and
when the trimmed string contains '->' split on '->' and use the right-hand (new)
path (trimmed) as the file path (still feeding it into path.join(cwd, ...));
keep existing handling for non-rename entries and for the git diff (commits !==
null) path, and reuse listFiles/fs.statSync logic unchanged.

In `@demo/ctx/src/i18n.ts`:
- Around line 61-75: newProvider currently overwrites i18n.provider entirely
(dropping fields like baseUrl and settings and mismatching schema), so change
the sync to merge into the existing provider instead of replacing it: if
i18n.provider exists, create mergedProvider = { ...i18n.provider, id:
"anthropic", model: "claude-haiku-4-5", prompt: `Translate from {source} to
{target}.\n\n${context}` } (preserve any existing baseUrl, settings and other
custom fields), then use mergedProvider for i18n.provider and write to i18nPath;
keep the existing selectMenu flow and only apply the merge when user chooses
"Update". Also ensure you only copy voices if it exists in the current provider
schema (i18n.provider?.voices) rather than adding a new voices field
unconditionally.

In `@demo/ctx/src/jsonc.ts`:
- Around line 56-60: The code currently pops any preceding line that starts with
"//" (result.pop() when trimStart().startsWith("//")), which deletes user
comments; change this to only remove previously generated CTX comments by using
a stable prefix (e.g., "// CTX:") so you only replace your own annotations.
Update the logic around result.pop() to check for trimStart().startsWith("//
CTX:") and when adding comments use the same prefix (e.g., in the push where you
build the comment string for comments[key], write `${indent}// CTX:
${comments[key]}`) so subsequent runs only replace lines that begin with that
unique marker.

In `@demo/ctx/src/research.ts`:
- Around line 102-112: The loop handling toolUses currently passes
model-provided paths directly into listFiles and readFile; modify the branches
for "list_files" and "read_file" to resolve the requested path against targetDir
and abort if it escapes: use path.resolve(targetDir, input.directory) /
path.resolve(targetDir, input.file_path), compute a normalized relative path
(e.g., path.relative(targetDir, resolved)), and if that relative path begins
with ".." or is absolute outside targetDir, do not call listFiles/readFile —
instead push a safe error/result (e.g., tool_result with an error message) and
still call toolCall with a sanitized input; only call listFiles/readFile when
the resolved path is inside targetDir.
- Around line 80-117: The loop currently breaks unless stop_reason ===
"tool_use" but doesn't handle response.stop_reason === "pause_turn"; modify the
loop so that when response.stop_reason === "pause_turn" you append the assistant
content to messages (same as messages.push({ role: "assistant", content:
response.content })) and then immediately continue the loop (calling
client.messages.create again) so Claude can finish the paused turn; keep the
existing tool_use handling (collect toolUses, push tool_results, then push user
message with toolResults) but ensure pause_turn does not cause an early exit —
specifically check response.stop_reason for "pause_turn" before breaking and
treat it by pushing assistant content and looping to re-request via
client.messages.create.

In `@demo/ctx/src/state.ts`:
- Around line 8-15: The code in getStateDir uses process.env.HOME! which can be
undefined on Windows or restricted environments; update getStateDir to resolve a
safe home directory by using os.homedir() (or fallbacks like
process.env.USERPROFILE or HOMEDRIVE+HOMEPATH) instead of the non-null
assertion, then build the state path with path.join and create the directory as
before; reference getStateDir and _stateDir so you locate and replace the
process.env.HOME! usage with a robust homeDir resolution.

In `@demo/ctx/src/ui.ts`:
- Around line 39-46: The path-shortening in toolCall currently treats any arg as
a path (arg -> short) and mangles non-path values like search queries; update
toolCall so it only applies the split-and-slice shortening when the selected arg
appears to be a filesystem path (e.g., contains a '/' or matches a path-like
regex) and otherwise leave the arg unchanged (or apply a simple length-based
truncation for very long strings); adjust references to arg and short in the
function so name, arg selection logic (input.file_path, input.directory,
Object.values(input)[0]) and the console.log use the
validated/possibly-truncated display value instead of unconditionally splitting
by '/'.

In `@demo/ctx/src/voices.ts`:
- Around line 67-69: The current code reads context with readFile(contextPath)
and parses i18n via JSON.parse(i18nRaw) without error handling, so unreadable
files or malformed JSON can leak errors into downstream calls; update the logic
around the symbols context, readFile, i18nRaw, i18nPath and JSON.parse to
validate and handle failures: check the return of readFile(contextPath) and
treat non-string/error-return values as failures (log/throw or return a safe
default), wrap JSON.parse(i18nRaw) in a try/catch that handles malformed JSON
(log the parse error and either fallback to an empty object or propagate a
controlled error), and ensure i18nRaw is a string before parsing so errors from
fs.readFileSync are detected and handled.

---

Nitpick comments:
In `@demo/ctx/README.md`:
- Line 61: Several fenced code blocks in the README are missing language
specifiers; update each triple-backtick block that has no language identifier to
include a language such as "text" or "plaintext" so linters and renderers can
correctly format them (i.e., locate each ```...``` block with no specifier and
change to ```text or ```plaintext).

In `@demo/ctx/src/files.ts`:
- Around line 7-15: The readFile function currently returns an error string
("[Error: ${e}]") which can leak into LLM prompts; change readFile (and its
callers) to avoid embedding errors in file content by either rethrowing the
caught error or returning a clear non-content sentinel (e.g., null | undefined
or a Result object) instead of a string; update references to readFile(filePath:
string) so callers check for the sentinel/error and handle/report it explicitly
rather than treating the return as file content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 12193040-6105-48b5-a856-da78988ee117

📥 Commits

Reviewing files that changed from the base of the PR and between 336eeae and a3c3c5a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • demo/ctx/.gitignore
  • demo/ctx/README.md
  • demo/ctx/agent.ts
  • demo/ctx/package.json
  • demo/ctx/src/agent-loop.ts
  • demo/ctx/src/cli.ts
  • demo/ctx/src/files.ts
  • demo/ctx/src/i18n.ts
  • demo/ctx/src/jsonc.ts
  • demo/ctx/src/research.ts
  • demo/ctx/src/state.ts
  • demo/ctx/src/ui.ts
  • demo/ctx/src/voices.ts

tsx was in devDependencies, which are not installed for global consumers
of the bin entry; moving it to dependencies ensures the shebang resolves.

Made-with: Cursor
The project uses tsx/Node, not Bun. Updated the badge, install
requirements section, and the requirements list to reflect the
actual runtime.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
demo/ctx/README.md (1)

244-248: ⚠️ Potential issue | 🟡 Minor

Install commands still reference Bun but project uses Node.js/tsx.

The badge was updated to reflect tsx/Node.js, but the install commands still use bun install and bun link. Since package.json uses tsx as the TypeScript runner and the requirements section specifies Node.js, these commands should be updated for consistency.

📝 Proposed fix
 ```bash
 git clone https://github.com/bhavya031/ctx
 cd ctx
-bun install
-bun link
+npm install
+npm link
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @demo/ctx/README.md around lines 244 - 248, Update the install command block
in the README to use Node/npm instead of Bun: replace the lines "bun install"
and "bun link" with "npm install" and "npm link" (the fenced code block that
currently shows git clone, cd ctx, bun install, bun link), ensuring the commands
align with package.json/tsx usage and the README's Node.js requirements.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>demo/ctx/src/jsonc.ts (1)</summary><blockquote>

`51-65`: **Edge case: Multi-line `// CTX:` comments are not handled.**

The current logic only removes a single preceding `// CTX:` line. If a previous run generated a multi-line comment (split across lines) or if there are consecutive CTX comments from repeated runs with errors, stale lines could accumulate.

Consider whether multi-line CTX comments are possible. If the LLM could generate notes with newlines that get split, you may want a loop to pop all consecutive `// CTX:` lines.


<details>
<summary>🔧 Optional: Remove all consecutive CTX comments</summary>

```diff
     if (keyMatch) {
       const indent = keyMatch[1];
       const key = keyMatch[2];
-      if (result.length > 0 && result[result.length - 1].trimStart().startsWith("// CTX:")) {
+      // Remove all consecutive CTX comments (handles multi-line or stale duplicates)
+      while (result.length > 0 && result[result.length - 1].trimStart().startsWith("// CTX:")) {
         result.pop();
       }
       if (comments[key]) result.push(`${indent}// CTX: ${comments[key]}`);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/src/jsonc.ts` around lines 51 - 65, The loop that writes lines only
removes a single preceding CTX comment before inserting a new one, so change the
logic in the for-loop that iterates over lines (the block using keyMatch,
indent, key, and result) to pop all consecutive CTX comment lines instead of
one: replace the single if (result.length > 0 && result[result.length -
1].trimStart().startsWith("// CTX:")) result.pop(); with a loop that continues
popping while result is non-empty and the last element trimmed startsWith("//
CTX:"), then proceed to push the new comment from comments[key] and the current
line; this ensures multi-line or repeated "// CTX:" lines are fully removed
before inserting the updated comment.
demo/ctx/agent.ts (1)

18-18: Consider handling non-numeric --commits values.

parseInt(values.commits, 10) returns NaN for non-numeric input like --commits abc. While this would likely cause a git error later, validating early provides a better user experience.

🛡️ Proposed validation
-const commitCount = values.commits ? parseInt(values.commits, 10) : null;
+const commitCount = values.commits ? parseInt(values.commits, 10) : null;
+if (commitCount !== null && (isNaN(commitCount) || commitCount <= 0)) {
+  die(`  ✗ Invalid --commits value: must be a positive integer`);
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/agent.ts` at line 18, The assignment to commitCount using
parseInt(values.commits, 10) can produce NaN for non-numeric inputs; update the
parsing in demo/ctx/agent.ts to validate values.commits before assigning
commitCount (e.g., check /^\d+$/ or use parseInt then guard with
Number.isFinite/Number.isInteger), and if invalid return a clear error or
fallback to null; specifically adjust the code around the commitCount variable
(referencing commitCount and values.commits) to perform the validation and
handle non-numeric input gracefully.
demo/ctx/src/ui.ts (1)

83-83: Unused variable hr.

The hr variable is declared but never used in the function.

🧹 Proposed fix
-  const hr = `${D}${"─".repeat(WIDTH)}${R}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/src/ui.ts` at line 83, The constant hr (`const hr =
`${D}${"─".repeat(WIDTH)}${R}``) is declared but never used; either remove this
declaration or use `hr` where a horizontal rule was intended (replace the
appropriate string concatenation or console output with `hr`), referencing the
`hr` declaration and the related symbols D, R, and WIDTH when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demo/ctx/README.md`:
- Around line 244-245: Update the README instructions so the git clone points to
the lingo.dev monorepo and the working directory and install commands reflect
the demo location and bun usage: replace the existing "git clone
https://github.com/bhavya031/ctx" and "cd ctx" with "git clone
https://github.com/lingodotdev/lingo.dev" and "cd lingo.dev/demo/ctx", and
change the subsequent install/link steps to use "bun install" and "bun link"
instead of npm—ensure these updates are applied in the same section that
currently contains the git clone and cd commands.

---

Duplicate comments:
In `@demo/ctx/README.md`:
- Around line 244-248: Update the install command block in the README to use
Node/npm instead of Bun: replace the lines "bun install" and "bun link" with
"npm install" and "npm link" (the fenced code block that currently shows git
clone, cd ctx, bun install, bun link), ensuring the commands align with
package.json/tsx usage and the README's Node.js requirements.

---

Nitpick comments:
In `@demo/ctx/agent.ts`:
- Line 18: The assignment to commitCount using parseInt(values.commits, 10) can
produce NaN for non-numeric inputs; update the parsing in demo/ctx/agent.ts to
validate values.commits before assigning commitCount (e.g., check /^\d+$/ or use
parseInt then guard with Number.isFinite/Number.isInteger), and if invalid
return a clear error or fallback to null; specifically adjust the code around
the commitCount variable (referencing commitCount and values.commits) to perform
the validation and handle non-numeric input gracefully.

In `@demo/ctx/src/jsonc.ts`:
- Around line 51-65: The loop that writes lines only removes a single preceding
CTX comment before inserting a new one, so change the logic in the for-loop that
iterates over lines (the block using keyMatch, indent, key, and result) to pop
all consecutive CTX comment lines instead of one: replace the single if
(result.length > 0 && result[result.length - 1].trimStart().startsWith("//
CTX:")) result.pop(); with a loop that continues popping while result is
non-empty and the last element trimmed startsWith("// CTX:"), then proceed to
push the new comment from comments[key] and the current line; this ensures
multi-line or repeated "// CTX:" lines are fully removed before inserting the
updated comment.

In `@demo/ctx/src/ui.ts`:
- Line 83: The constant hr (`const hr = `${D}${"─".repeat(WIDTH)}${R}``) is
declared but never used; either remove this declaration or use `hr` where a
horizontal rule was intended (replace the appropriate string concatenation or
console output with `hr`), referencing the `hr` declaration and the related
symbols D, R, and WIDTH when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0625f495-f43a-4844-9ce9-ffdf1d04e13a

📥 Commits

Reviewing files that changed from the base of the PR and between a3c3c5a and 674652e.

📒 Files selected for processing (12)
  • demo/ctx/README.md
  • demo/ctx/agent.ts
  • demo/ctx/package.json
  • demo/ctx/src/agent-loop.ts
  • demo/ctx/src/cli.ts
  • demo/ctx/src/files.ts
  • demo/ctx/src/i18n.ts
  • demo/ctx/src/jsonc.ts
  • demo/ctx/src/research.ts
  • demo/ctx/src/state.ts
  • demo/ctx/src/ui.ts
  • demo/ctx/src/voices.ts
✅ Files skipped from review due to trivial changes (2)
  • demo/ctx/package.json
  • demo/ctx/src/voices.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • demo/ctx/src/cli.ts
  • demo/ctx/src/research.ts
  • demo/ctx/src/files.ts
  • demo/ctx/src/i18n.ts
  • demo/ctx/src/agent-loop.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
demo/ctx/README.md (1)

241-248: ⚠️ Potential issue | 🟡 Minor

Resolve mixed setup instructions (Node/tsx requirements vs Bun commands).

Line 241 says Node.js + tsx, but Lines 246-247 require bun install/bun link. Please make runtime/package-manager guidance consistent in one path (or explicitly document both paths).

🛠️ Proposed doc fix (single Node.js path)
 ```bash
 git clone https://github.com/lingodotdev/lingo.dev
 cd lingo.dev/demo/ctx
-bun install
-bun link
+npm install
+npm link
</details>

  

```shell
#!/bin/bash
# Verify actual runtime/tooling used by demo/ctx without executing project code.
set -euo pipefail

echo "== README install/requirements snippets =="
sed -n '236,252p' demo/ctx/README.md

echo
echo "== demo/ctx package metadata (scripts + packageManager + engines) =="
cat demo/ctx/package.json | sed -n '1,220p'

echo
echo "== Search for bun/tsx usage in demo/ctx =="
rg -n --type=json --type=md --type=ts --type=js '\bbun\b|\btsx\b' demo/ctx README.md
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/README.md` around lines 241 - 248, The README's install instructions
mix Node/tsx requirements with Bun commands (mentions "Node.js (with tsx)" but
shows "bun install" / "bun link"); make them consistent by choosing one path or
explicitly documenting both. If sticking with Node, replace the "bun install"
and "bun link" steps with the equivalent "npm install" and "npm link" and ensure
the README's requirements line matches; if supporting both, add two clearly
labeled sections ("Node (npm)" and "Bun") showing the exact commands for each.
Also verify the chosen path matches the project's package metadata (package.json
packageManager, scripts, and any tsx usage) and update the README accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demo/ctx/README.md`:
- Line 61: Several fenced code blocks in demo/ctx/README.md are missing language
identifiers, causing markdownlint MD040 warnings; update each triple-backtick
fence (examples shown around snippets like "your lingo.dev project", "ctx 
/your-project", "✓  No new changes (uncommitted) — context is up to date.", "◆ 
Brand Voices", "ctx run", and the review block starting with "┌─ Review:
lingo-context.md") by adding an appropriate language tag (e.g., text, bash,
jsonc) immediately after the opening ``` so every fenced code block has a
language identifier and the lint warnings are cleared.

---

Duplicate comments:
In `@demo/ctx/README.md`:
- Around line 241-248: The README's install instructions mix Node/tsx
requirements with Bun commands (mentions "Node.js (with tsx)" but shows "bun
install" / "bun link"); make them consistent by choosing one path or explicitly
documenting both. If sticking with Node, replace the "bun install" and "bun
link" steps with the equivalent "npm install" and "npm link" and ensure the
README's requirements line matches; if supporting both, add two clearly labeled
sections ("Node (npm)" and "Bun") showing the exact commands for each. Also
verify the chosen path matches the project's package metadata (package.json
packageManager, scripts, and any tsx usage) and update the README accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc4e9f39-db30-4d3b-8ca7-4399982e6bbb

📥 Commits

Reviewing files that changed from the base of the PR and between 674652e and 306d6c9.

📒 Files selected for processing (1)
  • demo/ctx/README.md


## How It Works

```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks to satisfy markdownlint (MD040).

These fences are missing language tags. Please annotate them (text, bash, jsonc, etc.) to clear lint warnings.

🧩 Example patch
-```
+```text
 your lingo.dev project
 ...
-```
+```

-```
+```text
   ctx  /your-project
 ...
-```
+```

-```
+```text
   ctx  /your-project
 ...
-```
+```

-```
+```text
   ✓  No new changes (uncommitted) — context is up to date.
 ...
-```
+```

-```
+```text
   ◆  Brand Voices
 ...
-```
+```

-```
+```text
 ctx run
 ...
-```
+```

-```
+```text
   ┌─ Review: lingo-context.md ──────────────────────────────┐
 ...
-```
+```

Also applies to: 90-90, 134-134, 156-156, 164-164, 202-202, 326-326

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 61-61: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/ctx/README.md` at line 61, Several fenced code blocks in
demo/ctx/README.md are missing language identifiers, causing markdownlint MD040
warnings; update each triple-backtick fence (examples shown around snippets like
"your lingo.dev project", "ctx  /your-project", "✓  No new changes (uncommitted)
— context is up to date.", "◆  Brand Voices", "ctx run", and the review block
starting with "┌─ Review: lingo-context.md") by adding an appropriate language
tag (e.g., text, bash, jsonc) immediately after the opening ``` so every fenced
code block has a language identifier and the lint warnings are cleared.

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.

Proposal: Add CTX AI context engine to lingo.dev

1 participant