Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ lets publish-docs # deploy docs site

`lets test-unit`, `lets test-bats`, and `lets lint` require Docker. Use `go test ./...` locally for quick iteration without Docker.

## Agent skills

### Issue tracker

The Issue tracker for this repo is GitHub; work items live as GitHub Issues in `lets-cli/lets`. See `docs/agents/issue-tracker.md`.

### Triage labels

Triage uses the default Triage label names: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, and `wontfix`. See `docs/agents/triage-labels.md`.

### Domain docs

This is a Single-context repo; skills should read the root Context and root ADRs. See `docs/agents/domain.md`.

## Agent Behavior

- **Proactive execution** — Don't ask "Can I proceed?" for implementation. DO ask before changing success criteria, test thresholds, or what "working" means.
Expand Down
101 changes: 101 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Context

This is a single-context repo.

## Purpose

`lets` is a YAML-based CLI task runner. A repository defines project workflow in `lets.yaml`, and `lets` turns that declaration into runnable **Project commands**, built-in **Self commands**, help output, shell completion, and editor tooling. In marketing copy "task runner" is fine; in precise product language prefer **Project command** to "task".

## Language choices

- Use **Settings** for `~/.config/lets/config.yaml`.
- Use **Project config** for `lets.yaml`.
- Use **Project command** for a user-defined runnable unit.
- Use **Self command** for `lets self ...` functionality.
- Use **Theme** for user-facing output styling; reserve "color scheme" for implementation details.

## Configuration model

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Project config** | The repository-level declaration in `lets.yaml` that defines commands and shared execution rules. | Settings, user config |
| **Settings** | Per-user lets behavior stored in `~/.config/lets/config.yaml`. | Project config |
| **Mixin** | An additional config file merged additively into a Project config. | Override, patch |
| **Global env** | Top-level environment entries shared by all Project commands. | Process env |
| **Env file** | A dotenv-style file loaded into command execution at global or command scope. | Settings file, config file |
| **Theme** | A named style for lets help and styled error output. | Color scheme, palette |

## Command model

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Project command** | A named runnable unit declared under `commands` in Project config. | Task, job |
| **Self command** | A built-in `lets self ...` command used to manage lets itself. | Project command |
| **Option** | A docopt-declared CLI input for a Project command. | Cobra flag, raw env var |
| **Dependency chain** | The ordered graph of Project commands reached through `depends`. | Pipeline, hook |
| **Reference command** | A Project command that reuses another command via `ref` and optional `args`. | Alias |
| **Command group** | A help-only label used to organize Project commands in rendered help. | Execution stage |
| **Environment** | The fully resolved environment passed to Project command execution. | Process env |
| **Checksum** | A SHA1 digest derived from configured files and exposed as environment variables. | Cache key |
| **Persisted checksum** | Stored checksum state used to detect change between invocations. | Build cache |

## Execution model

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Init script** | A top-level script run once per lets invocation before the first Project command executes. | Before script |
| **Before script** | A top-level script prepended to each Project command invocation, including dependencies. | Init script |
| **After script** | A command-scoped script run after a Project command execution attempt. | Cleanup hook |
| **Work dir** | The directory where a Project command runs after config and command resolution. | Repo root |
| **Help surface** | The rendered CLI help for root and Project commands. | Docs page |
| **LSP surface** | The editor-facing language-server features exposed by `lets self lsp`. | CLI help |

## Relationships

- One **Project config** defines zero or more **Project commands**.
- A **Project command** inherits shell and shared execution rules from **Project config** unless it overrides them.
- A **Dependency chain** contains only **Project commands**; **Self commands** are outside that graph.
- A **Reference command** points to exactly one target **Project command**.
- An **Option** parsed for a **Project command** is exposed as `LETSOPT_*` and `LETSCLI_*` variables in the command **Environment**.
- A **Checksum** belongs to one **Project command** and may expose one aggregate digest plus named digests.
- **Settings** affect lets itself, while **Project config** affects repository workflow.
- **Mixins** add commands, env, before scripts, and env files; conflicting names are errors rather than implicit overrides.
- A **Command group** changes help organization only; it does not change execution behavior.

## Execution flow

1. Discover **Project config** from `--config`, `LETS_CONFIG`, or upward search for `lets.yaml`.
2. Load **Mixins** and merge them into one effective **Project config**.
3. Validate config structure, supported keywords, version requirements, references, and dependency graph.
4. Build CLI surfaces from **Project commands** plus built-in **Self commands**.
5. Parse **Option** values with docopt and expose them to the command **Environment**.
6. Resolve **Environment** from built-in lets vars, config env, env files, parsed options, explicit overrides, and checksum vars.
7. Run the **Init script** once per invocation.
8. Execute the **Dependency chain** before the requested **Project command**.
9. Run Project command scripts in the selected shell and **Work dir**.
10. Run the **After script** after the execution attempt; its own failure does not replace the main command result.
11. Persist **Persisted checksum** state only after successful execution.

## Precedence and boundaries

- **Settings** precedence is: environment variables > settings file > built-in defaults.
- **Environment** precedence at command runtime is: process env < built-in lets vars < global `env` < global `env_file` < command `env` < command `env_file` < parsed options / explicit env overrides / checksum vars.
- `NO_COLOR` disables color even if **Settings** choose a **Theme**.
- A **Theme** affects lets output itself, not the child processes launched by **Project commands**.
- **Project config** must declare `shell`; **Mixins** do not.
- `persist_checksum` is valid only when `checksum` is declared.
- Unknown top-level keywords fail config loading unless they use the `x-` prefix for custom extensions.
- **Agent skills** are installed and managed with `lets self skills`; they are not configured in **Project config**.

## Non-goals

- `lets` orchestrates shell commands; it does not replace the shell itself.
- `lets` is not a package manager.
- **Settings** are not a place to share repository workflow.
- **Self commands** are not part of a repository's **Project command** namespace.
- **Mixins** are additive composition, not implicit override layers.

## Related docs

- `UBIQUITOUS_LANGUAGE.md` is the working glossary and ambiguity log.
- Promote stable terminology from `UBIQUITOUS_LANGUAGE.md` into this file when it becomes durable project language.
76 changes: 76 additions & 0 deletions UBIQUITOUS_LANGUAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Ubiquitous Language

## Lets configuration

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Settings** | Per-user lets behavior stored in `~/.config/lets/config.yaml`. | Config, `lets.yaml`, project config |
| **Project config** | Repository command and runtime configuration stored in `lets.yaml`. | Settings, user config |
| **Theme** | A named visual style for lets help and styled error output. | Color scheme, palette |
| **Default theme** | The standard lets theme. | Normal theme, builtin colors |

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.

suggestion (typo): Consider hyphenating “builtin” to “built-in” for clarity.

In the Default theme aliases, please change “builtin colors” to “built-in colors” to avoid it looking like a typo and to match common usage.

Suggested change
| **Default theme** | The standard lets theme. | Normal theme, builtin colors |
| **Default theme** | The standard lets theme. | Normal theme, built-in colors |

| **ANSI theme** | A theme limited to broadly supported ANSI terminal colors. | Plain theme, basic colors |
| **Synthwave theme** | A high-contrast neon lets theme. | Vaporwave, purple theme |

## Issue workflow

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Issue tracker** | The system of record where this repo's work items live. | Tickets, task board |
| **GitHub Issue** | A work item stored in `lets-cli/lets` on GitHub. | Local issue, scratch note |
| **Triage label** | A label string that marks an issue's triage state. | Tag, status |
| **Needs triage** | The triage state meaning a maintainer still needs to evaluate the issue. | Unreviewed, backlog |
| **Needs info** | The triage state meaning the issue is waiting on the reporter. | Blocked, pending |
| **Ready for agent** | The triage state meaning an AFK agent can execute the work without more human context. | AFK-ready, bot-ready |
| **Ready for human** | The triage state meaning the work requires human implementation. | Human-ready |
| **Won't fix** | The triage state meaning the work will not be actioned. | Rejected, closed-no-action |

## Documentation layout

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Domain docs** | The files that define project language and durable architectural decisions. | Repo docs, notes |
| **Context** | A `CONTEXT.md` file that defines the project's domain vocabulary for a scope. | Readme, design doc |
| **ADR** | An architecture decision record that captures a lasting technical decision. | Spec, random note |
| **Single-context repo** | A repo with one root `CONTEXT.md` and one root `docs/adr/`. | Monorepo, multi-context |
| **Multi-context repo** | A repo with a root `CONTEXT-MAP.md` and multiple per-context `CONTEXT.md` files. | Single-context |
| **Context map** | A root index file that points to per-context language docs. | Sitemap, overview |
| **Agent skill** | A reusable prompt-driven workflow that reads and writes repo-specific context. | Macro, script |

## People

| Term | Definition | Aliases to avoid |
| ---- | ---------- | ---------------- |
| **Maintainer** | A person who evaluates issues and applies triage labels. | Owner, reviewer |
| **Reporter** | A person who opens an issue or supplies follow-up information for it. | Submitter, user |
| **AFK agent** | An autonomous agent that can complete work without additional human context. | Bot, automation |
| **Human implementer** | A person needed when work cannot be delegated to an AFK agent. | Developer, coder |

## Relationships

- **Settings** apply to lets across all repositories, while **Project config** applies to one repository.
- A **Theme** belongs to **Settings** and is one of **Default theme**, **ANSI theme**, or **Synthwave theme**.
- A **GitHub Issue** lives in the **Issue tracker** and may have zero or more **Triage labels**.
- An issue should be **Ready for agent** only when a **Maintainer** has made it fully specified for an **AFK agent**.
- A **Single-context repo** has exactly one root **Context** and one shared root **ADR** directory.
- A **Multi-context repo** uses a **Context map** to point skills to the relevant **Context** files.

## Example dialogue

> **Dev:** "Should the new `theme` option live in **Settings** or the **Project config**?"
>
> **Domain expert:** "Put it in **Settings** — it changes lets itself, while the **Project config** in `lets.yaml` describes repo commands."
>
> **Dev:** "For this repo, does the **Issue tracker** mean **GitHub Issues** with **Triage labels**?"
>
> **Domain expert:** "Yes. A **Maintainer** evaluates each **GitHub Issue** and applies labels like **Needs triage** or **Ready for agent**."
>
> **Dev:** "And the repo is **Single-context**, so skills read one root **Context** and the root **ADR** directory?"
>
> **Domain expert:** "Exactly — no **Context map** is needed unless the repo grows into a **Multi-context repo**."

## Flagged ambiguities

- "settings" and "config" were used close together — use **Settings** for `~/.config/lets/config.yaml` and **Project config** for `lets.yaml`.
- "theme" and "color scheme" refer to the same user-facing concept here — use **Theme** in docs and CLI-facing language, and reserve "color scheme" for internal implementation details.
- "issue tracker" was used both abstractly and concretely — use **Issue tracker** for the system and **GitHub Issue** for an individual work item in this repo.
- "domain docs" was used for both the source-of-truth documents and the agent-facing instructions file — use **Domain docs** for `CONTEXT.md` and `docs/adr/`, and say "agent docs" when referring to `docs/agents/*`.
44 changes: 44 additions & 0 deletions docs/agents/domain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Domain Docs

This repo is a **Single-context repo**.

For this repo, the **Domain docs** are:

- the root **Context** at `CONTEXT.md`
- the root **ADR** directory at `docs/adr/`

`docs/agents/*` are agent docs. They describe workflow conventions for **Agent skills**, but they are not Domain docs.

## Before exploring, read these

- **`CONTEXT.md`** at the repo root
- **`docs/adr/`** at the repo root — read ADRs that touch the area you're about to work in

If these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The producer skill (`/grill-with-docs`) creates them lazily when terms or decisions actually get resolved.

## File structure

Single-context repo layout:

```
/
├── CONTEXT.md
├── docs/adr/
│ ├── 0001-some-decision.md
│ └── 0002-another-decision.md
└── src/
```

Do not expect a `CONTEXT-MAP.md` unless this repo grows into a **Multi-context repo**.

## Use the Context vocabulary

When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, or a test name), use the term as defined in the root **Context**. Don't drift to synonyms the glossary explicitly avoids.

If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/grill-with-docs`).

## Flag ADR conflicts

If your output contradicts an existing **ADR**, surface it explicitly rather than silently overriding:

> _Contradicts ADR-0007 — but worth reopening because…_
22 changes: 22 additions & 0 deletions docs/agents/issue-tracker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Issue tracker: GitHub

The **Issue tracker** for this repo is GitHub. Work items and PRDs live as **GitHub Issues** in `lets-cli/lets`. Use the `gh` CLI for all operations.

## Conventions

- **Create a GitHub Issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
- **Read a GitHub Issue**: `gh issue view <number> --comments`, and fetch labels when they matter to the workflow.
- **List GitHub Issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
- **Comment on a GitHub Issue**: `gh issue comment <number> --body "..."`
- **Apply / remove Triage labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
- **Close a GitHub Issue**: `gh issue close <number> --comment "..."`

Infer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.

## When a skill says "publish to the issue tracker"

Create a **GitHub Issue**.

## When a skill says "fetch the relevant ticket"

Fetch the relevant **GitHub Issue** with `gh issue view <number> --comments`.
13 changes: 13 additions & 0 deletions docs/agents/triage-labels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Triage Labels

This repo uses the default **Triage label** strings. The table below maps each canonical triage role to the exact GitHub label name to apply in this repo's **Issue tracker**.

| Canonical triage role | Triage label in this repo | Meaning |
| --------------------- | ------------------------- | ------- |
| `needs-triage` (**Needs triage**) | `needs-triage` | A **Maintainer** still needs to evaluate the **GitHub Issue**. |
| `needs-info` (**Needs info**) | `needs-info` | The **GitHub Issue** is waiting on the **Reporter** for more information. |
| `ready-for-agent` (**Ready for agent**) | `ready-for-agent` | The **GitHub Issue** is fully specified and ready for an **AFK agent**. |
| `ready-for-human` (**Ready for human**) | `ready-for-human` | The **GitHub Issue** requires a **Human implementer**. |
| `wontfix` (**Won't fix**) | `wontfix` | The **GitHub Issue** will not be actioned. |

When a skill mentions a canonical triage role, apply the matching label string from the second column.
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.26
toolchain go1.26.0

require (
charm.land/lipgloss/v2 v2.0.1
charm.land/lipgloss/v2 v2.0.2
github.com/charmbracelet/colorprofile v0.4.2
github.com/charmbracelet/x/ansi v0.11.6
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444
Expand All @@ -27,8 +27,11 @@ require (
)

require (
charm.land/bubbles/v2 v2.1.0 // indirect
charm.land/bubbletea/v2 v2.0.2 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymanbagabas/go-udiff v0.4.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect
github.com/charmbracelet/x/termios v0.1.1 // indirect
github.com/charmbracelet/x/windows v0.2.2 // indirect
Expand All @@ -38,7 +41,7 @@ require (
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.21 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/mango v0.1.0 // indirect
github.com/muesli/mango-cobra v1.2.0 // indirect
Expand Down
Loading
Loading