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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ npm/bin/tsq.exe
artifacts/
.pi-lens/
context.md
docs/superpowers/
18 changes: 14 additions & 4 deletions AGENTS-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Write path:

## Task Model
Task fields:
- `id` (`tsq-<8 crockford base32 chars>` root, `<parent>.<n>` child)
- `id` (`tsq-<number>` root, `<parent>.<n>` child); legacy `tsq-<8 crockford base32 chars>` IDs remain valid
- `alias` (kebab-case slug generated from the creation title; stable across title edits)
- `kind` (`task|feature|epic`)
- `title`
- `status` (`open|in_progress|blocked|deferred|closed|canceled`)
Expand Down Expand Up @@ -85,15 +86,21 @@ Relation types:
- `tsq` (no args, TTY): open read-only TUI
- `tsq init [--wizard|--no-wizard] [--yes] [--preset <name>] [--sync-branch|--worktree-name <name>]`
- `tsq init --install-skill|--uninstall-skill [--skill-targets ...] [--skill-name <name>] [--force-skill-overwrite]`
- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <tsq-xxxxxxxx>] [--body-file <path|->]`
- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <id>] [--body-file <path|->] [--force]`
- `tsq show <id> [--with-spec]`
- `tsq find ready [--lane <planning|coding>] [--assignee <name>] [--unassigned] [--kind ...] [--label ...] [--planning <needs_planning|planned>] [--tree [--full]]`
- `tsq find <blocked|open|in-progress|deferred|done|canceled> [filters...] [--tree [--full]]`
- `tsq find search <query> [--full]`

Note: for `find ready` and status-based `find` commands, `--full` is only valid with `--tree`. `--tree --full` keeps the full status set instead of applying the default tree status narrowing. `find search --full` remains valid without `--tree`.
- `tsq find similar "<text>"`
- `tsq watch [--once] [--interval <seconds>] [--status <csv>] [--assignee <name>] [--tree] [--flat]`

Notes:
- For `find ready` and status-based `find` commands, `--full` is only valid with `--tree`. `--tree --full` keeps the full status set instead of applying the default tree status narrowing. `find search --full` remains valid without `--tree`.
- `--id <id>` accepts `tsq-<number>` or legacy `tsq-<8 crockford base32 chars>`.
- Commands that accept a task ID also accept exact aliases and unique alias prefixes unless `--exact-id` is used.
- `tsq find similar "<text>"` shows ranked duplicate candidates with scores and reasons.
- `tsq create` refuses similar open/in-progress/blocked/deferred tasks unless `--force` is passed.

`watch` renders the task tree by default for human output. Use `--tree` to explicitly request tree view or `--flat` for the compact list view. These options are mutually exclusive.
- `tsq tui [--once] [--interval <seconds>] [--status <csv>] [--assignee <name>] [--board|--epics]`
- `tsq stale [--days <n>] [--status <status>] [--assignee <name>] [--limit <n>]`
Expand All @@ -113,6 +120,8 @@ Note: for `find ready` and status-based `find` commands, `--full` is only valid
- `tsq cancel <id...> [--note <text>]`
- `tsq orphans`
- `tsq spec <id> [--file <path> | --stdin | --text <markdown> | --show | --check] [--force]`
- `tsq spec <id> --update [--file <path> | --stdin | --text <markdown>]`
- `tsq spec <id> --patch [--file <path> | --stdin | --text <patch>]`
- `tsq block <task> by <blocker>`
- `tsq unblock <task> by <blocker>`
- `tsq order <later> after <earlier>`
Expand Down Expand Up @@ -149,6 +158,7 @@ Planning workflow guidance:
- Treat lifecycle `status` and `planning_state` as separate dimensions.
- `tsq find ready --lane planning` surfaces tasks that need planning work (`planning_state=needs_planning`).
- Planning-lane work should collaborate with the user and update specs/task body as needed before coding.
- Use `tsq spec <id> --update` for full spec replacement and `tsq spec <id> --patch` for small agent edits. Prefer patch input via stdin/file so unified-diff `---` headers are parsed as content.
- `tsq find ready --lane coding` surfaces tasks already planned (`planning_state=planned`).
- Use `status=deferred` for valid work intentionally parked for later.

Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Durable across restarts and context compaction.
- append-only audit trail
- stable machine output (`--json`)
- tree find view (`tsq find open --tree`)
- sequential task IDs (`tsq-<number>`) with alias resolution
- ranked search (`find search`) and duplicate detection (`find similar`)
- create duplicate gate (refuses similar tasks unless `--force`)
- skill install/uninstall via `tsq init`

## Non-Goals
Expand Down
27 changes: 26 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ dirs = "5"
once_cell = "1"
rust-embed = "8"
tempfile = "3"
diffy = "0.5"

[dev-dependencies]
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,22 @@ Commands:
- `tsq` (no args, TTY): open read-only TUI (List/Board views)
- `tsq init [--wizard|--no-wizard] [--yes] [--preset <name>] [--sync-branch|--worktree-name <name>]`
- `tsq init --install-skill|--uninstall-skill [--skill-targets ...] [--skill-name <name>] [--force-skill-overwrite]`
- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <tsq-xxxxxxxx>] [--body-file <path|->]`
- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <id>] [--body-file <path|->] [--force]`
- `tsq show <id> [--with-spec]`
- `tsq find ready [--lane <planning|coding>] [--assignee <name>] [--unassigned] [--kind ...] [--label ...] [--planning <needs_planning|planned>] [--tree [--full]]`
- `tsq find <blocked|open|in-progress|deferred|done|canceled> [filters...] [--tree [--full]]`
- `tsq find search <query> [--full]`

Note: for `find ready` and status-based `find` commands, `--full` is only valid with `--tree`. `--tree --full` keeps the full status set instead of applying the default tree status narrowing. `find search --full` remains valid without `--tree`.
- `tsq find similar "<text>"`
- `tsq watch [--once] [--interval <seconds>] [--status <csv>] [--assignee <name>] [--tree] [--flat]`

Notes:
- New root task IDs use `tsq-<number>`; legacy `tsq-<8 crockford base32 chars>` IDs remain valid.
- `--id <id>` accepts `tsq-<number>` or legacy `tsq-<8 crockford base32 chars>`.
- Task JSON includes `alias`, generated from the creation title and stable across title edits.
- Commands that accept a task ID also accept exact aliases and unique alias prefixes unless `--exact-id` is used.
- `tsq find similar "<text>"` shows ranked duplicate candidates.
- `tsq create` refuses similar open/in-progress/blocked/deferred tasks unless `--force` is passed.

`watch` renders the task tree by default for human output. Use `--tree` to explicitly request tree view or `--flat` for the compact list view. These options are mutually exclusive.
- `tsq tui [--once] [--interval <seconds>] [--status <csv>] [--assignee <name>] [--board|--epics]`
- `tsq stale [--days <n>] [--status <status>] [--assignee <name>] [--limit <n>]`
Expand All @@ -80,6 +87,8 @@ Note: for `find ready` and status-based `find` commands, `--full` is only valid
- `tsq cancel <id...> [--note <text>]`
- `tsq orphans`
- `tsq spec <id> [--file <path> | --stdin | --text <markdown> | --show | --check] [--force]`
- `tsq spec <id> --update [--file <path> | --stdin | --text <markdown>]`
- `tsq spec <id> --patch [--file <path> | --stdin | --text <patch>]`
- `tsq block <task> by <blocker>`
- `tsq unblock <task> by <blocker>`
- `tsq order <later> after <earlier>`
Expand Down
4 changes: 4 additions & 0 deletions SKILLS/tasque/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,15 @@ tsq create --parent <parent-id> --from-file tasks.md
```bash
tsq spec <id> --text "## Plan\n...\n## Acceptance\n..."
tsq spec <id> --show
# Choose one edit mode when changing an existing spec:
tsq spec <id> --update --stdin
tsq spec <id> --patch --stdin
tsq planned <id>
tsq claim <id> --assignee <name> --start
```

Use `tsq spec <id> --show` when spec markdown lives in sync worktree.
Use `--update` for whole-spec replacement. Use `--patch` for small agent edits; patch applies only to the attached spec and fails if context is stale. Prefer `--stdin` or `--file` for patches because unified diffs start with `---`.

## Parallel Work

Expand Down
20 changes: 17 additions & 3 deletions SKILLS/tasque/references/command-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Use `--sync-branch <name>` or `--worktree-name <name>` to choose another branch/
and create the worktree on first use. `tsq sync` pushes the sync branch to `origin`
and sets upstream automatically when needed. Non-git directories use local `.tasque/` storage.

- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <tsq-xxxxxxxx>] [--body-file <path|->]`
- `tsq create <title...> [--kind ...] [-p ...] [--parent <id>] [--from-file tasks.md] [--description <text>] [--external-ref <ref>] [--discovered-from <id>] [--planned|--needs-plan] [--ensure] [--id <id>] [--body-file <path|->] [--force]`

`tasks.md` supports nested two-space bullets:

Expand All @@ -29,8 +29,7 @@ and sets upstream automatically when needed. Non-git directories use local `.tas
- `tsq find ready [--lane <planning|coding>] [--assignee <name>] [--unassigned] [--kind ...] [--label ...] [--planning <needs_planning|planned>] [--tree [--full]]`
- `tsq find <blocked|open|in-progress|deferred|done|canceled> [filters...] [--tree [--full]]`
- `tsq find search <query> [--full]`

Note: for `find ready` and status-based `find` commands, `--full` is only valid with `--tree`. `--tree --full` keeps the full status set instead of applying the default tree status narrowing. `find search --full` remains valid without `--tree`.
- `tsq find similar "<text>"`
- `tsq edit <id> [--title ...] [--description ...] [--clear-description] [--priority ...] [--external-ref <ref>] [--clear-external-ref] [--discovered-from <id>] [--clear-discovered-from]`
- `tsq claim <id> [--assignee <a>] [--start] [--require-spec]`
- `tsq assign <id> --assignee <a>`
Expand All @@ -44,6 +43,14 @@ Note: for `find ready` and status-based `find` commands, `--full` is only valid
- `tsq reopen <id...> [--note <text>]`
- `tsq cancel <id...> [--note <text>]`

Notes:
- New root task IDs use `tsq-<number>`; legacy `tsq-<8 crockford base32 chars>` IDs remain valid.
- `--id <id>` accepts `tsq-<number>` or legacy `tsq-<8 crockford base32 chars>`.
- Task JSON includes `alias`, generated from the creation title and stable across title edits.
- Commands that accept a task ID also accept exact aliases and unique alias prefixes unless `--exact-id` is used.
- `tsq find similar "<text>"` shows ranked duplicate candidates.
- `tsq create` refuses similar open/in-progress/blocked/deferred tasks unless `--force` is passed.

## Dependencies and relations

- `tsq block <task> by <blocker>`
Expand All @@ -61,6 +68,8 @@ Note: for `find ready` and status-based `find` commands, `--full` is only valid
## Specs, notes, labels, history

- `tsq spec <id> [--file <path> | --stdin | --text <markdown> | --show | --check] [--force]`
- `tsq spec <id> --update [--file <path> | --stdin | --text <markdown>]`
- `tsq spec <id> --patch [--file <path> | --stdin | --text <patch>]`
- `tsq note <id> <text>`
- `tsq note <id> --stdin`
- `tsq notes <id>`
Expand All @@ -69,6 +78,11 @@ Note: for `find ready` and status-based `find` commands, `--full` is only valid
- `tsq labels`
- `tsq history <id> [--limit <n>] [--type <event-type>] [--actor <name>] [--since <iso>]`

Spec update notes:
- `--update` requires an existing attached spec and atomically replaces the whole spec.
- `--patch` requires an existing attached spec, applies one unified diff to the current spec in memory, rejects multi-file patches, and fails when patch context is stale.
- Prefer `--patch --stdin` or `--patch --file spec.patch`; unified diffs begin with `---`, which can confuse shell/arg parsing when passed via `--text`.

## Reporting and maintenance

- `tsq watch [--once] [--interval <seconds>] [--status <csv>] [--assignee <name>] [--tree] [--flat]`
Expand Down
22 changes: 22 additions & 0 deletions src/app/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ impl TasqueService {
service_create_update::create(&self.ctx, &input)
}

pub fn create_batch(
&self,
input: crate::app::service_types::CreateBatchInput,
) -> Result<Vec<Task>, TsqError> {
service_create_update::create_batch(&self.ctx, &input)
}

pub fn show(&self, id_raw: &str, exact_id: bool) -> Result<ShowResult, TsqError> {
service_query::show(&self.ctx, id_raw, exact_id)
}
Expand Down Expand Up @@ -182,6 +189,14 @@ impl TasqueService {
service_specs::spec_attach(&self.ctx, &input)
}

pub fn spec_update(&self, input: SpecUpdateInput) -> Result<SpecUpdateResult, TsqError> {
service_specs::spec_update(&self.ctx, &input)
}

pub fn spec_patch(&self, input: SpecPatchInput) -> Result<SpecUpdateResult, TsqError> {
service_specs::spec_patch(&self.ctx, &input)
}

pub fn spec_check(&self, input: SpecCheckInput) -> Result<SpecCheckResult, TsqError> {
service_specs::spec_check(&self.ctx, &input)
}
Expand Down Expand Up @@ -291,6 +306,13 @@ impl TasqueService {
service_query::search(&self.ctx, input)
}

pub fn similar(
&self,
input: &crate::app::service_types::SimilarInput,
) -> Result<Vec<crate::domain::similarity::SimilarTaskCandidate>, TsqError> {
service_query::similar(&self.ctx, input)
}

pub fn migrate(&self, branch: &str) -> Result<crate::types::MigrateResult, TsqError> {
crate::app::sync::migrate_to_sync_branch(&self.ctx.repo_root, branch, &self.ctx.actor)
}
Expand Down
Loading