Skip to content

feat(dir-add): scaffold agent.yaml + body-only AGENTS.md (wish dir-sync-frontmatter-refresh group 5) - #1198

Merged
namastex888 merged 1 commit into
devfrom
feat/dir-sync-frontmatter-refresh-group5
Apr 18, 2026
Merged

namastex888 merged 1 commit into
devfrom
feat/dir-sync-frontmatter-refresh-group5

Conversation

@automagik-genie

Copy link
Copy Markdown
Contributor

Wave 3 / Group 5 of wish `dir-sync-frontmatter-refresh`. Depends on Groups 1-4 (all on dev).

Behavior change

`genie dir add ` now scaffolds BOTH files on disk:

  • `agents//agent.yaml` — all CLI flags collapsed into a clean AgentConfig, written atomically via `writeAgentYaml` (lock-protected).
  • `agents//AGENTS.md` — frontmatter-less template starting with `# Agent: `, includes a `TBD` placeholder.

Then triggers `syncSingleAgentByName` (from G3/G4) so the DB row materializes from the yaml. Read-after-write consistent.

Code

`src/term-commands/dir.ts` — rewrote `handleDirAdd`:

  • `mkdirSync(resolvedDir, { recursive: true })` ensures the folder.
  • `scaffoldAgentsMdBody(name)` inline template (no YAML fence).
  • `writeAgentYaml` + `syncSingleAgentByName` replace the direct `directory.add` call.
  • Workspace-less fallback: still calls `directory.add` for the stub + warns the user to re-sync in a workspace.

Tests

`src/term-commands/dir-add.test.ts` (new, 6 cases):

  • creates both `agent.yaml` and `AGENTS.md`
  • `AGENTS.md.slice(0, 3) !== '---'` — wish acceptance criterion verified
  • `agent.yaml` parses cleanly; `--model` value present
  • DB directory entry has matching `model`
  • `--permission-preset` + `--allow` flatten into nested `permissions.*` yaml + DB
  • idempotency of the write-then-sync cycle

Test plan

  • `bun test src/term-commands/dir-add.test.ts` → 6 pass, 0 fail
  • `bun run typecheck` clean
  • `bunx knip` clean
  • Pre-push full suite: 2704 pass, 0 fail
  • CI Quality Gate green

🤖 Generated with Claude Code

…nc-frontmatter-refresh group 5)

Wave 3 / Group 5. `genie dir add <name>` now scaffolds BOTH files on
disk — `agent.yaml` (runtime config from CLI flags) and a
frontmatter-less `AGENTS.md` (pure prompt content from line 1) — then
syncs the DB row from the yaml via the same single-agent path as
`dir edit` from Group 4.

Behavior:
- `mkdirSync(agentDir, { recursive: true })` creates the folder.
- `AGENTS.md` is scaffolded from an inline template that starts with
  `# Agent: <name>` — no `---` fence. The template includes a
  `<mission>TBD</mission>` placeholder to prompt the user.
- `writeAgentYaml(join(dir, 'agent.yaml'), config)` writes the config
  atomically via the lockfile from Group 1.
- `syncSingleAgentByName(ws.root, name)` upserts the DB row via the
  G3 sync path so `dir add` is read-after-write consistent.
- If not in a workspace: fall back to `directory.add` so the row
  still registers; print a warning suggesting `genie dir sync`.

Tests (`src/term-commands/dir-add.test.ts` — new, 6 cases):

- creates both `agent.yaml` and `AGENTS.md`
- `AGENTS.md.slice(0, 3) !== '---'` (no frontmatter fence)
- `agent.yaml` parses cleanly; `--model` value lands inside
- DB directory entry has matching `model`
- `--permission-preset` + `--allow` flatten into `permissions.*`
  nested yaml + DB
- re-writing agent.yaml and re-syncing produces the new state in DB
  (idempotency of the write-then-sync cycle)

No direct `sql\`INSERT INTO agent_templates\`` calls in the add
handler path anymore; the DB projection flows from the yaml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8279b439-8338-4a40-a11f-4b0561ec8c99

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dir-sync-frontmatter-refresh-group5

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.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request updates the genie dir add command to scaffold both an agent.yaml configuration file and a frontmatter-less AGENTS.md file, followed by a database sync. It also adds comprehensive integration tests for this new behavior. Review feedback identifies a risk of overwriting existing agent configurations without a prior check and a bug in the workspace detection logic that fails to correctly register agents using custom directory paths.

Comment thread src/term-commands/dir.ts
// canonical source of every runtime-consumed field; AGENTS.md holds pure
// prompt content from line 1.

const promptMode = validatePromptMode(options.promptMode);

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.

high

The handleDirAdd function should check if an agent with the same name already exists in the directory before scaffolding files. Currently, it proceeds to create directories and overwrite agent.yaml even if the agent is already registered in the database, which can lead to accidental loss of existing configuration.

Suggested change
const promptMode = validatePromptMode(options.promptMode);
const existing = await directory.resolve(name);
if (existing && !existing.builtin) {
throw new Error("Agent " + name + " already exists. Use 'genie dir edit' to update or 'genie dir rm' first.");
}
const promptMode = validatePromptMode(options.promptMode);

Comment thread src/term-commands/dir.ts
Comment on lines +223 to +243
const ws = findWorkspace();
if (ws) {
await syncSingleAgentByName(ws.root, name);
} else {
// Not in a workspace — register a stub in the directory table so the
// agent is reachable even before the user runs `genie init`.
await directory.add(
{
name,
dir: resolvedDir,
repo: options.repo ? resolvePath(options.repo) : undefined,
promptMode,
model: options.model,
roles: normalizeRoles(options.roles),
...(permissions && { permissions }),
...(sdk && { sdk }),
},
{ global: options.global },
);
console.warn('Not in a genie workspace — directory row created; run `genie dir sync` in a workspace to re-sync.');
}

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.

high

There is a bug in the workspace detection logic: syncSingleAgentByName only works for agents located in the standard {workspace}/agents/{name} directory. If a user provides a custom path via --dir, syncSingleAgentByName will return 'not-found' and the agent will not be registered in the database, even though the CLI reports success. The logic should fall back to directory.add for non-standard paths to ensure the agent is correctly registered in the database.

  const ws = findWorkspace();
  const isStandardPath = ws && resolvedDir === resolvePath(join(ws.root, 'agents', name));

  if (isStandardPath) {
    await syncSingleAgentByName(ws.root, name);
  } else {
    // Not in a workspace or using a custom directory — register via directory.add
    // to ensure the DB row exists with the correct path.
    await directory.add(
      {
        name,
        dir: resolvedDir,
        repo: options.repo ? resolvePath(options.repo) : undefined,
        promptMode,
        model: options.model,
        roles: normalizeRoles(options.roles),
        ...(permissions && { permissions }),
        ...(sdk && { sdk }),
      },
      { global: options.global },
    );
    if (!ws) {
      console.warn("Not in a genie workspace — directory row created; run genie dir sync in a workspace to re-sync.");
    }
  }

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b523f293e2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/term-commands/dir.ts
const scope = options.global ? 'global' : 'project';
console.log(`Agent "${entry.name}" registered (${scope}).`);
printEntry(entry);
console.log(`Agent "${name}" registered (${scope}).`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Check sync outcome before declaring registration success

This path always prints Agent "..." registered even when the workspace sync does not register anything. In workspace mode, syncSingleAgentByName(ws.root, name) can return not-found (for example when --dir is not exactly {workspace}/agents/{name}), but the command still emits a success message and continues, leaving no corresponding directory row. Please gate the success output on the sync action (or fall back to directory.add) so users do not get false-positive registration results.

Useful? React with 👍 / 👎.

Comment thread src/term-commands/dir.ts
// Propagate to the DB via the same single-agent sync path used by `dir edit`.
const ws = findWorkspace();
if (ws) {
await syncSingleAgentByName(ws.root, name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve --repo when syncing newly added workspace agents

In the workspace branch, registration goes through syncSingleAgentByName instead of directory.add, which means the persisted repo comes from sync discovery (git remote/agent dir) rather than the CLI --repo value written into config. As a result, genie dir add <name> --repo <path> no longer reliably stores the requested repo for workspace users, which is a behavior regression from the previous direct directory.add flow.

Useful? React with 👍 / 👎.

@namastex888
namastex888 merged commit c70d1c3 into dev Apr 18, 2026
6 checks passed
@automagik-genie
automagik-genie deleted the feat/dir-sync-frontmatter-refresh-group5 branch September 25, 2026 04:49
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.

2 participants