Documentation
¶
Index ¶
Constants ¶
const ( VisibilityAlways = "always" VisibilityIndexed = "indexed" VisibilityHidden = "hidden" )
Visibility levels control how docs are disclosed to agents during prime.
Progressive disclosure model (inspired by Agent Skills spec):
- "always" — content auto-inlined into prime output. Reserved for future use; intended for small, universally-needed docs (<200 tokens) like glossaries. Not yet implemented — accepted as a valid value but treated as "indexed" for now.
- "indexed" — listed in catalog with title + description + when triggers. Agent reads full content on demand when task matches. This is the default.
- "hidden" — not visible to agents at all. Use for human-only docs, drafts, meeting notes, or directory instructions (like README.md).
const ( RuleStatusActive = "active" RuleStatusDraft = "draft" // RuleStatusSupersededPrefix is matched as a prefix on status values like // "superseded-by:<other-rule-name>". RuleStatusSupersededPrefix = "superseded-by:" )
Rule status values.
const ( RuleAudienceAI = "ai" RuleAudienceHuman = "human" RuleAudienceBoth = "both" )
Rule audience values.
const DefaultRuleAudience = RuleAudienceAI
DefaultRuleAudience is what's assumed when frontmatter omits the field.
const DefaultRuleVisibility = VisibilityIndexed
DefaultRuleVisibility is what's assumed when frontmatter omits the field. "indexed" — much closer to Claude's paths-deferred lazy loading than "always" is. Loading every team rule into prime would silently bloat context as the rule library grows; opting in to "always" forces teams to think about cost.
const DefaultVisibility = VisibilityIndexed
DefaultVisibility is the visibility applied when frontmatter omits the field. Docs in team context docs/ are visible by default — the whole point of the directory is sharing knowledge with the team, including AI coworkers.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type TeamDoc ¶
type TeamDoc struct {
Name string `json:"name"` // filename (e.g., "principles.md")
Title string `json:"title"` // from frontmatter or first H1 heading
Description string `json:"description,omitempty"` // one-line summary for catalog
Path string `json:"path"` // absolute path — agent reads on demand
When string `json:"when,omitempty"` // natural language triggers for when to read
Visibility string `json:"visibility"` // always | indexed | hidden
}
TeamDoc represents a single team document discovered from the docs/ directory within a team context. These docs are cataloged during ox agent prime so agents know what's available and when to read each document on demand.
func DiscoverDocs ¶
DiscoverDocs scans the docs/ directory in a team context for markdown files and returns a catalog of documents visible to agents.
Only .md files are processed. Rationale:
- Agents read markdown natively — no conversion tooling needed
- YAML frontmatter is a markdown convention with universal tooling support (Jekyll, Hugo, Obsidian, VS Code, Agent Skills spec)
- Token estimation is trivial for text content
- Non-markdown assets (images, PDFs, data files) need entirely different disclosure mechanisms and are out of scope for this catalog
README.md is always excluded — it contains instructions about the directory itself, not content for agents. Server-side hardcodes this as hidden.
Returns only docs with visibility != "hidden". Sorted by filename for stable, deterministic output.
type TeamRule ¶ added in v0.8.0
type TeamRule struct {
Name string `json:"name"` // kebab-case identifier; from frontmatter or filename
Description string `json:"description,omitempty"` // one-line summary
RelPath string `json:"rel_path"` // path relative to rules root (e.g., "backend/postgres.md")
AbsPath string `json:"abs_path"` // absolute path on disk
Repos []string `json:"repos,omitempty"` // repo filter; empty = all team repos
Audience string `json:"audience,omitempty"` // "ai" | "human" | "both" (default: "ai")
Visibility string `json:"visibility"` // "always" | "indexed" | "hidden"
Status string `json:"status,omitempty"` // "active" | "draft" | "superseded-by:<other>"
FromDiscussion string `json:"from_discussion,omitempty"` // optional provenance link
Body string `json:"body,omitempty"` // markdown body (excluding frontmatter); only populated for visibility=always
EstimatedTokens int `json:"estimated_tokens,omitempty"` // rough estimate (len(body)/4); only set when Body is loaded
}
TeamRule represents a single team-context behavioral rule discovered under agents/rules/ (preferred) or coworkers/rules/ (legacy fallback).
Team rules apply to every supported AI coding agent (Claude, Codex, Amp, Cursor, etc.) used by teammates running ox. They are the team-scope cousin of Claude's .claude/rules/<topic>.md — modular, one concern per file, and loaded into agent context via ox agent prime.
Subdirectories under agents/rules/ are walked recursively. The relative path is preserved so organization (e.g., backend/postgres.md) stays meaningful for navigation and dedupe.
func DiscoverRules ¶ added in v0.8.0
DiscoverRules walks the team context for behavioral rule files under agents/rules/**/*.md (preferred) and coworkers/rules/**/*.md (legacy fallback for any teams that adopted that location early). Subdirectories are walked recursively, mirroring how Claude Code walks .claude/rules/.
Rules with audience: human are excluded (this scanner is for agent consumption). Rules with status: draft and visibility: hidden are excluded. Rules with status starting with superseded-by: are excluded.
If repoSlug is non-empty, rules with a non-empty repos: list that does NOT contain repoSlug are excluded. Empty/absent repos: means the rule applies to all team repos.
For visibility: always rules, the markdown body (excluding frontmatter) is loaded into TeamRule.Body so the prime emitter can inline it. For indexed rules, only metadata is returned; the agent reads the file on demand from AbsPath.
Results are sorted by RelPath for stable output.
TODO(sync-out): A future daemon-driven optimization could sync filtered, repo-scoped team rules OUT of team context and into each cloned repo's agent-native rules directory (e.g., .claude/sageox-team-<slug>/rules/ for Claude, .cursor/rules/sageox-team-<slug>/ for Cursor). That would let team rules participate in the agent's NATIVE rule-loading machinery (Claude's `paths:`-scoped lazy loading, Cursor's `globs:` matching, etc.) instead of being delivered up front via prime XML.
Implementation considerations when picking this up:
Adapter dispatch — each agent has its own rules dir convention. The pkg/adapterprotocol RulesParams + handleInstallRules pattern already abstracts this (cmd/ox-adapter-claude-code/rules.go is the reference implementation). Sync-out would extend the rule file list passed to handleInstallRules with discovered team rules.
Namespace — write to a sageox-team-<slug>/ subdirectory under the agent's rules dir, never directly into .claude/rules/ root, to avoid colliding with project-local rules of the same name and to make cleanup unambiguous.
Lifecycle — daemon writes on team-context sync (after pull), and on repo-open. Daemon removes files for rules that disappear from team context (true mirror, not append-only). At prime time the sync state is read-only.
Filtering — apply the same repos:/audience:/status: filters here that DiscoverRules already applies, so a teammate working in repo A doesn't get repo B's rules synced into their working tree.
Multi-adapter coverage — today only ox-adapter-claude-code and ox-adapter-droid implement handleInstallRules. Other adapters (codex, amp, aider, gemini, opencode, pi) need rules.go before they can participate. Tracking the gap is the prerequisite for a uniform sync-out story.
Per-user knowledge bubble — when the user-context bubble lands, sync-out for user rules has the same shape but reads from the user-context location and tags entries with audience: ai, source: user (so the budget accounting in agent_prime_xml.go attributes them correctly to BudgetSourceUser).
Not implemented yet; this comment IS the design memo until someone picks up the work.