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
10 changes: 10 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

set -eu

if ! command -v pnpm >/dev/null 2>&1; then
echo "pre-commit: pnpm is required to run the test suite" >&2
exit 1
fi

exec pnpm test
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ That means:

## Dev Install

Install dependencies from the repository root to configure the pre-commit hook. It runs the workspace test suite before each commit:

```bash
pnpm install
```

To create development commands for `glc` and `ktc` under `~/.local/bin/`:

```bash
Expand Down
43 changes: 43 additions & 0 deletions openspec/specs/gitlab/jobs/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# GitLab Jobs Specification

## Purpose

Allow read-only inspection of GitLab CI/CD jobs and job traces.

## Requirements

### Requirement: List jobs

The system SHALL support listing jobs for a required project selector and optional pipeline, search, status, ref, scope, limit, refresh, and full-object controls according to the command surface.

#### Scenario: List jobs for a pipeline

- **WHEN** the user runs `glc jobs list --project <project> --pipeline <id>`
- **THEN** the command returns matching jobs using the stable job summary by default

### Requirement: Retrieve one job

The system SHALL support retrieving one job with a required project and job identifier.

#### Scenario: Get a job

- **WHEN** the user runs `glc jobs get --project <project> --job <id>`
- **THEN** the command returns the selected job or a not-found error

### Requirement: Read a job trace

The system SHALL support retrieving a job's trace as raw text for shell and diagnostic use.

#### Scenario: Get a job trace

- **WHEN** the user runs `glc jobs trace --project <project> --job <id>`
- **THEN** stdout contains the trace text without JSON decoration

### Requirement: Summarize job data

The system SHALL provide stable job summaries containing identifier, pipeline, name, stage, status, ref, duration, and web URL, with full upstream data available only when requested.

#### Scenario: Default job output

- **WHEN** a job list or get command is run without `--full`
- **THEN** the output uses the restricted stable schema
58 changes: 58 additions & 0 deletions openspec/specs/gitlab/merge-requests/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# GitLab Merge Requests Specification

## Purpose

Provide agent-friendly inspection of GitLab merge requests, their related datasets, versions, changes, and review snapshots.

## Requirements

### Requirement: List and retrieve merge requests

The system SHALL support merge request listing and retrieval with explicit group/project scoping and filters for search, state, sort, author, target/source branch, scope, date range, limit, refresh, and full payloads where applicable.

#### Scenario: List recently updated merge requests

- **WHEN** the user runs `glc mrs list --project <project> --since <date-spec>`
- **THEN** the command translates the date specification to an API boundary and returns matching merge requests

#### Scenario: Retrieve related merge request data

- **WHEN** the user runs `glc mrs get --project <project> --mr <iid> --with <datasets>`
- **THEN** the command returns the merge request together with the requested related datasets

### Requirement: Inspect merge request history and changes

The system SHALL support listing commits, pipelines, diff versions, and changes for a merge request, with optional diff text for changes and an explicit version selector.

#### Scenario: List merge request commits

- **WHEN** the user runs `glc mrs commits --project <project> --mr <iid>`
- **THEN** the command returns summarized commits for that merge request

#### Scenario: Request a merge request patch

- **WHEN** the user runs `glc mrs changes --project <project> --mr <iid> --patch`
- **THEN** the change items include diff text when GitLab provides it

### Requirement: Generate an agent-friendly snapshot bundle

The system SHALL support writing a deterministic merge request snapshot bundle containing a manifest and navigable overview, timeline, index, and per-file change artifacts for the requested datasets.

#### Scenario: Snapshot the latest diff

- **WHEN** the user runs `glc mrs snapshot --project <project> --mr <iid> --version latest --output-dir <dir>`
- **THEN** the command resolves `latest` to a concrete version and writes the snapshot to the requested directory

#### Scenario: Snapshot a changed file with unavailable diff

- **WHEN** GitLab marks a changed file as collapsed or too large
- **THEN** the snapshot keeps the file in metadata and explicitly indicates that its diff is unavailable

### Requirement: Return stable merge request summaries and anonymized identities

The system SHALL include stable identifiers, project, title, state, branches, timestamps, status, and web URL in default merge request summaries, and SHALL anonymize user identities in rendered output.

#### Scenario: Render a merge request list

- **WHEN** a merge request list is rendered without `--full`
- **THEN** each item uses the stable summary schema and does not expose the raw author identity
48 changes: 48 additions & 0 deletions openspec/specs/gitlab/pipelines/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# GitLab Pipelines Specification

## Purpose

Allow read-only inspection of GitLab CI/CD pipelines for a selected project.

## Requirements

### Requirement: List pipelines

The system SHALL support listing pipelines for a required project selector with optional search, state, sort, limit, refresh, and full-object controls.

#### Scenario: List recent pipelines

- **WHEN** the user runs `glc pipelines list --project <project>`
- **THEN** the command returns matching pipelines using the stable pipeline summary by default

#### Scenario: Limit pipeline results

- **WHEN** the user supplies `--limit <n>`
- **THEN** the command returns no more than the requested number of pipeline items

### Requirement: Retrieve one pipeline

The system SHALL support retrieving one pipeline using a required project and pipeline identifier.

#### Scenario: Get a pipeline

- **WHEN** the user runs `glc pipelines get --project <project> --pipeline <id>`
- **THEN** the command returns the selected pipeline or a not-found error

### Requirement: Summarize pipeline data

The system SHALL provide stable pipeline summaries containing identifier, project, ref, status, source, SHA, creation time, and web URL, with full upstream data available only when requested.

#### Scenario: Default pipeline output

- **WHEN** a pipeline command is run without `--full`
- **THEN** the output uses the restricted stable schema

### Requirement: Honor read and cache controls

The system SHALL perform pipeline operations as read-only requests, use the shared cache by default, bypass it with `--refresh`, and emit cache diagnostics only when verbose mode is requested.

#### Scenario: Refresh pipeline data

- **WHEN** the user runs a pipeline command with `--refresh`
- **THEN** the command bypasses an existing cached response and fetches current data
67 changes: 67 additions & 0 deletions openspec/specs/gitlab/repositories/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# GitLab Repositories Specification

## Purpose

Allow agents and shell users to inspect GitLab groups, projects, and repository contents through read-only, resource-first commands.

## Requirements

### Requirement: Inspect groups and namespaces

The system SHALL support listing groups, retrieving one group, and rendering a group tree, with optional group, search, state, sort, limit, refresh, and full-object controls.

#### Scenario: List top-level groups

- **WHEN** the user runs `glc groups list` without a group selector
- **THEN** the command returns matching groups using the default summary schema

#### Scenario: Render a group tree

- **WHEN** the user runs `glc groups tree --group <full-path>`
- **THEN** the command returns a hierarchical representation of the selected namespace

### Requirement: Inspect projects

The system SHALL support listing projects, retrieving one project, and rendering a project tree, using explicit group or project selectors and optional search, state, sort, limit, refresh, and full-object controls.

#### Scenario: List projects in a group

- **WHEN** the user runs `glc projects list --group <full-path>`
- **THEN** the command returns projects in that group using the restricted project summary by default

#### Scenario: Retrieve one project

- **WHEN** the user runs `glc projects get --project <path-with-namespace>`
- **THEN** the command returns the selected project or a not-found error

### Requirement: Inspect repository trees and refs

The system SHALL support listing repository tree entries, listing branches or tags, and reading one repository file using an explicit project selector and optional path, ref, page, limit, search, refresh, and full-object controls.

#### Scenario: Browse a repository path

- **WHEN** the user runs `glc repos tree --project <project> --ref <ref> --path <path>`
- **THEN** the command returns repository entries for that path and ref

#### Scenario: Read a repository file

- **WHEN** the user runs `glc repos file --project <project> --path <path> --ref <ref>`
- **THEN** the command returns the file contents in a raw-friendly form

### Requirement: Use stable summaries with opt-in full payloads

The system SHALL return restricted stable summaries by default and SHALL return the upstream GitLab objects only when `--full` is requested.

#### Scenario: Default project listing

- **WHEN** a project list is requested without `--full`
- **THEN** each item contains the documented stable project fields rather than the complete GitLab payload

### Requirement: Keep repository exploration read-only

The system SHALL perform only read operations for group, project, and repository commands and SHALL require explicit selectors for resource-specific operations.

#### Scenario: Missing project selector

- **WHEN** a repository operation is invoked without its required project selector
- **THEN** the command fails before making a resource request
53 changes: 53 additions & 0 deletions openspec/specs/kaiten/task-comments/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Kaiten Task Comments Specification

## Purpose

Provide read-only retrieval and stable rendering of comments attached to a Kaiten task.

## Requirements

### Requirement: Retrieve comments for a task

The system SHALL support `ktc task-comments get --task <id>` and SHALL require the task identifier before making the request.

#### Scenario: Get task comments

- **WHEN** the user runs `ktc task-comments get --task <id>`
- **THEN** the command requests the task's comments and returns normalized comment records

#### Scenario: Missing task selector

- **WHEN** the comments command is run without `--task`
- **THEN** the command fails with a CLI argument error

### Requirement: Normalize comment records

The system SHALL represent each comment with its identifier, author information, content, and creation/update timestamps when available.

#### Scenario: Comment has alternate upstream field names

- **WHEN** Kaiten returns comment text or timestamps under supported alternate field names
- **THEN** the normalized record exposes the canonical `content`, `created_at`, and `updated_at` fields

### Requirement: Render comments safely

The system SHALL support Markdown and JSON output, apply field projection before rendering, and anonymize comment authors in rendered output.

#### Scenario: Render a comment list as Markdown

- **WHEN** comments are requested without `--json`
- **THEN** stdout contains a Markdown comment list with a shortened anonymized author identity

#### Scenario: Render comments as JSON

- **WHEN** `--json` is requested
- **THEN** stdout contains valid JSON with the normalized comment records and anonymized identity values

### Requirement: Use read-only request and cache controls

The system SHALL fetch comments through the read-only Kaiten client, cache GET responses by default, bypass cached data with `--refresh`, and report request diagnostics only in verbose mode.

#### Scenario: Refresh comments

- **WHEN** the user runs the comments command with `--refresh`
- **THEN** the command bypasses the cached comment response and requests current data
67 changes: 67 additions & 0 deletions openspec/specs/kaiten/tasks/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Kaiten Tasks Specification

## Purpose

Allow agents and shell users to find, inspect, and summarize Kaiten tasks through a read-oriented command surface.

## Requirements

### Requirement: List the current user's tasks

The system SHALL support `ktc tasks mine`, resolve the current Kaiten user, collect visible cards, normalize them into task records, and apply the shared task filters and limit controls.

#### Scenario: List my open tasks

- **WHEN** the user runs `ktc tasks mine --state open`
- **THEN** the command returns only open tasks assigned to the resolved current user

#### Scenario: Current user cannot be resolved

- **WHEN** the current user endpoint cannot provide a usable user identity
- **THEN** the command fails with an authentication/configuration error rather than returning unrelated tasks

### Requirement: Find tasks across selected Kaiten scope

The system SHALL support task search by text and filters for assignee, space, board, state, date boundaries, and result limit.

#### Scenario: Find tasks by board and text

- **WHEN** the user runs `ktc tasks find <query> --space <space> --board <board>`
- **THEN** the command scans the selected scope, applies the text and entity filters, sorts matches by recency, and returns them

#### Scenario: Unknown space or board

- **WHEN** a supplied space or board selector matches no entity
- **THEN** the command fails with a not-found error identifying the selector

### Requirement: Retrieve one task with lookup fallback

The system SHALL support `ktc tasks get --id <id>` and SHALL try the direct card endpoint before falling back to scanning accessible spaces and boards when necessary.

#### Scenario: Direct task lookup succeeds

- **WHEN** the direct card endpoint returns the requested task
- **THEN** the command returns the normalized task without scanning every board

#### Scenario: Direct lookup misses

- **WHEN** the direct lookup cannot find the task
- **THEN** the command searches accessible boards and returns the task if found, otherwise reports that the task was not found

### Requirement: Normalize task records

The system SHALL expose stable task records with identifiers, title, description, archived/state/status flags, assignee, space, board, column, lane, type, relations, timestamps, and URL when available.

#### Scenario: Derive task status

- **WHEN** a card is archived, completed, or located in a typed workflow column
- **THEN** the normalized task reports the corresponding `archived`, `done`, `in_progress`, or `open` status and `is_open` value

### Requirement: Keep task discovery read-only and agent-friendly

The system SHALL use read-only Kaiten requests, shared caching with `--refresh` bypass, deterministic sorting, optional field projection, and anonymized user information in rendered output.

#### Scenario: Render task details as Markdown

- **WHEN** a task is retrieved without `--json`
- **THEN** the output includes core facts and brief parent/child relations in Markdown without exposing raw user identity
Loading
Loading