Skip to content

feat(add-agent): opt-in --custom flag for non-catalog role names#28

Merged
nmelo merged 1 commit into
mainfrom
claude/add-agent-custom-flag
May 19, 2026
Merged

feat(add-agent): opt-in --custom flag for non-catalog role names#28
nmelo merged 1 commit into
mainfrom
claude/add-agent-custom-flag

Conversation

@nmelo
Copy link
Copy Markdown
Owner

@nmelo nmelo commented May 19, 2026

Summary

The roles package documents itself as an open set: unknown role names are valid and receive sensible defaults. LookupRole("designer") correctly returns a bare default RoleDef, and TestLookupRole_Unknown locks that contract in. But the CLI gate in add-agent rejects every non-catalog name, contradicting the open-set claim. The current validator (IsValidRoleName) acknowledges the gap in its own doc comment and explicitly scopes the fix out:

Operators wanting truly custom roles must add them to the Catalog or design a separate opt-in (out of scope here).

This PR adds that opt-in.

What changed

  • New flag --custom on initech add-agent. When set, names outside the catalog and numbered families go through a new pattern check rather than the closed-set check.
  • New roles.IsValidCustomRoleName — pure pattern validator: ^[a-z][a-z0-9-]{0,31}$. Lowercase letter start, then up to 31 lowercase letters / digits / hyphens. Hyphens not underscores, consistent with the catalog's own naming. URL- and filesystem-friendly.
  • IsValidRoleName is unchanged. Default behavior is unchanged. Typo protection is preserved for callers who do not opt in.
  • The error message on unknown roles now hints at --custom.

Custom roles flow through LookupRole's existing bare-default branch (Autonomous, no src, no playbooks), so no scaffold or runtime changes are needed.

Why

Initech is being used outside pure software-engineering org shapes. The motivating use case is a marketing fleet (content, demandgen, events, community) but the same gap blocks any non-software vocabulary: design teams, DBAs, sec-ops, customer success, etc. The previous workaround was either to misuse eng4/qa10 slots or to fork initech and edit the catalog. Both are bad.

Backward compatibility

  • Default behavior unchanged: initech add-agent designer still rejects with unknown agent. The new error message adds a hint about --custom.
  • No catalog changes. No template changes. No scaffold or TUI changes.
  • IsValidRoleName semantics unchanged. New callers can opt in to IsValidCustomRoleName as a sibling.

Regression tests

Three new tests in cmd/add_agent_test.go:

  • TestRunAddAgent_CustomFlag_AllowsArbitraryNamemarketing is accepted with --custom and the role lands in initech.yaml and on disk.
  • TestRunAddAgent_CustomFlag_RejectsBadIdentifier — uppercase, leading digits, underscores, dots, and whitespace are rejected with a clear pattern error.
  • TestRunAddAgent_WithoutCustomFlag_StillRejectsUnknown — locks in that --custom is strictly opt-in. Also extends TestRunAddAgent_UnknownRole to require the --custom hint in the error message.

One new table test in internal/roles/catalog_test.go:

  • TestIsValidCustomRoleName_AcceptsAndRejects — pure unit coverage on the pattern (marketing, designer, dba, data-eng accepted; uppercase, leading digits, underscores, whitespace, 33-char names rejected; 32-char boundary accepted).

Note on the "fail on main" requirement: this is a feature-add PR, not a fix-the-broken-code PR. The new tests reference symbols that do not exist on main (addAgentCustom flag, IsValidCustomRoleName function), so checking out main and running them produces a compile failure rather than a runtime failure. The semantic regression they protect against — add-agent rejecting valid custom names that LookupRole already supports — is locked in by the existence of the tests at all.

Test plan

  • make check passes clean (vet + lint-test-names + test, 14 packages).
  • go test ./cmd/ -run 'TestRunAddAgent_(Custom|Unknown|WithoutCustom)' -v passes (5 new subtests + the existing TestRunAddAgent_UnknownRole).
  • go test ./internal/roles/ -run TestIsValidCustomRoleName -v passes.
  • Existing test suite unchanged in behavior (no regressions).

How to use

# Existing behavior, unchanged:
initech add-agent eng1            # ok
initech add-agent qa10            # ok (numbered family)
initech add-agent designer        # error: unknown agent. Hint about --custom.

# New behavior:
initech add-agent --custom designer    # ok
initech add-agent --custom data-eng    # ok
initech add-agent --custom Designer    # error: invalid custom role name (uppercase)
initech add-agent --custom 1designer   # error: invalid custom role name (leading digit)

Summary by CodeRabbit

New Features

  • Added --custom flag to the add-agent command, enabling users to add custom roles outside the predefined catalog. Custom role names must follow a naming pattern: start with a lowercase letter and contain only lowercase letters, digits, or hyphens (maximum 32 characters).

Review Change Stack

The roles package documents itself as an open set ("unknown role names
are valid and receive sensible defaults") and LookupRole correctly
returns defaults for arbitrary names. But IsValidRoleName at the CLI
gated add-agent to the catalog + numbered families, and its own doc
comment scoped the fix out: "Operators wanting truly custom roles must
add them to the Catalog or design a separate opt-in (out of scope here)."

This adds that opt-in. add-agent now accepts a --custom flag. When set,
names outside the catalog go through IsValidCustomRoleName, a pure
pattern check requiring ^[a-z][a-z0-9-]{0,31}$. The default closed-set
gate stays intact for typo protection. Custom roles get the bare default
RoleDef (Autonomous, no src, no playbooks) via LookupRole's existing
fallback, so no scaffold or runtime changes are needed.

Motivated by adding marketing-shaped roles (content, demandgen, events,
community) to a non-software project. The same opt-in lets future users
register designer, dba, or any other vocabulary their team needs.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds opt-in support for custom role names in the add-agent command via a new --custom CLI flag. The validation logic accepts custom names following a lowercase-start, alphanumeric-hyphen pattern with comprehensive tests covering both valid custom roles and rejection of invalid identifiers while maintaining backward compatibility.

Changes

Custom Role Name Support via --custom Flag

Layer / File(s) Summary
Custom role name validation contract
internal/roles/catalog.go, internal/roles/catalog_test.go
A new customRoleNameRe regex pattern defines valid custom role identifiers (lowercase start, letters/digits/hyphens, max 32 chars). The exported IsValidCustomRoleName function validates against this pattern. IsValidRoleName documentation clarifies it gates only catalog and numbered-family roles, directing callers to the new function for custom role opt-in. Tests exercise both accepted custom names and rejected edge cases (empty, uppercase, invalid punctuation, boundary length).
CLI flag integration and help text
cmd/add_agent.go
The addAgentCustom boolean flag variable tracks whether --custom was provided. The add-agent command help text is extended with usage instructions and naming constraints for non-catalog roles.
Runtime validation with conditional custom role support
cmd/add_agent.go, cmd/add_agent_test.go
When a role name is not found in the catalog, validation conditionally accepts it if --custom is enabled and the name passes IsValidCustomRoleName, or rejects it with a hint to pass --custom. Tests verify custom role creation succeeds with scaffold and config updates, invalid custom names are rejected with appropriate errors, and backward-compatible behavior is maintained when --custom is absent.

Sequence Diagram(s)

N/A — The changes are primarily validation logic and flag integration without multi-component request/response flows warranting a sequence diagram.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A custom role now finds its way,
With --custom flag to save the day,
The regex guards what names are right,
From marketing to flagged delight,
Old roles still thrive, no breaking light! 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% 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 summarizes the main change: adding an opt-in --custom flag to the add-agent command for non-catalog role names. It is concise, specific, and directly reflects the primary feature being introduced.
Description check ✅ Passed The description comprehensively covers the motivation (supporting non-software vocabularies), implementation details (--custom flag, IsValidCustomRoleName pattern), backward compatibility assurances, and detailed regression tests with clear test plan validation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/add-agent-custom-flag

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.

@nmelo nmelo merged commit 90400bb into main May 19, 2026
3 of 4 checks passed
@nmelo nmelo deleted the claude/add-agent-custom-flag branch May 19, 2026 18:57
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