From a20ee17a28dd7342f58ae068ccddb41118eec7ef Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 20:22:37 +0300 Subject: [PATCH 1/6] Keep the process skills in the repository The tasks, changelog, and tech-debt skills defined how work in tfscli is planned, how the changelog is written, and how deferred problems are recorded, yet they lived only in one developer's home directory. CLAUDE.md told an agent to ask when they were missing, and CONTRIBUTING.md kept a third copy of their rules as a summary. The three skills now live under .claude/skills/, so every contributor and every agent has the same rules. Each file is identical to its general version: it opens by deferring to a project copy when one exists and to the project's own documentation where that sets a different convention, so the choices left to tfscli are written in CONTRIBUTING.md rather than in the skills. The skills themselves changed in the process: - changelog uses all six Keep a Changelog sections, names a versioning scheme in the preamble only when the project declares one, and leaves an existing changelog in another format unconverted unless asked. - tech-debt closes an entry as fixed, with a reference, or as dropped, with a reason - the practice docs/tech-debt.md had already adopted. - tasks places its files next to existing ones, then in the project's documentation directory, then in docs/. docs/tech-debt.md follows the new entry format and gets a proper title. The purpose of each project document is now written down where an editor meets it. CONTRIBUTING.md gains a map of the documents, what each records, and when it changes; project-brief.md and architecture.md state their purpose at the top. The brief records purpose, scope, constraints, non-goals, and design principles and changes only with a product decision; feature behaviour belongs in README.md. Its sections that describe current behaviour predate that rule and are recorded as TD-08. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01QdgV5rygmGcBfQQBMtuQpt --- .claude/skills/changelog/SKILL.md | 136 ++++++++++++++++++++++++++++++ .claude/skills/tasks/SKILL.md | 116 +++++++++++++++++++++++++ .claude/skills/tech-debt/SKILL.md | 89 +++++++++++++++++++ CLAUDE.md | 4 +- CONTRIBUTING.md | 59 ++++++++----- docs/architecture.md | 5 ++ docs/project-brief.md | 4 + docs/tech-debt.md | 57 ++++++++----- 8 files changed, 426 insertions(+), 44 deletions(-) create mode 100644 .claude/skills/changelog/SKILL.md create mode 100644 .claude/skills/tasks/SKILL.md create mode 100644 .claude/skills/tech-debt/SKILL.md diff --git a/.claude/skills/changelog/SKILL.md b/.claude/skills/changelog/SKILL.md new file mode 100644 index 0000000..775e414 --- /dev/null +++ b/.claude/skills/changelog/SKILL.md @@ -0,0 +1,136 @@ +--- +name: changelog +description: Maintain CHANGELOG.md for users, not developers — Keep a Changelog format, behaviour-visible changes only, the six standard sections, strict entry format, and the release procedure. +argument-hint: "[change to record | release X.Y.Z]" +--- + +Format and rules for maintaining `CHANGELOG.md`. Use this skill when adding an entry, +reviewing whether a change belongs in the changelog, or preparing a release section. + +## Project version first + +If the current repository contains `.claude/skills/changelog/SKILL.md` and that file is +not the one you are reading, read it and follow it instead of this file. + +Where the project's own documentation (for example `CONTRIBUTING.md` or `CLAUDE.md`) +sets a different convention, the project's convention wins over this skill. + +## Existing changelogs + +If `CHANGELOG.md` already exists in a format other than the one described here, do not +convert it unless the user asks for that explicitly. Add new entries in the format the +file already uses, and offer the conversion as a separate change. + +## Audience + +Every entry is written for the **user**, not the developer. The changelog describes +changes in observable behaviour — not implementation details, refactoring, or test +coverage. If a change is invisible to the user, it does not belong here. + +## Structure + +The file follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/), with one +deliberate omission: no version comparison links are kept at the end of the file. They +are addressed to developers rather than users, and every release would have to rewrite +them. + +The file opens with a short preamble naming the format, followed by one section per +release, ordered from newest to oldest. The top section is always `[Unreleased]` and +collects changes that have not yet been released. Sections are separated by their +headings alone — no horizontal rules between them. + +```markdown +# Changelog + +All notable changes to this project are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +## [Unreleased] + +### Added +- ... + +## [0.2.0] - 2026-03-15 + +### Changed +- ... + +### Fixed +- ... + +## [0.1.0] - 2026-02-28 + +### Added +- ... +``` + +If the project declares a versioning scheme — in its contributing guide or similar +documentation — the preamble names it as well, for example: "and this project adheres +to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)." Do not name a scheme the +project has not declared. + +A version heading is `## [X.Y.Z] - YYYY-MM-DD`: the version in brackets, a hyphen +surrounded by spaces, and the release date in ISO 8601 format. + +## Sections + +Use exactly these six section names, in this order. A section heading appears only +when it has at least one entry — in `[Unreleased]` as well as in released versions. +When `[Unreleased]` has no entries, it consists of its heading alone; the first entry +of a kind adds its section heading in its place in the order. + +| Section | Use for | +|---------|---------| +| `Added` | New features and capabilities visible to the user. | +| `Changed` | Existing behaviour that has been intentionally altered. | +| `Deprecated` | Features or options that still work but will be removed in a future release. | +| `Removed` | Features or options that no longer exist. | +| `Fixed` | Bugs that were observable by the user and are now resolved. | +| `Security` | Fixed vulnerabilities, so that users know to upgrade. | + +## Entry format + +One entry per line, starting with `-`. One sentence, ending with a period. +No issue numbers, no commit hashes, no author names. + +**Write what changed in behaviour, not what changed in code.** + +Start each entry with the subject of the change, not a verb: + +``` +✓ Export button now produces a file named after the current date. +✓ Filters are no longer reset after a manual data refresh. + +✗ Added date-based filename generation to the export button. +✗ Fixed filter state preservation on refresh. +``` + +## What to include and what to skip + +| Include | Skip | +|---------|------| +| New feature visible to the user | Refactoring without behaviour change | +| Bug fix the user could observe | Dependency updates with no visible effect | +| Config field or CLI flag change | New or updated tests | +| Change in existing feature behaviour | Documentation edits | +| Removed or deprecated feature or option | Internal code cleanup | + +## Releasing + +If the project automates the release, the automation performs these steps; do not +perform them by hand. Otherwise, before tagging a release: + +1. Insert a version heading `## [X.Y.Z] - YYYY-MM-DD` directly below `## [Unreleased]`, + so that the entries collected so far belong to the new version and `[Unreleased]` + is left empty. +2. Commit the result before tagging. + +```markdown +## [Unreleased] + +## [0.2.0] - 2026-03-15 + +### Fixed +- ... +``` diff --git a/.claude/skills/tasks/SKILL.md b/.claude/skills/tasks/SKILL.md new file mode 100644 index 0000000..b8e091d --- /dev/null +++ b/.claude/skills/tasks/SKILL.md @@ -0,0 +1,116 @@ +--- +name: tasks +description: Universal task-file workflow — create a structured tasks file from a feature/request and execute it step by step, tracking what is done vs. pending in any project. No project-specific assumptions. +argument-hint: "[feature description to break down | path to a tasks file]" +--- + +A portable, file-based way to record and track work in any repository. It keeps +"what is done vs. what is left" unambiguous: a single markdown file holds an ordered +list of atomic tasks, each with a plain-text status. The skill makes no assumptions +about the project — no required tooling, no other documents, no fixed task categories. + +## Project version first + +If the current repository contains `.claude/skills/tasks/SKILL.md` and that file is +not the one you are reading, read it and follow it instead of this file. + +Where the project's own documentation (for example `CONTRIBUTING.md` or `CLAUDE.md`) +sets a different convention, the project's convention wins over this skill. + +## Mode detection + +Decide what to do from the user's request and the current context: + +- A path to an existing `Active` tasks file is given (or exactly one such file is found + in the tasks directory) → **Execute** mode. +- A feature or request description is given and no matching file exists → **Create** + mode (breakdown), then offer to start executing. +- Ambiguous (e.g. several active files, or unclear whether to create or execute) → ask + the user one short question before proceeding. + +## The tasks file + +This format is the heart of the skill. Use it verbatim. + +- **Name:** `YYYY-MM-DD-tasks-{slug}.md` — the date prefix orders files and avoids + name collisions; `{slug}` is a short kebab-case name for the feature/work. +- **Location:** active files live in the *tasks directory*: the directory that already + holds the project's tasks files; otherwise the directory where the project keeps its + documentation; otherwise `docs/`, created if it does not exist. Completed files move + to its `archive/` subdirectory. +- **Header status:** `**Status:** Active` while in progress; `**Status:** Archived` + once every task is done. + +### Layout + +```markdown +# YYYY-MM-DD-tasks-{slug}.md + +**Status:** Active + +## Context + +[Optional, free-form. Shared decisions, constraints, or notes that span several +tasks. Omit the whole section if there is nothing to record.] + +--- + +### TASK-01 `short-name` +**Description:** what to do +**Definition of done:** an observable, checkable outcome +**Status:** Pending + +### TASK-02 `short-name` +**Description:** ... +**Definition of done:** ... +**Status:** Pending +``` + +There are no task types and no cross-references between tasks. Every task has the same +four fields. + +### Status values + +| Status | Meaning | +|--------|---------| +| `Pending` | Not started. | +| `In progress` | Currently being worked on. | +| `Done` | Definition of done is met. | +| `Skipped — ` | Intentionally not done; reason recorded inline. | + +Write the status text verbatim. The only status that carries extra text is +`Skipped`, which appends its reason. Never annotate a `Pending` task — do not mark one +as "next", do not rank candidates, do not add any note to it. The next task to do is +simply the topmost `Pending` one; that is self-evident and needs no marker. + +## Create mode (breakdown) + +1. Turn the feature/request into a complete, ordered list of **atomic** tasks — each + one achievable in a single focused session, with a definition of done that can be + checked. +2. Propose the task structure to the user and let them adjust before writing anything. +3. Write the file to the tasks directory with header `Active` and every task `Pending`. +4. Offer to start executing the first task. + +## Execute mode (tracking discipline) + +1. The next task is the topmost one still `Pending` — no decision required. When you + start working on it, set its status to `In progress`. Do not touch the other + `Pending` tasks. +2. Do the work for that one task only — do not run ahead into later tasks. +3. When its definition of done is met, set its status to `Done`. +4. **Same-commit rule:** when the task's work is committed, the updated tasks file goes + into that **same commit** — never a separate status-only commit. This skill follows + the project's normal commit cadence and does not force commits the user did not ask + for; it only governs how the file participates when a commit happens. +5. When the **last** task is done: change the header to `Archived` and move the file to + the `archive/` subdirectory — in the same commit as that task's work. +6. If a task is abandoned, mark it `Skipped — ` rather than deleting it. + +## Invariants + +- Tasks are atomic; work on one at a time. +- Never leave a finished task unmarked — the file is the source of truth for progress. +- The tasks file travels with the work it describes in a single commit. +- Archive the file (header + move to `archive/`) once all tasks are resolved. +- Make no assumptions about other project files, documents, or tooling. diff --git a/.claude/skills/tech-debt/SKILL.md b/.claude/skills/tech-debt/SKILL.md new file mode 100644 index 0000000..2b04626 --- /dev/null +++ b/.claude/skills/tech-debt/SKILL.md @@ -0,0 +1,89 @@ +--- +name: tech-debt +description: Record and track consciously deferred problems in tech-debt.md — what qualifies as tech debt, the TD entry format, and closing items as fixed or dropped. Use when deferring a known issue or documenting a deliberate compromise. +argument-hint: "[problem to record | TD-NN to close]" +--- + +Maintenance is not a separate development loop — it is a single living document +(`tech-debt.md`) and a simple rule for how to handle known problems. The skill makes +no assumptions about the project beyond the presence of a repository. + +## Project version first + +If the current repository contains `.claude/skills/tech-debt/SKILL.md` and that file is +not the one you are reading, read it and follow it instead of this file. + +Where the project's own documentation (for example `CONTRIBUTING.md` or `CLAUDE.md`) +sets a different convention, the project's convention wins over this skill. + +## tech-debt.md + +`tech-debt.md` exists for the entire life of the project. It records known problems +that have been consciously deferred — not forgotten, but deliberately not fixed yet. + +**Location.** If `tech-debt.md` already exists in the repository, use that file and +never create a second one. If it does not exist when the first item is recorded, +create it in the directory where the project keeps its documentation, or in `docs/` +(creating it) if the project has no such directory. + +**What goes here:** +- A known issue with an explicit decision to defer it, with reasoning +- A compromise made consciously during a code review +- Something that requires design or architectural thinking before implementation + +**What does not go here:** +- A bug — fix it now or plan it as regular work +- A small cosmetic fix — either fix it immediately or ignore it + +**Practical test:** if during a code review you would write "this is an intentional +tradeoff, document it" — it goes in `tech-debt.md`. If you would write "fix this" — +fix it. + +## Format + +```markdown +# Tech debt + +## Active + +### TD-03 `short name` +**Problem:** what is wrong +**Why deferred:** reasoning +**Trigger:** what would make us fix this (new feature, performance issue, etc.) +**Added:** YYYY-MM-DD, in + +--- + +## Closed + +### TD-01 `short name` +**Closed:** YYYY-MM-DD — fixed in + +### TD-02 `short name` +**Closed:** YYYY-MM-DD — dropped: +``` + +Numbers (`TD-NN`) are assigned sequentially and never reused. The **Added** line +names where the decision was made — a review, a plan of work, or a conversation. + +## How it gets populated + +During a review, if a non-critical problem is found and the decision is made to defer +it — it is added to `tech-debt.md` in the same commit as the review fixes. + +## Closing an item + +An item is closed in one of two ways: + +- **Fixed.** When the item is ready to be fixed, it becomes a regular piece of work, + planned and carried out the way the project plans any change. When the work is done, + the item is closed with `fixed in` and a reference to where the fix can be found. +- **Dropped.** When a review of the item shows that no change is needed — the problem + does not occur in practice, or it turns out to be a decision rather than a deferred + problem — the item is closed with `dropped:` and the reason. + +Either way, the item moves to the Closed section, keeping its number and short name, +and its body is replaced with the **Closed** line. The original reasoning remains in +the repository history. + +`tech-debt.md` is never archived — it accumulates a Closed section over time. diff --git a/CLAUDE.md b/CLAUDE.md index 1b6a804..048536b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Process -The project follows a deliberate, strict workflow defined by process skills: `project-start` (brief, tech stack, architecture, repo skeleton), `tasks` (task breakdown and execution), `tech-debt` (deferred compromises), and `changelog` (CHANGELOG.md entries and releases). If these skills are available, they are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. If they are not available in the current environment, ask the user how to proceed instead of improvising the process from memory. +The workflow is defined by three process skills kept in the repository under `.claude/skills/`: `tasks` (task breakdown and execution), `changelog` (`CHANGELOG.md` entries and releases), and `tech-debt` (deferred compromises). They are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. The choices they leave to the project are in the "Process" section of `CONTRIBUTING.md`, and the purpose of each project document is in its "Project documents" section. Note: tasks files created before the move to skills (e.g. `docs/2026-05-20-tasks-html-quirks.md`) follow an older format with task types and emoji statuses; keep their existing format when updating them. @@ -14,7 +14,7 @@ The MVP is implemented: `tfscli wit work-items get` works end to end, `tfscli wi Three documents drive everything: -- `project-brief.md` — product scope, constraints, non-goals, error/config/command contracts. **Read this before proposing any user-facing change.** +- `project-brief.md` — purpose, scope, constraints, non-goals, and design principles of the product. **Read this before proposing any user-facing change.** It changes only when a product decision changes; feature behaviour belongs in `README.md`, not here. - `architecture.md` — tech stack with rationale and rejected alternatives. **Read this before adding a dependency or swapping a library.** - Process skills — the development workflow (see "Process" above). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb514c2..384209c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,30 +85,45 @@ if a change would break one, raise it before implementing. parsing are `encoding/json`. A fourth dependency is a decision recorded in `docs/architecture.md`, not a `go get`. +## Project documents + +Each document has one job, and new information goes to the document whose job it is. +`project-brief.md` and `architecture.md` also state their purpose at the top. + +| Document | What it records | When it changes | +|---|---|---| +| `docs/project-brief.md` | Purpose, audience, scope, constraints, non-goals, and design principles | A product decision changes — not when a feature is added | +| `docs/architecture.md` | Technology stack, architecture, and project structure, with rationale | The stack, the modules, their interactions, or the top-level structure change | +| `README.md` | What tfscli does and how to use it | Any user-visible behaviour changes | +| `skills/tfscli/SKILL.md` | How an AI agent uses tfscli; ships in every release archive | A command, a flag, an error category, or an environment variable changes | +| `CHANGELOG.md` | User-visible changes, per release | Any user-visible change | +| `CONTRIBUTING.md` | How the project is built, checked, released, and worked on | The build, the rules, or the process change | +| `CLAUDE.md` | Guidance for AI agents working in the repository | Anything it summarises changes | +| `docs/tech-debt.md` | Consciously deferred problems | A problem is deferred or closed | +| `docs/YYYY-MM-DD-tasks-.md` | The plan and progress of one unit of work | The work progresses; archived to `docs/archive/` when done | +| `.claude/skills/` | The process rules below | The process changes | + ## Process -Work is planned and tracked through the process skills `tasks`, `changelog`, and -`tech-debt`, which are authoritative wherever they are available. Where they are not, ask -how to proceed rather than reconstructing the process from the summary below. - -- **Tasks files.** A unit of work gets `docs/YYYY-MM-DD-tasks-.md`, with - `**Status:** Active` in the header and an ordered list of atomic tasks, each carrying a - description, a definition of done, and a status of `Pending`, `In progress`, `Done`, or - `Skipped — `. The file travels in the same commit as the work it describes; a - status-only commit is never correct. When the last task is resolved, the header becomes - `Archived` and the file moves to `docs/archive/` in that same commit. - `docs/2026-05-20-tasks-html-quirks.md` predates this format and keeps its own — task - types and emoji statuses — when updated. -- **Changelog.** `CHANGELOG.md` is written for the user of the tool: features, observable - bug fixes, changed configuration keys and flags, behaviour changes, and removals, but not - refactoring, tests, documentation, or invisible dependency updates. The format is - [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) without version - comparison links. Sections are exactly `Added`, `Changed`, `Removed`, and `Fixed`, in - that order, and a section heading appears only when it has entries; an entry is one - sentence starting with the subject of the change rather than a verb. Unreleased work - accumulates under `[Unreleased]`. -- **Tech debt.** A consciously deferred compromise is recorded in `docs/tech-debt.md` - rather than left in a comment, and is closed through the normal tasks-file workflow. +Work is planned and tracked with three process skills kept in the repository. Each is a +plain Markdown file and the complete set of rules, for people as much as for AI agents: + +- `.claude/skills/tasks/SKILL.md` — tasks files: a unit of work as an ordered list of + atomic tasks with a definition of done and a status each, committed together with the + work it describes and archived when done. +- `.claude/skills/changelog/SKILL.md` — `CHANGELOG.md`: Keep a Changelog 1.1.0 without + comparison links, user-visible changes only, one sentence per entry. +- `.claude/skills/tech-debt/SKILL.md` — `docs/tech-debt.md`: what counts as a deferred + problem, the entry format, and closing an entry as fixed or dropped. + +The skills leave a few choices to the project. In tfscli: + +- Tasks files live in `docs/`, and archived ones in `docs/archive/`. The fix of a tech + debt entry is planned as a tasks file. `docs/2026-05-20-tasks-html-quirks.md` predates + the current format and keeps its own — task types and emoji statuses — when updated. +- The changelog preamble names Semantic Versioning, as declared in "Choosing the + version", and the version section is written by the release workflow (see + "Releasing"). ## Commits and branches diff --git a/docs/architecture.md b/docs/architecture.md index fa11231..26d657f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,5 +1,10 @@ # Architecture — tfscli +This document records the technology stack, the architecture, and the project structure +of tfscli, with their rationale and the alternatives rejected. It changes when the stack, +the modules, their interactions, or the top-level structure change. The behaviour of +individual features is documented in `README.md`, not here. + ## Tech Stack ### Language: Go diff --git a/docs/project-brief.md b/docs/project-brief.md index 4a58cff..6633d36 100644 --- a/docs/project-brief.md +++ b/docs/project-brief.md @@ -1,5 +1,9 @@ # Project Brief — tfscli +This document records the purpose, audience, scope, constraints, non-goals, and design +principles of tfscli. It changes only when one of these decisions changes. The behaviour +of individual features is documented in `README.md`, not here. + ## Problem AI coding agents (Claude Code, opencode, Cursor) have no lightweight way to access on-premises TFS / Azure DevOps Server data. Existing solutions are MCP servers that require Node.js runtime, long startup times, a persistent process, and explicit credentials (PAT or login/password). They don't fit the stateless CLI model that agents already use for OS interaction (`git`, `grep`, `find`). diff --git a/docs/tech-debt.md b/docs/tech-debt.md index ac68da3..5224998 100644 --- a/docs/tech-debt.md +++ b/docs/tech-debt.md @@ -1,8 +1,8 @@ -## tech-debt.md +# Tech debt -### Active +## Active -#### TD-07 `main-not-protected` +### TD-07 `main-not-protected` **Problem:** `main` has no server-side protection. The rule that changes reach it only through pull requests with a green `check` is a convention that GitHub does not enforce. @@ -31,28 +31,45 @@ work found necessary at that point: **Added:** 2026-10-05, in conversation; replaces TASK-01 of `docs/archive/2026-10-04-tasks-release-bypass.md` +### TD-08 `brief-describes-feature-behaviour` +**Problem:** `docs/project-brief.md` now states that it records the purpose, scope, +constraints, non-goals, and design principles of tfscli, and that feature behaviour is +documented in `README.md`. Several of its sections predate that statement and describe +current behaviour instead: the login sequence under "Authentication", the details +under "Configuration", the list of commands under "Command Format", the sample +messages under "Error Format", and "Key Dependencies". The same content is kept in +`README.md`, `CLAUDE.md`, `skills/tfscli/SKILL.md`, and `docs/architecture.md`, so +every feature has had to update the brief as one more copy. +**Why deferred:** Moving the content is a separate review of each section — what is a +principle and stays, what is behaviour and is already covered elsewhere — and is not +needed to state the purpose of the document. +**Trigger:** the next change that would otherwise add feature behaviour to the brief. +The normative parts stay as principles: the credential model, the configuration +precedence, and the error format and its stability. +**Added:** 2026-10-05, in conversation on the purpose of the project documents + --- -### Closed +## Closed -#### TD-01 `login-anonymous-detection` -**Fixed:** 2026-10-05 — dropped without a change: no server with anonymous -access is available to verify against; recorded as a known limitation in -`README.md` until a user reports such a server +### TD-01 `login-anonymous-detection` +**Closed:** 2026-10-05 — dropped: no server with anonymous access is available to +verify against; recorded as a known limitation in `README.md` until a user reports +such a server -#### TD-02 `tls-1.2-minimum` -**Fixed:** 2026-10-05 — not a deferred problem but a decision; recorded under -"Defaults are safe" in `docs/architecture.md` +### TD-02 `tls-1.2-minimum` +**Closed:** 2026-10-05 — dropped: not a deferred problem but a decision; recorded +under "Defaults are safe" in `docs/architecture.md` -#### TD-03 `request-duration-test` -**Fixed:** 2026-10-05 +### TD-03 `request-duration-test` +**Closed:** 2026-10-05 — fixed in c70658c -#### TD-04 `url-userinfo-in-output` -**Fixed:** 2026-10-05 +### TD-04 `url-userinfo-in-output` +**Closed:** 2026-10-05 — fixed in d46745f -#### TD-05 `collection-named-like-virtual-directory` -**Fixed:** 2026-10-05 — dropped without a change: the naming is not known to -occur, and a report of it would surface as a `not_found` at login +### TD-05 `collection-named-like-virtual-directory` +**Closed:** 2026-10-05 — dropped: the naming is not known to occur, and a +report of it would surface as a `not_found` at login -#### TD-06 `path-segments-unescaped` -**Fixed:** 2026-10-05 +### TD-06 `path-segments-unescaped` +**Closed:** 2026-10-05 — fixed in c70658c From 591ef888b01ec7d70e217ab9db6ba539eebbe4e3 Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 20:28:17 +0300 Subject: [PATCH 2/6] Close the gaps the review found in the process skills The tasks skill worded its archive condition three ways, so a file whose last task was skipped could stay Active, and it sent an agent past a task left In progress by an interrupted session to the next Pending one. A task now counts as resolved when it is Done or Skipped, the file is archived once every task is resolved, and an unfinished task is resumed before a new one starts. The skill's invariant against assuming project files no longer contradicts its rule that project conventions win, mode detection no longer treats a request for new work as a request to continue the one active file, and a project whose tasks files are all archived keeps new ones beside the archive rather than in it. The tech-debt skill described adding an entry only during a review; it now covers any deliberate deferral and says which commit the entry goes into. A deferred bug is no longer excluded, and the closing remark no longer borrows "archived" from the tasks skill. The rest is wording: metaphors and a first-person placeholder in the skills, an unclear sentence in the changelog skill, two inaccuracies in the Process section of CONTRIBUTING.md, an ambiguous reference and an outdated list heading in CLAUDE.md, whose document descriptions now match the headers of the brief and the architecture, the header paragraphs written in the line style of their files, a time-bound "now" in TD-08, and a row for .claude/ in the top-level directories of architecture.md so that it is not confused with skills/. The skills under .claude/skills/ remain identical to their general versions. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01QdgV5rygmGcBfQQBMtuQpt --- .claude/skills/changelog/SKILL.md | 6 ++--- .claude/skills/tasks/SKILL.md | 37 ++++++++++++++++++------------- .claude/skills/tech-debt/SKILL.md | 20 +++++++++-------- CLAUDE.md | 8 +++---- CONTRIBUTING.md | 5 +++-- docs/architecture.md | 6 ++--- docs/project-brief.md | 4 +--- docs/tech-debt.md | 15 +++++++------ 8 files changed, 54 insertions(+), 47 deletions(-) diff --git a/.claude/skills/changelog/SKILL.md b/.claude/skills/changelog/SKILL.md index 775e414..42cf111 100644 --- a/.claude/skills/changelog/SKILL.md +++ b/.claude/skills/changelog/SKILL.md @@ -1,6 +1,6 @@ --- name: changelog -description: Maintain CHANGELOG.md for users, not developers — Keep a Changelog format, behaviour-visible changes only, the six standard sections, strict entry format, and the release procedure. +description: Maintain CHANGELOG.md for users, not developers — Keep a Changelog format, user-visible changes only, the six standard sections, strict entry format, and the release procedure. argument-hint: "[change to record | release X.Y.Z]" --- @@ -77,8 +77,8 @@ surrounded by spaces, and the release date in ISO 8601 format. Use exactly these six section names, in this order. A section heading appears only when it has at least one entry — in `[Unreleased]` as well as in released versions. -When `[Unreleased]` has no entries, it consists of its heading alone; the first entry -of a kind adds its section heading in its place in the order. +When `[Unreleased]` has no entries, it consists of its heading alone. The first entry +for a section adds that section's heading at its position in the order below. | Section | Use for | |---------|---------| diff --git a/.claude/skills/tasks/SKILL.md b/.claude/skills/tasks/SKILL.md index b8e091d..afb0db2 100644 --- a/.claude/skills/tasks/SKILL.md +++ b/.claude/skills/tasks/SKILL.md @@ -6,8 +6,8 @@ argument-hint: "[feature description to break down | path to a tasks file]" A portable, file-based way to record and track work in any repository. It keeps "what is done vs. what is left" unambiguous: a single markdown file holds an ordered -list of atomic tasks, each with a plain-text status. The skill makes no assumptions -about the project — no required tooling, no other documents, no fixed task categories. +list of atomic tasks, each with a plain-text status. The skill requires no particular +tooling or project files and imposes no fixed task categories. ## Project version first @@ -21,8 +21,9 @@ sets a different convention, the project's convention wins over this skill. Decide what to do from the user's request and the current context: -- A path to an existing `Active` tasks file is given (or exactly one such file is found - in the tasks directory) → **Execute** mode. +- A path to an existing `Active` tasks file is given, or the request names no new work + and exactly one `Active` file exists in the tasks directory (see "The tasks file") → + **Execute** mode. - A feature or request description is given and no matching file exists → **Create** mode (breakdown), then offer to start executing. - Ambiguous (e.g. several active files, or unclear whether to create or execute) → ask @@ -30,16 +31,17 @@ Decide what to do from the user's request and the current context: ## The tasks file -This format is the heart of the skill. Use it verbatim. +Use the following format verbatim. - **Name:** `YYYY-MM-DD-tasks-{slug}.md` — the date prefix orders files and avoids name collisions; `{slug}` is a short kebab-case name for the feature/work. - **Location:** active files live in the *tasks directory*: the directory that already - holds the project's tasks files; otherwise the directory where the project keeps its + holds the project's active tasks files, or the parent of the `archive/` directory + that holds its archived ones; otherwise the directory where the project keeps its documentation; otherwise `docs/`, created if it does not exist. Completed files move - to its `archive/` subdirectory. + to the `archive/` subdirectory of the tasks directory. - **Header status:** `**Status:** Active` while in progress; `**Status:** Archived` - once every task is done. + once every task is resolved — `Done` or `Skipped`. ### Layout @@ -78,10 +80,13 @@ four fields. | `Done` | Definition of done is met. | | `Skipped — ` | Intentionally not done; reason recorded inline. | +A task is *resolved* when it is `Done` or `Skipped`. + Write the status text verbatim. The only status that carries extra text is `Skipped`, which appends its reason. Never annotate a `Pending` task — do not mark one as "next", do not rank candidates, do not add any note to it. The next task to do is -simply the topmost `Pending` one; that is self-evident and needs no marker. +the one already `In progress`, if any, and otherwise the topmost `Pending` one; that is +self-evident and needs no marker. ## Create mode (breakdown) @@ -94,16 +99,17 @@ simply the topmost `Pending` one; that is self-evident and needs no marker. ## Execute mode (tracking discipline) -1. The next task is the topmost one still `Pending` — no decision required. When you - start working on it, set its status to `In progress`. Do not touch the other - `Pending` tasks. +1. The next task is the one already `In progress`, if any — for example, one left + unfinished by an interrupted session; otherwise it is the topmost `Pending` one, and + when you start working on it, set its status to `In progress`. No decision is + required either way. Do not touch the other `Pending` tasks. 2. Do the work for that one task only — do not run ahead into later tasks. 3. When its definition of done is met, set its status to `Done`. 4. **Same-commit rule:** when the task's work is committed, the updated tasks file goes into that **same commit** — never a separate status-only commit. This skill follows the project's normal commit cadence and does not force commits the user did not ask for; it only governs how the file participates when a commit happens. -5. When the **last** task is done: change the header to `Archived` and move the file to +5. When the last task is resolved: change the header to `Archived` and move the file to the `archive/` subdirectory — in the same commit as that task's work. 6. If a task is abandoned, mark it `Skipped — ` rather than deleting it. @@ -112,5 +118,6 @@ simply the topmost `Pending` one; that is self-evident and needs no marker. - Tasks are atomic; work on one at a time. - Never leave a finished task unmarked — the file is the source of truth for progress. - The tasks file travels with the work it describes in a single commit. -- Archive the file (header + move to `archive/`) once all tasks are resolved. -- Make no assumptions about other project files, documents, or tooling. +- Archive the file (header + move to `archive/`) once every task is resolved. +- Require no particular project files or tooling; follow the project's documented + conventions where they exist. diff --git a/.claude/skills/tech-debt/SKILL.md b/.claude/skills/tech-debt/SKILL.md index 2b04626..a178f25 100644 --- a/.claude/skills/tech-debt/SKILL.md +++ b/.claude/skills/tech-debt/SKILL.md @@ -4,9 +4,9 @@ description: Record and track consciously deferred problems in tech-debt.md — argument-hint: "[problem to record | TD-NN to close]" --- -Maintenance is not a separate development loop — it is a single living document -(`tech-debt.md`) and a simple rule for how to handle known problems. The skill makes -no assumptions about the project beyond the presence of a repository. +This skill maintains `tech-debt.md`, a single document that records known problems +deliberately deferred, and defines how entries are added and closed. It assumes +nothing about the project beyond the presence of a repository. ## Project version first @@ -32,7 +32,7 @@ create it in the directory where the project keeps its documentation, or in `doc - Something that requires design or architectural thinking before implementation **What does not go here:** -- A bug — fix it now or plan it as regular work +- A bug with no decision to defer it — fix it now or plan it as regular work - A small cosmetic fix — either fix it immediately or ignore it **Practical test:** if during a code review you would write "this is an intentional @@ -49,7 +49,7 @@ fix it. ### TD-03 `short name` **Problem:** what is wrong **Why deferred:** reasoning -**Trigger:** what would make us fix this (new feature, performance issue, etc.) +**Trigger:** the event that makes the fix necessary (a new feature, a performance issue) **Added:** YYYY-MM-DD, in --- @@ -66,10 +66,12 @@ fix it. Numbers (`TD-NN`) are assigned sequentially and never reused. The **Added** line names where the decision was made — a review, a plan of work, or a conversation. -## How it gets populated +## Adding an item -During a review, if a non-critical problem is found and the decision is made to defer -it — it is added to `tech-debt.md` in the same commit as the review fixes. +When a problem is deliberately deferred — during a review, while planning or doing +work, or in a discussion — add an entry under Active with the next free number. The +entry goes into the same commit as the change that led to the decision, such as the +review fixes, or into a commit of its own when there is no such change. ## Closing an item @@ -86,4 +88,4 @@ Either way, the item moves to the Closed section, keeping its number and short n and its body is replaced with the **Closed** line. The original reasoning remains in the repository history. -`tech-debt.md` is never archived — it accumulates a Closed section over time. +`tech-debt.md` is never moved or split; closed entries stay in its Closed section. diff --git a/CLAUDE.md b/CLAUDE.md index 048536b..08f6953 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Process -The workflow is defined by three process skills kept in the repository under `.claude/skills/`: `tasks` (task breakdown and execution), `changelog` (`CHANGELOG.md` entries and releases), and `tech-debt` (deferred compromises). They are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. The choices they leave to the project are in the "Process" section of `CONTRIBUTING.md`, and the purpose of each project document is in its "Project documents" section. +The workflow is defined by three process skills kept in the repository under `.claude/skills/`: `tasks` (task breakdown and execution), `changelog` (`CHANGELOG.md` entries and releases), and `tech-debt` (deferred compromises). They are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. `CONTRIBUTING.md` records the choices they leave to the project ("Process") and the purpose of each project document ("Project documents"). Note: tasks files created before the move to skills (e.g. `docs/2026-05-20-tasks-html-quirks.md`) follow an older format with task types and emoji statuses; keep their existing format when updating them. @@ -12,10 +12,10 @@ Note: tasks files created before the move to skills (e.g. `docs/2026-05-20-tasks The MVP is implemented: `tfscli wit work-items get` works end to end, `tfscli wit work-items list` and `tfscli wit work-items get-batch` read several work items by id, `tfscli wit wiql query-by-wiql` finds work item ids with a WIQL query, and the module has one package per architecture module (see the "Project Structure" section of `docs/architecture.md`). Release 0.0.5, which predates the current command names, has been run against a live TFS instance: `auth login` and reading one work item (`get`) work there; `list`, `get-batch`, and `query-by-wiql` have not been run against a live server yet; the error paths and rich-text rendering on real data have not been checked yet — see the "Status" and "Known limitations" sections of `README.md`. Further work goes through tasks files per the `tasks` skill. -Three documents drive everything: +Read these before the corresponding kind of change (the full list of project documents is in "Project documents" in `CONTRIBUTING.md`): -- `project-brief.md` — purpose, scope, constraints, non-goals, and design principles of the product. **Read this before proposing any user-facing change.** It changes only when a product decision changes; feature behaviour belongs in `README.md`, not here. -- `architecture.md` — tech stack with rationale and rejected alternatives. **Read this before adding a dependency or swapping a library.** +- `project-brief.md` — purpose, audience, scope, constraints, non-goals, and design principles of the product. **Read this before proposing any user-facing change.** It changes only when a product decision changes; feature behaviour belongs in `README.md`, not here. +- `architecture.md` — technology stack, architecture, and project structure, with rationale and rejected alternatives. **Read this before adding a dependency or swapping a library.** - Process skills — the development workflow (see "Process" above). ## Non-negotiable product constraints diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 384209c..1148e76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,7 +106,8 @@ Each document has one job, and new information goes to the document whose job it ## Process Work is planned and tracked with three process skills kept in the repository. Each is a -plain Markdown file and the complete set of rules, for people as much as for AI agents: +plain Markdown file and states the full rules, for people as much as for AI agents, +completed by the project choices listed below: - `.claude/skills/tasks/SKILL.md` — tasks files: a unit of work as an ordered list of atomic tasks with a definition of done and a status each, committed together with the @@ -122,7 +123,7 @@ The skills leave a few choices to the project. In tfscli: debt entry is planned as a tasks file. `docs/2026-05-20-tasks-html-quirks.md` predates the current format and keeps its own — task types and emoji statuses — when updated. - The changelog preamble names Semantic Versioning, as declared in "Choosing the - version", and the version section is written by the release workflow (see + version", and the version heading is inserted by the release workflow (see "Releasing"). ## Commits and branches diff --git a/docs/architecture.md b/docs/architecture.md index 26d657f..9e224ef 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,9 +1,6 @@ # Architecture — tfscli -This document records the technology stack, the architecture, and the project structure -of tfscli, with their rationale and the alternatives rejected. It changes when the stack, -the modules, their interactions, or the top-level structure change. The behaviour of -individual features is documented in `README.md`, not here. +This document records the technology stack, the architecture, and the project structure of tfscli, with their rationale and the alternatives rejected. It changes when the stack, the modules, their interactions, or the top-level structure change. The behaviour of individual features is documented in `README.md`, not here. ## Tech Stack @@ -343,5 +340,6 @@ Standard Go CLI layout: a single binary entry point under `cmd/`, all implementa | `internal/` | All implementation packages, one per architecture module. Tests sit next to the code (`_test.go`); fixtures live in per-package `testdata/` directories. | | `docs/` | Design documents (`project-brief.md`, `architecture.md`), tasks files, tech-debt register. Not part of the shipped binary. | | `skills/` | The agent skill shipped beside the binary, `skills/tfscli/SKILL.md`, in the Agent Skills format. Copied into the archive by goreleaser and installed by copying the directory into an agent's skills path. | +| `.claude/` | Claude Code project settings and the process skills in `.claude/skills/` (tasks, changelog, tech-debt). Not shipped, and unrelated to `skills/`, which holds the skill for users of tfscli. | Deliberately absent: `pkg/` (nothing is exported), `vendor/` (dependencies resolve through the module proxy), a separate `test/` tree (Go convention keeps tests beside the code they test). diff --git a/docs/project-brief.md b/docs/project-brief.md index 6633d36..2286228 100644 --- a/docs/project-brief.md +++ b/docs/project-brief.md @@ -1,8 +1,6 @@ # Project Brief — tfscli -This document records the purpose, audience, scope, constraints, non-goals, and design -principles of tfscli. It changes only when one of these decisions changes. The behaviour -of individual features is documented in `README.md`, not here. +This document records the purpose, audience, scope, constraints, non-goals, and design principles of tfscli. It changes only when one of these decisions changes. The behaviour of individual features is documented in `README.md`, not here. ## Problem diff --git a/docs/tech-debt.md b/docs/tech-debt.md index 5224998..54268d9 100644 --- a/docs/tech-debt.md +++ b/docs/tech-debt.md @@ -32,14 +32,15 @@ work found necessary at that point: `docs/archive/2026-10-04-tasks-release-bypass.md` ### TD-08 `brief-describes-feature-behaviour` -**Problem:** `docs/project-brief.md` now states that it records the purpose, scope, -constraints, non-goals, and design principles of tfscli, and that feature behaviour is -documented in `README.md`. Several of its sections predate that statement and describe -current behaviour instead: the login sequence under "Authentication", the details -under "Configuration", the list of commands under "Command Format", the sample -messages under "Error Format", and "Key Dependencies". The same content is kept in +**Problem:** The preamble of `docs/project-brief.md` states that it records the purpose, +scope, constraints, non-goals, and design principles of tfscli, and that feature +behaviour is documented in `README.md`. Several of its sections predate that statement +and describe current behaviour instead: the login sequence under "Authentication", +the details under "Configuration", the list of commands under "Command Format", the +sample messages under "Error Format", and "Key Dependencies". The same content is kept in `README.md`, `CLAUDE.md`, `skills/tfscli/SKILL.md`, and `docs/architecture.md`, so -every feature has had to update the brief as one more copy. +every feature change also has to update the brief, which duplicates content kept +elsewhere. **Why deferred:** Moving the content is a separate review of each section — what is a principle and stays, what is behaviour and is already covered elsewhere — and is not needed to state the purpose of the document. From 952c11a0b5d85f7fa6ec4d7b85027fa4d62ff25a Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 20:55:33 +0300 Subject: [PATCH 3/6] Keep accepted work in a backlog instead of placeholder tasks files Work accepted for later was kept as Active tasks files holding a single placeholder task to be broken down when its turn came. The tasks skill has no such stage: a breakdown made in advance goes stale, most of the effort before a start is discussion rather than tasks, and with several Active files its mode detection could never pick one on its own. A fourth process skill, backlog, now owns docs/backlog.md: accepted work in priority order, each entry carrying its goal, the decisions already made, and an optional trigger. The three API domains and the HTML quirks work move there, and their tasks files are removed; none had a resolved task. HTML quirks was the only file in the old format, so the exception for that format goes with it. The tasks skill now refuses to create a file for work that does not start now and points to wherever the project keeps planned work, without naming the backlog skill, which a user of tasks may not have. It also lets the plan change during execution: Pending tasks may be added, edited, reordered, or removed with the user's agreement, Done tasks are never rewritten, and task numbers are identifiers rather than order. The tech-debt format gains an optional Fix notes field, so that what is already known about a fix no longer has to be folded into the trigger; TD-07 and TD-08 are rewritten to use it. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Piji2RRZC6jeJ51vEorrNJ --- .claude/skills/backlog/SKILL.md | 98 +++++++++++++++++++ .claude/skills/tasks/SKILL.md | 46 +++++++-- .claude/skills/tech-debt/SKILL.md | 10 +- CLAUDE.md | 6 +- CONTRIBUTING.md | 11 ++- README.md | 2 +- docs/2026-05-20-tasks-html-quirks.md | 42 -------- ...10-04-tasks-domains-3-git-pull-requests.md | 22 ----- ...10-04-tasks-domains-4-workitem-comments.md | 18 ---- docs/2026-10-04-tasks-domains-5-build.md | 19 ---- docs/architecture.md | 8 +- docs/backlog.md | 60 ++++++++++++ docs/tech-debt.md | 8 +- internal/htmlmd/doc.go | 2 +- internal/htmlmd/htmlmd_test.go | 2 +- 15 files changed, 225 insertions(+), 129 deletions(-) create mode 100644 .claude/skills/backlog/SKILL.md delete mode 100644 docs/2026-05-20-tasks-html-quirks.md delete mode 100644 docs/2026-10-04-tasks-domains-3-git-pull-requests.md delete mode 100644 docs/2026-10-04-tasks-domains-4-workitem-comments.md delete mode 100644 docs/2026-10-04-tasks-domains-5-build.md create mode 100644 docs/backlog.md diff --git a/.claude/skills/backlog/SKILL.md b/.claude/skills/backlog/SKILL.md new file mode 100644 index 0000000..f92dbbe --- /dev/null +++ b/.claude/skills/backlog/SKILL.md @@ -0,0 +1,98 @@ +--- +name: backlog +description: Keep accepted work that has not started yet in backlog.md — what belongs there, the entry format, priority order, and how an entry leaves the backlog when the work starts or is dropped. Use when work is accepted for later, or when asked to plan, note, or make a task for something that will not start now. +argument-hint: "[work to record | entry to start or drop]" +--- + +This skill maintains `backlog.md`, a single document that lists work accepted for +implementation but not started yet, and defines how entries are added, ordered, and +taken out. It assumes nothing about the project beyond the presence of a repository. + +## Project version first + +If the current repository contains `.claude/skills/backlog/SKILL.md` and that file is +not the one you are reading, read it and follow it instead of this file. + +Where the project's own documentation (for example `CONTRIBUTING.md` or `CLAUDE.md`) +sets a different convention, the project's convention wins over this skill. + +## backlog.md + +`backlog.md` records decisions to do a piece of work later, together with what has +already been decided about it. Most of the effort behind an entry is the discussion +that led to it; the entry keeps the outcome of that discussion so that it is not +repeated. An entry is not broken down into tasks: the breakdown is done when the work +starts, when it can draw on the state of the project at that time. + +**Location.** If `backlog.md` already exists in the repository, use that file and never +create a second one. If it does not exist when the first entry is recorded, create it +in the directory where the project keeps its documentation, or in `docs/` (creating it) +if the project has no such directory. + +**What goes here:** +- Work that has been accepted for implementation and is not starting now +- Work accepted on a condition that has not occurred yet, with that condition recorded + +**What does not go here:** +- Work that starts now — plan it directly, the way the project plans any change +- An idea that has not been accepted — discuss it first; record it only once accepted +- A known problem deliberately left unfixed — that is tech debt, recorded where the + project keeps it + +**Practical test:** if the answer to "are we going to do this?" is yes, and to "are we +starting now?" is no, it goes in `backlog.md`. + +## Format + +```markdown +# Backlog + +Accepted work that has not started yet, in priority order. + +### `short-name` +**Goal:** what the work achieves for the users of the project +**Context:** decisions, constraints, and open questions already established +**Trigger:** the event that must occur before the work can start +**Added:** YYYY-MM-DD, in + +### `short-name` +**Goal:** ... +**Context:** ... +**Added:** ... +``` + +**Trigger** is optional: an entry without it can start at any time. **Context** may run +to several paragraphs or a list; it is the input to planning the work when it starts. +The **Added** line names where the work was accepted — a review, a plan of work, or a +conversation. Entries have no numbers; the short name identifies an entry and is not +reused while the entry is in the file. + +## Order + +The order of entries is their priority: the entry nearest the top whose trigger, if +any, has occurred is the next to start. A new entry goes where its priority puts it, +not at the end by default; ask the user when the position is not evident. + +## Adding and changing an entry + +Add an entry when work is accepted for later — in a discussion, a review, or while +planning or doing other work. Before writing it, show the entry and its position to the +user. The entry goes into the same commit as the change that led to the decision, or +into a commit of its own when there is no such change. + +An entry is edited when a later discussion changes what was decided: the goal, the +context, the trigger, or the position. It records the current decision, not the +history of how it was reached. + +## Taking an entry out + +An entry leaves the backlog in one of two ways: + +- **Started.** The work is planned the way the project plans any change, with the + entry's goal and context as the input. The entry is removed in the same commit that + creates that plan. +- **Dropped.** When the work is no longer wanted, the entry is removed, and the commit + message states why. + +Either way, the entry is deleted rather than marked; its text remains in the repository +history. `backlog.md` stays in place when it becomes empty. diff --git a/.claude/skills/tasks/SKILL.md b/.claude/skills/tasks/SKILL.md index afb0db2..d970354 100644 --- a/.claude/skills/tasks/SKILL.md +++ b/.claude/skills/tasks/SKILL.md @@ -1,6 +1,6 @@ --- name: tasks -description: Universal task-file workflow — create a structured tasks file from a feature/request and execute it step by step, tracking what is done vs. pending in any project. No project-specific assumptions. +description: Universal task-file workflow — create a structured tasks file for work that starts now and execute it step by step, tracking what is done vs. pending in any project. No project-specific assumptions. argument-hint: "[feature description to break down | path to a tasks file]" --- @@ -25,7 +25,8 @@ Decide what to do from the user's request and the current context: and exactly one `Active` file exists in the tasks directory (see "The tasks file") → **Execute** mode. - A feature or request description is given and no matching file exists → **Create** - mode (breakdown), then offer to start executing. + mode (breakdown), then offer to start executing. Work that is not to start now does + not get a tasks file (see "Create mode"). - Ambiguous (e.g. several active files, or unclear whether to create or execute) → ask the user one short question before proceeding. @@ -90,19 +91,28 @@ self-evident and needs no marker. ## Create mode (breakdown) -1. Turn the feature/request into a complete, ordered list of **atomic** tasks — each +A tasks file is created when the work starts, not in advance: most of the effort before +that is discussion and decisions, and a breakdown made ahead of time goes stale. + +1. Confirm that the work starts now. If it does not — the user wants it recorded, + planned, or kept for later — do not create a tasks file. Record it where the project + keeps planned work, if it has such a place; otherwise ask the user where it should + go. If the work was recorded there earlier, use that record as the input to the + breakdown and take it out as that place's rules require. +2. Turn the feature/request into a complete, ordered list of **atomic** tasks — each one achievable in a single focused session, with a definition of done that can be checked. -2. Propose the task structure to the user and let them adjust before writing anything. -3. Write the file to the tasks directory with header `Active` and every task `Pending`. -4. Offer to start executing the first task. +3. Propose the task structure to the user and let them adjust before writing anything. +4. Write the file to the tasks directory with header `Active` and every task `Pending`, + numbered `TASK-01`, `TASK-02`, … in order. +5. Offer to start executing the first task. ## Execute mode (tracking discipline) 1. The next task is the one already `In progress`, if any — for example, one left unfinished by an interrupted session; otherwise it is the topmost `Pending` one, and when you start working on it, set its status to `In progress`. No decision is - required either way. Do not touch the other `Pending` tasks. + required either way. Do not start or mark the other `Pending` tasks. 2. Do the work for that one task only — do not run ahead into later tasks. 3. When its definition of done is met, set its status to `Done`. 4. **Same-commit rule:** when the task's work is committed, the updated tasks file goes @@ -111,12 +121,32 @@ self-evident and needs no marker. for; it only governs how the file participates when a commit happens. 5. When the last task is resolved: change the header to `Archived` and move the file to the `archive/` subdirectory — in the same commit as that task's work. -6. If a task is abandoned, mark it `Skipped — ` rather than deleting it. +6. When the work shows that the plan is wrong, change it as described in "Changing + the plan". + +## Changing the plan + +The `Pending` tasks are a plan, not a record, and the plan changes when the work shows +it is wrong: a task turns out to be needed, a description contains a mistake, two tasks +contradict each other, or a task is redundant. A task whose outcome is a decision often +determines the tasks that follow it; those are added once the decision is made. + +- `Pending` tasks may be added, edited, reordered, or removed, and the Context section + may be updated. Propose every such change to the user before writing it, as when + creating the file. +- `Done` tasks are not rewritten: they record what was done, and commits refer to them. +- A task that was a mistake in the plan — a duplicate, a contradiction, a task not + needed — is removed. A task that is deliberately not done, where the reason is worth + knowing later, is marked `Skipped — ` instead. +- Task numbers identify tasks and do not express order. A number is never changed or + reused; a new task takes the next unused number and is placed where it is to be + done. The order of execution is the order in the file. ## Invariants - Tasks are atomic; work on one at a time. - Never leave a finished task unmarked — the file is the source of truth for progress. +- `Done` tasks are never rewritten; `Pending` tasks change when the plan proves wrong. - The tasks file travels with the work it describes in a single commit. - Archive the file (header + move to `archive/`) once every task is resolved. - Require no particular project files or tooling; follow the project's documented diff --git a/.claude/skills/tech-debt/SKILL.md b/.claude/skills/tech-debt/SKILL.md index a178f25..7fb5cb7 100644 --- a/.claude/skills/tech-debt/SKILL.md +++ b/.claude/skills/tech-debt/SKILL.md @@ -50,6 +50,7 @@ fix it. **Problem:** what is wrong **Why deferred:** reasoning **Trigger:** the event that makes the fix necessary (a new feature, a performance issue) +**Fix notes:** what is already known about the fix (optional) **Added:** YYYY-MM-DD, in --- @@ -66,6 +67,12 @@ fix it. Numbers (`TD-NN`) are assigned sequentially and never reused. The **Added** line names where the decision was made — a review, a plan of work, or a conversation. +**Trigger** names only the event, not what to do when it occurs. What is already known +about the fix — findings, constraints, and the steps worked out when the decision to +defer was made — goes into **Fix notes**, so that it is not rediscovered later. The +field may run to several paragraphs or a list, and is omitted when nothing is known +yet. + ## Adding an item When a problem is deliberately deferred — during a review, while planning or doing @@ -78,7 +85,8 @@ review fixes, or into a commit of its own when there is no such change. An item is closed in one of two ways: - **Fixed.** When the item is ready to be fixed, it becomes a regular piece of work, - planned and carried out the way the project plans any change. When the work is done, + planned and carried out the way the project plans any change, with the item's + **Fix notes** as an input to the planning. When the work is done, the item is closed with `fixed in` and a reference to where the fix can be found. - **Dropped.** When a review of the item shows that no change is needed — the problem does not occur in practice, or it turns out to be a decision rather than a deferred diff --git a/CLAUDE.md b/CLAUDE.md index 08f6953..37b9dcb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,13 +4,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Process -The workflow is defined by three process skills kept in the repository under `.claude/skills/`: `tasks` (task breakdown and execution), `changelog` (`CHANGELOG.md` entries and releases), and `tech-debt` (deferred compromises). They are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. `CONTRIBUTING.md` records the choices they leave to the project ("Process") and the purpose of each project document ("Project documents"). - -Note: tasks files created before the move to skills (e.g. `docs/2026-05-20-tasks-html-quirks.md`) follow an older format with task types and emoji statuses; keep their existing format when updating them. +The workflow is defined by four process skills kept in the repository under `.claude/skills/`: `tasks` (task breakdown and execution), `backlog` (accepted work not started yet), `changelog` (`CHANGELOG.md` entries and releases), and `tech-debt` (deferred compromises). They are authoritative — invoke the matching one before doing the work; this CLAUDE.md intentionally does not duplicate their content. `CONTRIBUTING.md` records the choices they leave to the project ("Process") and the purpose of each project document ("Project documents"). ## Project state -The MVP is implemented: `tfscli wit work-items get` works end to end, `tfscli wit work-items list` and `tfscli wit work-items get-batch` read several work items by id, `tfscli wit wiql query-by-wiql` finds work item ids with a WIQL query, and the module has one package per architecture module (see the "Project Structure" section of `docs/architecture.md`). Release 0.0.5, which predates the current command names, has been run against a live TFS instance: `auth login` and reading one work item (`get`) work there; `list`, `get-batch`, and `query-by-wiql` have not been run against a live server yet; the error paths and rich-text rendering on real data have not been checked yet — see the "Status" and "Known limitations" sections of `README.md`. Further work goes through tasks files per the `tasks` skill. +The MVP is implemented: `tfscli wit work-items get` works end to end, `tfscli wit work-items list` and `tfscli wit work-items get-batch` read several work items by id, `tfscli wit wiql query-by-wiql` finds work item ids with a WIQL query, and the module has one package per architecture module (see the "Project Structure" section of `docs/architecture.md`). Release 0.0.5, which predates the current command names, has been run against a live TFS instance: `auth login` and reading one work item (`get`) work there; `list`, `get-batch`, and `query-by-wiql` have not been run against a live server yet; the error paths and rich-text rendering on real data have not been checked yet — see the "Status" and "Known limitations" sections of `README.md`. Accepted work that has not started is listed in `docs/backlog.md`; work in progress goes through tasks files per the `tasks` skill. Read these before the corresponding kind of change (the full list of project documents is in "Project documents" in `CONTRIBUTING.md`): diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1148e76..3a5256d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,19 +99,23 @@ Each document has one job, and new information goes to the document whose job it | `CHANGELOG.md` | User-visible changes, per release | Any user-visible change | | `CONTRIBUTING.md` | How the project is built, checked, released, and worked on | The build, the rules, or the process change | | `CLAUDE.md` | Guidance for AI agents working in the repository | Anything it summarises changes | +| `docs/backlog.md` | Accepted work not started yet, in priority order | Work is accepted, started, or dropped | | `docs/tech-debt.md` | Consciously deferred problems | A problem is deferred or closed | | `docs/YYYY-MM-DD-tasks-.md` | The plan and progress of one unit of work | The work progresses; archived to `docs/archive/` when done | | `.claude/skills/` | The process rules below | The process changes | ## Process -Work is planned and tracked with three process skills kept in the repository. Each is a +Work is planned and tracked with four process skills kept in the repository. Each is a plain Markdown file and states the full rules, for people as much as for AI agents, completed by the project choices listed below: - `.claude/skills/tasks/SKILL.md` — tasks files: a unit of work as an ordered list of atomic tasks with a definition of done and a status each, committed together with the work it describes and archived when done. +- `.claude/skills/backlog/SKILL.md` — `docs/backlog.md`: work accepted for later, with + the decisions already made about it, in priority order; broken down into a tasks file + only when it starts. - `.claude/skills/changelog/SKILL.md` — `CHANGELOG.md`: Keep a Changelog 1.1.0 without comparison links, user-visible changes only, one sentence per entry. - `.claude/skills/tech-debt/SKILL.md` — `docs/tech-debt.md`: what counts as a deferred @@ -119,9 +123,8 @@ completed by the project choices listed below: The skills leave a few choices to the project. In tfscli: -- Tasks files live in `docs/`, and archived ones in `docs/archive/`. The fix of a tech - debt entry is planned as a tasks file. `docs/2026-05-20-tasks-html-quirks.md` predates - the current format and keeps its own — task types and emoji statuses — when updated. +- Tasks files live in `docs/`, and archived ones in `docs/archive/`. Work taken from the + backlog and the fix of a tech debt entry are planned as a tasks file. - The changelog preamble names Semantic Versioning, as declared in "Choosing the version", and the version heading is inserted by the release workflow (see "Releasing"). diff --git a/README.md b/README.md index 19fe022..55f5e13 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Not present in v1: write operations (out of scope) and JSON output (`--json`, pl ### Known limitations - **HTML tables collapse.** The markdown converter runs on library defaults, which have no table support: a `` becomes its cell text run together, without separators. A work item whose Description holds a table renders unreadably. -- **Rich-text noise is unhandled.** @-mentions, attachment links, Word- and Outlook-pasted markup, and work-item references are converted literally, with whatever wrapper markup TFS stored. Fixing this needs samples from a real instance and is tracked in `docs/2026-05-20-tasks-html-quirks.md`. +- **Rich-text noise is unhandled.** @-mentions, attachment links, Word- and Outlook-pasted markup, and work-item references are converted literally, with whatever wrapper markup TFS stored. Fixing this needs samples from a real instance and is planned in `docs/backlog.md`. - **Servers with anonymous access are not supported.** `auth login` has not been tested against a server that admits anonymous requests, such as Azure DevOps Server with public projects enabled. On such a server an invalid PAT may pass the login check and be stored, and the other commands would then read as the anonymous user, seeing less, without an error. ## Installation diff --git a/docs/2026-05-20-tasks-html-quirks.md b/docs/2026-05-20-tasks-html-quirks.md deleted file mode 100644 index 7e1ccd9..0000000 --- a/docs/2026-05-20-tasks-html-quirks.md +++ /dev/null @@ -1,42 +0,0 @@ -## 2026-05-20-tasks-html-quirks.md - -**Status:** Active -**Trigger:** A decision to collect rich-text samples from a live TFS instance. The work in this file is deliberately deferred until then — see the "HTML quirks" decision in the conversation that produced the Architecture section of `architecture.md`. A live connection is no longer the blocker: release 0.0.5 ran `auth login` and the single work item read (now `wit work-items get`) successfully against a live server. - -### Contracts - -No new API contracts. Scope is limited to the `htmlmd` module and golden tests around it. - -### Note on task types - -This file predates the move of the process into the global `tasks` skill and keeps the older format: task types (Regular, Smoke, Review, Docs) and emoji statuses. Under that format a tasks file normally contains all four task types. This file deliberately omits the Smoke type: there is no running code to smoke-test — the feature is fixtures (`testdata/`) plus golden tests plus library-plugin rules. TASK-01 already requires a live-TFS round-trip to harvest the fixtures, which is the only end-to-end interaction the feature can produce; the golden tests in TASK-02 are the verification mechanism instead of a smoke check. - ---- - -### TASK-01 `collect-html-samples` -**Type:** Regular -**Description:** Connect to a live TFS instance and dump the raw HTML of 10–20 work item rich-text fields, with coverage across `System.Description`, `Microsoft.VSTS.TCM.ReproSteps`, `Microsoft.VSTS.TCM.SystemInfo`, and `Microsoft.VSTS.Common.AcceptanceCriteria`. Aim for variety: items with @-mentions, items with attachments, items with Word- or Outlook-pasted content, items linking to other work items. Store the samples as fixtures under `internal/htmlmd/testdata/` (one file per sample, `.html` extension). Add a sibling `README.md` enumerating each file with one-line provenance — work item type and which quirks it exhibits. -**Definition of done:** ≥10 sample HTML files committed under `internal/htmlmd/testdata/`, with a `README.md` enumerating them. -**Status:** ⬜ Pending - -### TASK-02 `golden-tests-baseline` -**Type:** Regular -**Description:** For each sample collected in TASK-01, add a golden test that runs the current `htmlmd.Convert` over it and records the output as `.expected.md` next to the input. Goal here is to capture today's behaviour, not to improve it — golden tests will signal when changes in TASK-03 take effect. Standard `-update` flag pattern to regenerate expectations. -**Definition of done:** all golden tests pass; running with `-update` regenerates expected files. -**Status:** ⬜ Pending - -### TASK-03 `identify-and-fix-noise` -**Type:** Regular -**Description:** Inspect the golden outputs from TASK-02. Classify noise: mentions rendering as `[@name](#)`, attachment links pointing to authenticated URLs, Word-paste leftovers (``, `MsoNormal`, mso-* attributes), work-item references rendering as long URLs. Known before the samples arrive: the library's default rule set has no table support, so `
` markup collapses to its concatenated cell text — enabling `plugin/table` belongs to this task. For each chosen class, add a rule via the library's plugin API. Update golden expectations in the same commit. Out of scope: anything that requires additional TFS API calls (e.g. fetching attachment filenames from the attachments endpoint) — that becomes a separate feature. -**Definition of done:** the list of noise classes addressed is recorded both in the commit message and in this tasks file (append a short bullet list under this DoD when the task completes); each rule has a corresponding golden diff demonstrating its effect. -**Status:** ⬜ Pending - -### TASK-04 `review` -**Type:** Review -**Covers:** TASK-01, TASK-02, TASK-03 -**Status:** ⬜ Pending - -### TASK-05 `docs` -**Type:** Docs -**Description:** Update `README.md`, `CHANGELOG.md`, and the "Known limitations" section of `skills/tfscli/SKILL.md` with a one-line user-facing note that HTML rendering now handles the relevant TFS patterns (mentions, attachments, Word paste, work-item refs — whichever were addressed). `README.md` and `SKILL.md` both carry the limitation and must stop claiming it together. No technical detail in `CHANGELOG.md`; see the `changelog` skill. -**Status:** ⬜ Pending diff --git a/docs/2026-10-04-tasks-domains-3-git-pull-requests.md b/docs/2026-10-04-tasks-domains-3-git-pull-requests.md deleted file mode 100644 index 86a90a2..0000000 --- a/docs/2026-10-04-tasks-domains-3-git-pull-requests.md +++ /dev/null @@ -1,22 +0,0 @@ -# 2026-10-04-tasks-domains-3-git-pull-requests.md - -**Status:** Active - -## Context - -Third of five planned API domains, numbered in the order they are to be taken. -An agent sees the code through the local `git`, but pull requests, review -comments, and linked work items exist only on the server; the "address the -review comments" scenario is impossible without them. The domain is of no use -on TFVC projects. Pull request threads appeared only in TFS 2017; under -"Server compatibility is preserved" in `docs/project-brief.md` they should be -optional, failing with a clear error on an older server while everything else -keeps working. - ---- - -### TASK-01 `git-pull-requests` -**Description:** Read pull requests, their comment threads, and linked work -items. To be broken down into atomic tasks before work starts. -**Definition of done:** The task is broken down into atomic tasks in this file. -**Status:** Pending diff --git a/docs/2026-10-04-tasks-domains-4-workitem-comments.md b/docs/2026-10-04-tasks-domains-4-workitem-comments.md deleted file mode 100644 index 16785f5..0000000 --- a/docs/2026-10-04-tasks-domains-4-workitem-comments.md +++ /dev/null @@ -1,18 +0,0 @@ -# 2026-10-04-tasks-domains-4-workitem-comments.md - -**Status:** Active - -## Context - -Fourth of five planned API domains, numbered in the order they are to be taken. -This extends the existing work item domain rather than adding a new one. The -Comments API exists only on recent servers; on older ones the discussion is -kept in the revisions of the `System.History` field. - ---- - -### TASK-01 `workitem-comments` -**Description:** Read the discussion of a work item. To be broken down into -atomic tasks before work starts. -**Definition of done:** The task is broken down into atomic tasks in this file. -**Status:** Pending diff --git a/docs/2026-10-04-tasks-domains-5-build.md b/docs/2026-10-04-tasks-domains-5-build.md deleted file mode 100644 index 917dc3c..0000000 --- a/docs/2026-10-04-tasks-domains-5-build.md +++ /dev/null @@ -1,19 +0,0 @@ -# 2026-10-04-tasks-domains-5-build.md - -**Status:** Active - -## Context - -Fifth of five planned API domains, numbered in the order they are to be taken. -Scenario: a CI build failed and the agent is to find out why, locating the -failed step through the timeline and reading its log. Less frequent than the -domains before it, since many on-prem teams run CI outside TFS Build. The -volume of logs needs a decision: the whole log or only the failed step. - ---- - -### TASK-01 `build-status-and-logs` -**Description:** Read builds, their timeline, and their logs. To be broken down -into atomic tasks before work starts. -**Definition of done:** The task is broken down into atomic tasks in this file. -**Status:** Pending diff --git a/docs/architecture.md b/docs/architecture.md index 9e224ef..35b10e2 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -177,7 +177,7 @@ This section describes the conceptual module structure, their responsibilities, - **apiclient** — wraps `net/http`. Builds URLs from `Config.URL + Collection + path`, adding `api-version` only when `APIVersion` is set; without it the server answers at the version it chooses. Sets `Authorization: Basic base64(":")` on every request. Configures TLS using `CABundle` (appended to system root pool) and `InsecureSkipVerify`. Hooks the logger via a `RoundTripper` — that transport is the single call site of `LogRequest`, so every outgoing request is logged exactly once and no other module logs HTTP traffic. Classifies HTTP outcomes into the stable error categories defined in the brief (`auth`, `not_found`, `forbidden`, `server`, `config`, `network`). - **workitem** — domain logic for Work Items: Get Work Item, Work Items - List, and Get Work Items Batch. Owns the `WorkItem`/`Field` types, the `BatchRequest`/`Batch` types for reading several work items, and the allowlist of fields known to contain HTML (`System.Description`, `Microsoft.VSTS.TCM.ReproSteps`, `Microsoft.VSTS.TCM.SystemInfo`, `Microsoft.VSTS.Common.AcceptanceCriteria`, …). After unmarshalling, tags each field with its `FieldKind`. For several work items, keeps the server's order and reports the requested ids the server did not return. Returns raw values — does not perform markdown conversion. - **wiql** — domain logic for Wiql: Query By Wiql. Owns the `Request` and `Result` types. Builds the path at collection level, under a project, or under a project and a team; passes the query text through unchanged and sends `$top` and `timePrecision` only when they are given. Reads the query type, `asOf`, the reference names of the columns, and either the work item ids of a flat query or the relations of a link query, keeping the server's order. Does not read the work items themselves: that is a separate call through `workitem`, made by the caller. -- **htmlmd** — thin wrapper over `github.com/JohannesKaufmann/html-to-markdown/v2`. One method: `Convert(html string) (string, error)`. v1 uses library defaults only; the wrapper is the extension point where TFS-specific rules will be registered once real HTML samples have been collected (see `2026-05-20-tasks-html-quirks.md`). +- **htmlmd** — thin wrapper over `github.com/JohannesKaufmann/html-to-markdown/v2`. One method: `Convert(html string) (string, error)`. v1 uses library defaults only; the wrapper is the extension point where TFS-specific rules will be registered once real HTML samples have been collected (see the `html-quirks` entry in `docs/backlog.md`). - **tfserr** — typed error `Error{Category, Message, HTTPStatus, Cause}` with the stable category set from the brief. Provides `Print(err, w)` writing `Error [category]: message (HTTP status)` and `ExitCode(err)` mapping to a non-zero process exit code (v1: 1 for every category; the API leaves room for per-category exit codes later without breaking the contract). - **log** — `Logger` interface with two implementations: `noop` (default) and `stderr` (selected by `--verbose` / `TFSCLI_VERBOSE=1`). Methods: `LogRequest(method, url, status, dur)` and `Warn(msg)`. The logger interface accepts only these four request fields — PAT and the `Authorization` header are never passed in, so they cannot leak through the logger by construction. @@ -320,7 +320,7 @@ type Result struct { - **New API domain** (repos, builds): add a new domain module and register its resource command under the area command, adding the area command (e.g. `git`) if it does not exist yet. No edits to `apiclient`, `config`, or `tfserr`. - **`--json` output**: introduce a `Renderer` interface in the cli layer; add a `JSONRenderer` that consumes `*WorkItem` directly. The markdown printer becomes the other implementation. Local refactor confined to the cli layer. -- **TFS-specific HTML quirks** (mentions, attachment links, Word paste leftovers): add rules in `htmlmd` plus golden tests on real samples. Tracked in `2026-05-20-tasks-html-quirks.md`. +- **TFS-specific HTML quirks** (mentions, attachment links, Word paste leftovers): add rules in `htmlmd` plus golden tests on real samples. Planned as the `html-quirks` entry in `docs/backlog.md`. --- @@ -338,8 +338,8 @@ Standard Go CLI layout: a single binary entry point under `cmd/`, all implementa |---|---| | `cmd/` | Binary entry points, one subdirectory per binary. v1 has a single binary, `tfscli`; its `main` only wires modules together and delegates to the cli package. | | `internal/` | All implementation packages, one per architecture module. Tests sit next to the code (`_test.go`); fixtures live in per-package `testdata/` directories. | -| `docs/` | Design documents (`project-brief.md`, `architecture.md`), tasks files, tech-debt register. Not part of the shipped binary. | +| `docs/` | Design documents (`project-brief.md`, `architecture.md`), tasks files, backlog, tech-debt register. Not part of the shipped binary. | | `skills/` | The agent skill shipped beside the binary, `skills/tfscli/SKILL.md`, in the Agent Skills format. Copied into the archive by goreleaser and installed by copying the directory into an agent's skills path. | -| `.claude/` | Claude Code project settings and the process skills in `.claude/skills/` (tasks, changelog, tech-debt). Not shipped, and unrelated to `skills/`, which holds the skill for users of tfscli. | +| `.claude/` | Claude Code project settings and the process skills in `.claude/skills/` (tasks, backlog, changelog, tech-debt). Not shipped, and unrelated to `skills/`, which holds the skill for users of tfscli. | Deliberately absent: `pkg/` (nothing is exported), `vendor/` (dependencies resolve through the module proxy), a separate `test/` tree (Go convention keeps tests beside the code they test). diff --git a/docs/backlog.md b/docs/backlog.md new file mode 100644 index 0000000..4ace4ed --- /dev/null +++ b/docs/backlog.md @@ -0,0 +1,60 @@ +# Backlog + +Accepted work that has not started yet, in priority order. + +### `git-pull-requests` +**Goal:** An agent can read pull requests, their comment threads, and the work items +linked to them. +**Context:** The API domains in this backlog are ordered by how much each lets an agent +do without being handed an id by a person. An agent sees the code through the local +`git`, but pull requests, review comments, and linked work items exist only on the +server; the "address the review comments" scenario is impossible without them. The +domain is of no use on TFVC projects. Pull request threads appeared only in TFS 2017; +under "Server compatibility is preserved" in `docs/project-brief.md` they should be +optional, failing with a clear error on an older server while everything else keeps +working. +**Added:** 2026-10-04, in conversation on the next API domains + +### `workitem-comments` +**Goal:** An agent can read the discussion of a work item. +**Context:** This extends the existing work item domain rather than adding a new one. +The Comments API exists only on recent servers; on older ones the discussion is kept in +the revisions of the `System.History` field. +**Added:** 2026-10-04, in conversation on the next API domains + +### `build-status-and-logs` +**Goal:** An agent can read builds, their timeline, and their logs. +**Context:** Scenario: a CI build failed and the agent is to find out why, locating the +failed step through the timeline and reading its log. Less frequent than the domains +before it, since many on-prem teams run CI outside TFS Build. The volume of logs needs +a decision: the whole log or only the failed step. +**Added:** 2026-10-04, in conversation on the next API domains + +### `html-quirks` +**Goal:** Rich-text fields such as Description and Repro Steps are printed without the +TFS-specific markup noise they are stored with. +**Context:** The scope is the `htmlmd` package and golden tests around it; no new API +contracts. Decisions already made: +- The rules are derived from real data: 10–20 raw HTML samples of + `System.Description`, `Microsoft.VSTS.TCM.ReproSteps`, + `Microsoft.VSTS.TCM.SystemInfo`, and `Microsoft.VSTS.Common.AcceptanceCriteria`, + covering @-mentions, attachments, Word- and Outlook-pasted content, and links to + other work items, stored as fixtures in `internal/htmlmd/testdata/` with a + `README.md` giving the provenance of each. +- Golden tests first record the current output of `htmlmd.Convert` on the samples, + with the usual `-update` flag, so that each rule added afterwards shows as a golden + diff. +- The expected noise classes: mentions rendered as `[@name](#)`, attachment links to + authenticated URLs, Word-paste leftovers (``, `MsoNormal`, `mso-*` attributes), + and work item references rendered as long URLs. Known before the samples arrive: the + library's default rule set has no table support, so `
` collapses to its + concatenated cell text; enabling `plugin/table` belongs to this work. +- Out of scope: anything that needs additional TFS API calls, such as fetching + attachment file names; that is a separate feature. +- The limitation is stated in "Known limitations" in both `README.md` and + `skills/tfscli/SKILL.md`, which must stop claiming it together. +**Trigger:** A decision to collect rich-text samples from a live TFS instance. A live +connection is no longer the blocker: release 0.0.5 ran `auth login` and reading one +work item against a live server. +**Added:** 2026-05-20, in the conversation that produced the Architecture section of +`docs/architecture.md` diff --git a/docs/tech-debt.md b/docs/tech-debt.md index 54268d9..66b4ea4 100644 --- a/docs/tech-debt.md +++ b/docs/tech-debt.md @@ -9,8 +9,8 @@ enforce. **Why deferred:** The repository is private on the free plan, where GitHub does not enforce rulesets. Protection becomes possible only when the repository is made public or the account moves to GitHub Pro, and neither has been decided. -**Trigger:** The repository becomes public, or the account moves to GitHub Pro. The -work found necessary at that point: +**Trigger:** The repository becomes public, or the account moves to GitHub Pro. +**Fix notes:** - A branch ruleset on the default branch: pull request required with 0 approvals, the `check` status check from GitHub Actions required with branches up to date, linear history, deletions and force pushes blocked; only rebase merging allowed @@ -45,8 +45,8 @@ elsewhere. principle and stays, what is behaviour and is already covered elsewhere — and is not needed to state the purpose of the document. **Trigger:** the next change that would otherwise add feature behaviour to the brief. -The normative parts stay as principles: the credential model, the configuration -precedence, and the error format and its stability. +**Fix notes:** The normative parts stay as principles: the credential model, the +configuration precedence, and the error format and its stability. **Added:** 2026-10-05, in conversation on the purpose of the project documents --- diff --git a/internal/htmlmd/doc.go b/internal/htmlmd/doc.go index 2a2128e..586fba7 100644 --- a/internal/htmlmd/doc.go +++ b/internal/htmlmd/doc.go @@ -1,4 +1,4 @@ // Package htmlmd is a thin wrapper over html-to-markdown/v2 exposing // Convert(html) (string, error). It is the extension point for -// TFS-specific conversion rules (see docs/2026-05-20-tasks-html-quirks.md). +// TFS-specific conversion rules (see the html-quirks entry in docs/backlog.md). package htmlmd diff --git a/internal/htmlmd/htmlmd_test.go b/internal/htmlmd/htmlmd_test.go index 596bd55..1ac4df3 100644 --- a/internal/htmlmd/htmlmd_test.go +++ b/internal/htmlmd/htmlmd_test.go @@ -5,7 +5,7 @@ import "testing" // The expectations below record the library defaults, which is all v1 uses. // They are a smoke check that the wrapper is wired to the converter — not an // endorsement of any particular rendering. TFS-specific rules and golden tests -// on real samples arrive with docs/2026-05-20-tasks-html-quirks.md. +// on real samples arrive with the html-quirks entry in docs/backlog.md. func TestConvert(t *testing.T) { tests := []struct { name string From 1eb69647fa9174ad4bb7f38828f675f1db33f08e Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 21:06:23 +0300 Subject: [PATCH 4/6] Explain why the process lives in repository files and portable skills Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013xePd54F4w9BtuyAbVQUnD --- CONTRIBUTING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a5256d..648ff60 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -121,6 +121,17 @@ completed by the project choices listed below: - `.claude/skills/tech-debt/SKILL.md` — `docs/tech-debt.md`: what counts as a deferred problem, the entry format, and closing an entry as fixed or dropped. +The plans, the backlog, and the tech debt are kept as files in the repository rather +than in an issue tracker, so that each decision is versioned together with the change it +concerns, is reviewed in the same pull request, and can be read by an AI agent without +access to an external service. + +The skills are written to be portable: the same files are also used outside this +repository, which is why they make no assumptions about the project. A copy installed +as a personal skill takes precedence over the project one in Claude Code, so each skill +opens with a "Project version first" section that sends the reader to the repository +copy when one exists; in the repository copy that section has no effect. + The skills leave a few choices to the project. In tfscli: - Tasks files live in `docs/`, and archived ones in `docs/archive/`. Work taken from the From 9fd8ff41d1f7f39add11b9a6f30d28077c0d0103 Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 21:14:46 +0300 Subject: [PATCH 5/6] Close the gaps the review found in the backlog and process skills The review read the skills as an agent would, literally, and found rules that contradict each other or leave a case uncovered. "Plan" meant both the breakdown of work that starts now and work kept for later. It now means only the breakdown; the backlog is "accepted work that has not started" everywhere, and "plan" is gone from the backlog skill's triggers. Its precondition field is renamed from Trigger to Blocked until, since a tech-debt Trigger makes a fix necessary while the backlog field only permits a start. The tasks skill now covers what the previous change left open: archiving when the last Pending tasks are removed rather than resolved, postponing an Active file (deleted when everything moves to the backlog, archived with its unresolved tasks skipped when it holds work already done), and a request for the next work when no Active file exists. Pending tasks may be renumbered to follow their order; Done and Skipped ones keep their numbers, since commits refer to them. The tech-debt skill sends accepted future work to the backlog, as the backlog skill already sends deferred problems to tech debt; shows an entry to the user before writing it and allows editing it, as the backlog does; says which commit closes an entry; and uses "entry" and `short-name` like the other skills. The changelog keeps the six Keep a Changelog sections. The four-section rule CONTRIBUTING.md used to state went away with the move into skills; "Choosing the version" now says that a Deprecated entry does not make a release breaking. The Process list there names each skill and its document only, since its summaries were what drifted from the skills. The ordering reason of the API domains is repeated in each domain entry of the backlog, so it survives when the first one starts. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Piji2RRZC6jeJ51vEorrNJ --- .claude/skills/backlog/SKILL.md | 35 +++++++++------- .claude/skills/tasks/SKILL.md | 34 +++++++++++----- .claude/skills/tech-debt/SKILL.md | 67 ++++++++++++++++++------------- CONTRIBUTING.md | 20 ++++----- README.md | 2 +- docs/architecture.md | 2 +- docs/backlog.md | 35 ++++++++-------- 7 files changed, 111 insertions(+), 84 deletions(-) diff --git a/.claude/skills/backlog/SKILL.md b/.claude/skills/backlog/SKILL.md index f92dbbe..77f810b 100644 --- a/.claude/skills/backlog/SKILL.md +++ b/.claude/skills/backlog/SKILL.md @@ -1,6 +1,6 @@ --- name: backlog -description: Keep accepted work that has not started yet in backlog.md — what belongs there, the entry format, priority order, and how an entry leaves the backlog when the work starts or is dropped. Use when work is accepted for later, or when asked to plan, note, or make a task for something that will not start now. +description: Keep accepted work that has not started yet in backlog.md — what belongs there, the entry format, priority order, and how an entry leaves the backlog when the work starts or is dropped. Use when work is accepted for later, or when asked to record, note, or make a task for something that will not start now. argument-hint: "[work to record | entry to start or drop]" --- @@ -32,9 +32,11 @@ if the project has no such directory. **What goes here:** - Work that has been accepted for implementation and is not starting now - Work accepted on a condition that has not occurred yet, with that condition recorded +- Work that started and is postponed before it is finished **What does not go here:** -- Work that starts now — plan it directly, the way the project plans any change +- Work that starts now — break it down and start it the way the project handles any + change - An idea that has not been accepted — discuss it first; record it only once accepted - A known problem deliberately left unfixed — that is tech debt, recorded where the project keeps it @@ -52,7 +54,7 @@ Accepted work that has not started yet, in priority order. ### `short-name` **Goal:** what the work achieves for the users of the project **Context:** decisions, constraints, and open questions already established -**Trigger:** the event that must occur before the work can start +**Blocked until:** the event that must occur before the work can start **Added:** YYYY-MM-DD, in ### `short-name` @@ -61,36 +63,39 @@ Accepted work that has not started yet, in priority order. **Added:** ... ``` -**Trigger** is optional: an entry without it can start at any time. **Context** may run -to several paragraphs or a list; it is the input to planning the work when it starts. +**Blocked until** is optional: an entry without it can start at any time. It names a +precondition, not a deadline — the work does not have to start when it occurs. +**Context** may run to several paragraphs or a list; it is the input to planning the +work when it starts. The **Added** line names where the work was accepted — a review, a plan of work, or a conversation. Entries have no numbers; the short name identifies an entry and is not reused while the entry is in the file. ## Order -The order of entries is their priority: the entry nearest the top whose trigger, if -any, has occurred is the next to start. A new entry goes where its priority puts it, -not at the end by default; ask the user when the position is not evident. +The order of entries is their priority: the entry nearest the top that is not blocked +is the next to start. A new entry goes where its priority puts it, not at the end by +default; ask the user when the position is not evident. ## Adding and changing an entry Add an entry when work is accepted for later — in a discussion, a review, or while -planning or doing other work. Before writing it, show the entry and its position to the -user. The entry goes into the same commit as the change that led to the decision, or -into a commit of its own when there is no such change. +planning or doing other work — or when work already started is postponed; then the +entry carries the decisions made so far. Before writing it, show the entry and its +position to the user. The entry goes into the same commit as the change that led to the +decision, or into a commit of its own when there is no such change. An entry is edited when a later discussion changes what was decided: the goal, the -context, the trigger, or the position. It records the current decision, not the +context, the precondition, or the position. It records the current decision, not the history of how it was reached. ## Taking an entry out An entry leaves the backlog in one of two ways: -- **Started.** The work is planned the way the project plans any change, with the - entry's goal and context as the input. The entry is removed in the same commit that - creates that plan. +- **Started.** The work is broken down the way the project breaks down any change, with + the entry's goal and context as the input. The entry is removed in the same commit + that creates that breakdown. - **Dropped.** When the work is no longer wanted, the entry is removed, and the commit message states why. diff --git a/.claude/skills/tasks/SKILL.md b/.claude/skills/tasks/SKILL.md index d970354..78ff53f 100644 --- a/.claude/skills/tasks/SKILL.md +++ b/.claude/skills/tasks/SKILL.md @@ -27,6 +27,9 @@ Decide what to do from the user's request and the current context: - A feature or request description is given and no matching file exists → **Create** mode (breakdown), then offer to start executing. Work that is not to start now does not get a tasks file (see "Create mode"). +- The request names no new work and no `Active` file exists → propose starting the next + item from where the project keeps accepted work that has not started, if it has such + a place, as **Create** mode; otherwise ask the user what to work on. - Ambiguous (e.g. several active files, or unclear whether to create or execute) → ask the user one short question before proceeding. @@ -95,10 +98,10 @@ A tasks file is created when the work starts, not in advance: most of the effort that is discussion and decisions, and a breakdown made ahead of time goes stale. 1. Confirm that the work starts now. If it does not — the user wants it recorded, - planned, or kept for later — do not create a tasks file. Record it where the project - keeps planned work, if it has such a place; otherwise ask the user where it should - go. If the work was recorded there earlier, use that record as the input to the - breakdown and take it out as that place's rules require. + noted, or kept for later — do not create a tasks file. Record it where the project + keeps accepted work that has not started, if it has such a place; otherwise ask the + user where it should go. If the work was recorded there earlier, use that record as + the input to the breakdown and take it out as that place's rules require. 2. Turn the feature/request into a complete, ordered list of **atomic** tasks — each one achievable in a single focused session, with a definition of done that can be checked. @@ -119,8 +122,9 @@ that is discussion and decisions, and a breakdown made ahead of time goes stale. into that **same commit** — never a separate status-only commit. This skill follows the project's normal commit cadence and does not force commits the user did not ask for; it only governs how the file participates when a commit happens. -5. When the last task is resolved: change the header to `Archived` and move the file to - the `archive/` subdirectory — in the same commit as that task's work. +5. When every task in the file is resolved — the last one is done or skipped, or the + last `Pending` ones are removed — change the header to `Archived` and move the file + to the `archive/` subdirectory, in the commit that brings the file to that state. 6. When the work shows that the plan is wrong, change it as described in "Changing the plan". @@ -138,9 +142,21 @@ determines the tasks that follow it; those are added once the decision is made. - A task that was a mistake in the plan — a duplicate, a contradiction, a task not needed — is removed. A task that is deliberately not done, where the reason is worth knowing later, is marked `Skipped — ` instead. -- Task numbers identify tasks and do not express order. A number is never changed or - reused; a new task takes the next unused number and is placed where it is to be - done. The order of execution is the order in the file. +- The order of execution is the order in the file. When tasks are added, removed, or + reordered, the `Pending` tasks may be renumbered so that the numbers follow that + order; `Done` and `Skipped` tasks keep their numbers, since commits refer to them. + +### Postponing the work + +When work in an `Active` file stops before every task is resolved and is to be resumed +later, record its goal and the decisions already made where the project keeps accepted +work that has not started, if it has such a place; otherwise ask the user. Then, in the +same commit: + +- if the file holds nothing that is not carried over — no `Done` task and no record + worth keeping on its own — delete it; +- otherwise mark the unresolved tasks `Skipped — postponed` and archive the file, so + that the work already done stays on record. ## Invariants diff --git a/.claude/skills/tech-debt/SKILL.md b/.claude/skills/tech-debt/SKILL.md index 7fb5cb7..ae9f9bf 100644 --- a/.claude/skills/tech-debt/SKILL.md +++ b/.claude/skills/tech-debt/SKILL.md @@ -1,12 +1,12 @@ --- name: tech-debt -description: Record and track consciously deferred problems in tech-debt.md — what qualifies as tech debt, the TD entry format, and closing items as fixed or dropped. Use when deferring a known issue or documenting a deliberate compromise. +description: Record and track consciously deferred problems in tech-debt.md — what qualifies as tech debt, the TD entry format, and closing entries as fixed or dropped. Use when deferring a known issue or documenting a deliberate compromise. argument-hint: "[problem to record | TD-NN to close]" --- This skill maintains `tech-debt.md`, a single document that records known problems -deliberately deferred, and defines how entries are added and closed. It assumes -nothing about the project beyond the presence of a repository. +deliberately deferred, and defines how entries are added, changed, and closed. It +assumes nothing about the project beyond the presence of a repository. ## Project version first @@ -22,18 +22,20 @@ sets a different convention, the project's convention wins over this skill. that have been consciously deferred — not forgotten, but deliberately not fixed yet. **Location.** If `tech-debt.md` already exists in the repository, use that file and -never create a second one. If it does not exist when the first item is recorded, +never create a second one. If it does not exist when the first entry is recorded, create it in the directory where the project keeps its documentation, or in `docs/` (creating it) if the project has no such directory. **What goes here:** - A known issue with an explicit decision to defer it, with reasoning - A compromise made consciously during a code review -- Something that requires design or architectural thinking before implementation +- A known problem whose fix requires design or architectural thinking first **What does not go here:** - A bug with no decision to defer it — fix it now or plan it as regular work - A small cosmetic fix — either fix it immediately or ignore it +- New work accepted for later that does not fix a problem in what exists — record it + where the project keeps accepted work that has not started **Practical test:** if during a code review you would write "this is an intentional tradeoff, document it" — it goes in `tech-debt.md`. If you would write "fix this" — @@ -46,7 +48,7 @@ fix it. ## Active -### TD-03 `short name` +### TD-03 `short-name` **Problem:** what is wrong **Why deferred:** reasoning **Trigger:** the event that makes the fix necessary (a new feature, a performance issue) @@ -57,42 +59,49 @@ fix it. ## Closed -### TD-01 `short name` +### TD-01 `short-name` **Closed:** YYYY-MM-DD — fixed in -### TD-02 `short name` +### TD-02 `short-name` **Closed:** YYYY-MM-DD — dropped: ``` Numbers (`TD-NN`) are assigned sequentially and never reused. The **Added** line names where the decision was made — a review, a plan of work, or a conversation. -**Trigger** names only the event, not what to do when it occurs. What is already known -about the fix — findings, constraints, and the steps worked out when the decision to -defer was made — goes into **Fix notes**, so that it is not rediscovered later. The -field may run to several paragraphs or a list, and is omitted when nothing is known -yet. +**Trigger** names only the event that makes the fix necessary, not what to do when it +occurs. What is already known about the fix — findings, constraints, and the steps +worked out when the decision to defer was made — goes into **Fix notes**, so that it is +not rediscovered later. The field may run to several paragraphs or a list, and is +omitted when nothing is known yet. -## Adding an item +## Adding and changing an entry When a problem is deliberately deferred — during a review, while planning or doing -work, or in a discussion — add an entry under Active with the next free number. The -entry goes into the same commit as the change that led to the decision, such as the -review fixes, or into a commit of its own when there is no such change. - -## Closing an item - -An item is closed in one of two ways: - -- **Fixed.** When the item is ready to be fixed, it becomes a regular piece of work, - planned and carried out the way the project plans any change, with the item's - **Fix notes** as an input to the planning. When the work is done, - the item is closed with `fixed in` and a reference to where the fix can be found. -- **Dropped.** When a review of the item shows that no change is needed — the problem +work, or in a discussion — add an entry under Active with the next free number. Before +writing it, show the entry to the user. The entry goes into the same commit as the +change that led to the decision, such as the review fixes, or into a commit of its own +when there is no such change. + +An entry is edited when a later discussion changes what is known: the problem, the +reasoning, the trigger, or the fix notes. It records the current understanding, not +the history of how it was reached. + +## Closing an entry + +An entry is closed in one of two ways: + +- **Fixed.** When the entry is ready to be fixed, it becomes a regular piece of work, + planned and carried out the way the project plans any change, with the entry's + **Fix notes** as an input to the planning. The entry is closed in the commit that + completes the fix, with `fixed in` and a reference to the plan of the work or the + pull request; a commit is named only when the entry is closed after the fix has been + committed. +- **Dropped.** When a review of the entry shows that no change is needed — the problem does not occur in practice, or it turns out to be a decision rather than a deferred - problem — the item is closed with `dropped:` and the reason. + problem — the entry is closed with `dropped:` and the reason. -Either way, the item moves to the Closed section, keeping its number and short name, +Either way, the entry moves to the Closed section, keeping its number and short name, and its body is replaced with the **Closed** line. The original reasoning remains in the repository history. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 648ff60..6ce57cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,16 +110,10 @@ Work is planned and tracked with four process skills kept in the repository. Eac plain Markdown file and states the full rules, for people as much as for AI agents, completed by the project choices listed below: -- `.claude/skills/tasks/SKILL.md` — tasks files: a unit of work as an ordered list of - atomic tasks with a definition of done and a status each, committed together with the - work it describes and archived when done. -- `.claude/skills/backlog/SKILL.md` — `docs/backlog.md`: work accepted for later, with - the decisions already made about it, in priority order; broken down into a tasks file - only when it starts. -- `.claude/skills/changelog/SKILL.md` — `CHANGELOG.md`: Keep a Changelog 1.1.0 without - comparison links, user-visible changes only, one sentence per entry. -- `.claude/skills/tech-debt/SKILL.md` — `docs/tech-debt.md`: what counts as a deferred - problem, the entry format, and closing an entry as fixed or dropped. +- `.claude/skills/tasks/SKILL.md` — tasks files; +- `.claude/skills/backlog/SKILL.md` — `docs/backlog.md`; +- `.claude/skills/changelog/SKILL.md` — `CHANGELOG.md`; +- `.claude/skills/tech-debt/SKILL.md` — `docs/tech-debt.md`. The plans, the backlog, and the tech debt are kept as files in the repository rather than in an issue tracker, so that each decision is versioned together with the change it @@ -182,8 +176,10 @@ major version is 0, the usual convention for `0.y.z` applies: version — `0.1.0` after `0.0.6`. Breaking usage means removing or renaming a command, a flag, an environment variable, or a configuration key, or refusing input that used to be accepted. An entry under `Removed` in `[Unreleased]`, or an entry under `Changed` - that does one of these, makes the release breaking; -- any other release — new features and fixes only — raises the patch version. + that does one of these, makes the release breaking. An entry under `Deprecated` does + not: what it names still works; +- any other release — new features, deprecations, and fixes only — raises the patch + version. Version `1.0.0` is a separate, explicit decision. From then on, a breaking release raises the major version. diff --git a/README.md b/README.md index 55f5e13..b676e61 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Not present in v1: write operations (out of scope) and JSON output (`--json`, pl ### Known limitations - **HTML tables collapse.** The markdown converter runs on library defaults, which have no table support: a `
` becomes its cell text run together, without separators. A work item whose Description holds a table renders unreadably. -- **Rich-text noise is unhandled.** @-mentions, attachment links, Word- and Outlook-pasted markup, and work-item references are converted literally, with whatever wrapper markup TFS stored. Fixing this needs samples from a real instance and is planned in `docs/backlog.md`. +- **Rich-text noise is unhandled.** @-mentions, attachment links, Word- and Outlook-pasted markup, and work-item references are converted literally, with whatever wrapper markup TFS stored. Fixing this needs samples from a real instance and is recorded in `docs/backlog.md`. - **Servers with anonymous access are not supported.** `auth login` has not been tested against a server that admits anonymous requests, such as Azure DevOps Server with public projects enabled. On such a server an invalid PAT may pass the login check and be stored, and the other commands would then read as the anonymous user, seeing less, without an error. ## Installation diff --git a/docs/architecture.md b/docs/architecture.md index 35b10e2..37cbb21 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -320,7 +320,7 @@ type Result struct { - **New API domain** (repos, builds): add a new domain module and register its resource command under the area command, adding the area command (e.g. `git`) if it does not exist yet. No edits to `apiclient`, `config`, or `tfserr`. - **`--json` output**: introduce a `Renderer` interface in the cli layer; add a `JSONRenderer` that consumes `*WorkItem` directly. The markdown printer becomes the other implementation. Local refactor confined to the cli layer. -- **TFS-specific HTML quirks** (mentions, attachment links, Word paste leftovers): add rules in `htmlmd` plus golden tests on real samples. Planned as the `html-quirks` entry in `docs/backlog.md`. +- **TFS-specific HTML quirks** (mentions, attachment links, Word paste leftovers): add rules in `htmlmd` plus golden tests on real samples. Recorded as the `html-quirks` entry in `docs/backlog.md`. --- diff --git a/docs/backlog.md b/docs/backlog.md index 4ace4ed..b1c4c30 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -5,29 +5,30 @@ Accepted work that has not started yet, in priority order. ### `git-pull-requests` **Goal:** An agent can read pull requests, their comment threads, and the work items linked to them. -**Context:** The API domains in this backlog are ordered by how much each lets an agent -do without being handed an id by a person. An agent sees the code through the local -`git`, but pull requests, review comments, and linked work items exist only on the -server; the "address the review comments" scenario is impossible without them. The -domain is of no use on TFVC projects. Pull request threads appeared only in TFS 2017; -under "Server compatibility is preserved" in `docs/project-brief.md` they should be -optional, failing with a clear error on an older server while everything else keeps -working. +**Context:** The API domains are ordered by how much each lets an agent do without being +handed an id by a person. An agent sees the code through the local `git`, but pull +requests, review comments, and linked work items exist only on the server; the "address +the review comments" scenario is impossible without them. The domain is of no use on +TFVC projects. Pull request threads appeared only in TFS 2017; under "Server +compatibility is preserved" in `docs/project-brief.md` they should be optional, failing +with a clear error on an older server while everything else keeps working. **Added:** 2026-10-04, in conversation on the next API domains ### `workitem-comments` **Goal:** An agent can read the discussion of a work item. -**Context:** This extends the existing work item domain rather than adding a new one. -The Comments API exists only on recent servers; on older ones the discussion is kept in -the revisions of the `System.History` field. +**Context:** The API domains are ordered by how much each lets an agent do without being +handed an id by a person. This extends the existing work item domain rather than adding +a new one. The Comments API exists only on recent servers; on older ones the discussion +is kept in the revisions of the `System.History` field. **Added:** 2026-10-04, in conversation on the next API domains ### `build-status-and-logs` **Goal:** An agent can read builds, their timeline, and their logs. -**Context:** Scenario: a CI build failed and the agent is to find out why, locating the -failed step through the timeline and reading its log. Less frequent than the domains -before it, since many on-prem teams run CI outside TFS Build. The volume of logs needs -a decision: the whole log or only the failed step. +**Context:** The API domains are ordered by how much each lets an agent do without being +handed an id by a person. Scenario: a CI build failed and the agent is to find out why, +locating the failed step through the timeline and reading its log. Less frequent than +the domains before it, since many on-prem teams run CI outside TFS Build. The volume of +logs needs a decision: the whole log or only the failed step. **Added:** 2026-10-04, in conversation on the next API domains ### `html-quirks` @@ -53,8 +54,8 @@ contracts. Decisions already made: attachment file names; that is a separate feature. - The limitation is stated in "Known limitations" in both `README.md` and `skills/tfscli/SKILL.md`, which must stop claiming it together. -**Trigger:** A decision to collect rich-text samples from a live TFS instance. A live -connection is no longer the blocker: release 0.0.5 ran `auth login` and reading one +**Blocked until:** A decision to collect rich-text samples from a live TFS instance. A +live connection is no longer the blocker: release 0.0.5 ran `auth login` and reading one work item against a live server. **Added:** 2026-05-20, in the conversation that produced the Architecture section of `docs/architecture.md` From f467d0cf3860b770f1a250bae342a92e190a8fa9 Mon Sep 17 00:00:00 2001 From: Dmitry Pleshakov Date: Mon, 5 Oct 2026 21:18:14 +0300 Subject: [PATCH 6/6] Resolve the contradictions the second review of the process skills found Postponed work is accepted work that has not started, as the backlog defines it: once it stops, it counts as not started again. Renumbering Pending tasks keeps the numbers of Done, Skipped, and In progress tasks and never reuses one of them, so a Skipped task between Pending ones no longer causes a collision. The rule for deleting a postponed tasks file is stated without a double negative. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013xePd54F4w9BtuyAbVQUnD --- .claude/skills/backlog/SKILL.md | 2 +- .claude/skills/tasks/SKILL.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.claude/skills/backlog/SKILL.md b/.claude/skills/backlog/SKILL.md index 77f810b..e70ef7b 100644 --- a/.claude/skills/backlog/SKILL.md +++ b/.claude/skills/backlog/SKILL.md @@ -32,7 +32,7 @@ if the project has no such directory. **What goes here:** - Work that has been accepted for implementation and is not starting now - Work accepted on a condition that has not occurred yet, with that condition recorded -- Work that started and is postponed before it is finished +- Work postponed before it was finished: once it stops, it counts as not started again **What does not go here:** - Work that starts now — break it down and start it the way the project handles any diff --git a/.claude/skills/tasks/SKILL.md b/.claude/skills/tasks/SKILL.md index 78ff53f..56ae574 100644 --- a/.claude/skills/tasks/SKILL.md +++ b/.claude/skills/tasks/SKILL.md @@ -144,7 +144,8 @@ determines the tasks that follow it; those are added once the decision is made. knowing later, is marked `Skipped — ` instead. - The order of execution is the order in the file. When tasks are added, removed, or reordered, the `Pending` tasks may be renumbered so that the numbers follow that - order; `Done` and `Skipped` tasks keep their numbers, since commits refer to them. + order. `Done`, `Skipped`, and `In progress` tasks keep their numbers, since commits + may refer to them, and a renumbered task never takes a number that one of them holds. ### Postponing the work @@ -153,7 +154,7 @@ later, record its goal and the decisions already made where the project keeps ac work that has not started, if it has such a place; otherwise ask the user. Then, in the same commit: -- if the file holds nothing that is not carried over — no `Done` task and no record +- if everything in the file is carried over — it has no `Done` task and no record worth keeping on its own — delete it; - otherwise mark the unresolved tasks `Skipped — postponed` and archive the file, so that the work already done stays on record.