From 14b745e2e75f894786442fe64f15eb0df3db854c Mon Sep 17 00:00:00 2001 From: 4gl <@> Date: Sun, 9 Aug 2026 17:39:33 +0100 Subject: [PATCH] fix: agent tidy up --- .agents/docs/domain.md | 36 ++++++ .agents/docs/issue-tracker.md | 19 +++ .agents/skills/add-feed-post/SKILL.md | 82 +++++++++++++ .agents/skills/grill-with-docs/SKILL.md | 7 -- .../skills/grill-with-docs/agents/openai.yaml | 5 - .../skills/setup-matt-pocock-skills/SKILL.md | 116 ------------------ .../agents/openai.yaml | 5 - .../skills/setup-matt-pocock-skills/domain.md | 51 -------- .../issue-tracker-github.md | 45 ------- .../issue-tracker-gitlab.md | 46 ------- .../issue-tracker-local.md | 30 ----- .../setup-matt-pocock-skills/triage-labels.md | 15 --- AGENTS.md | 27 +++- CONTEXT.md | 30 +++++ content/feed/fsedit-paging/index.md | 21 ++++ docs/agents/domain.md | 36 ------ docs/agents/issue-tracker.md | 30 ----- 17 files changed, 212 insertions(+), 389 deletions(-) create mode 100644 .agents/docs/domain.md create mode 100644 .agents/docs/issue-tracker.md create mode 100644 .agents/skills/add-feed-post/SKILL.md delete mode 100644 .agents/skills/grill-with-docs/SKILL.md delete mode 100644 .agents/skills/grill-with-docs/agents/openai.yaml delete mode 100644 .agents/skills/setup-matt-pocock-skills/SKILL.md delete mode 100644 .agents/skills/setup-matt-pocock-skills/agents/openai.yaml delete mode 100644 .agents/skills/setup-matt-pocock-skills/domain.md delete mode 100644 .agents/skills/setup-matt-pocock-skills/issue-tracker-github.md delete mode 100644 .agents/skills/setup-matt-pocock-skills/issue-tracker-gitlab.md delete mode 100644 .agents/skills/setup-matt-pocock-skills/issue-tracker-local.md delete mode 100644 .agents/skills/setup-matt-pocock-skills/triage-labels.md create mode 100644 CONTEXT.md create mode 100644 content/feed/fsedit-paging/index.md delete mode 100644 docs/agents/domain.md delete mode 100644 docs/agents/issue-tracker.md diff --git a/.agents/docs/domain.md b/.agents/docs/domain.md new file mode 100644 index 0000000..52b4141 --- /dev/null +++ b/.agents/docs/domain.md @@ -0,0 +1,36 @@ +# Domain Docs + +How to consume this repo's domain documentation when exploring the codebase. + +## Before exploring, read these + +- **`CONTEXT.md`** at the repo root - the domain glossary and orientation. +- **`.agents/adr/`** - read the Architecture Decision Records that touch the area you're about to work in. + +If any of these files don't exist, proceed silently. Don't flag their absence or suggest creating them upfront; they are created lazily when terms or decisions actually get resolved. + +## File structure + +``` +/ +├── CONTEXT.md +├── .agents/ +│ ├── adr/ +│ │ ├── 0001-.md +│ │ └── 0002-.md +│ ├── docs/ +│ └── skills/ +└── src/ +``` + +## Use the glossary's vocabulary + +When your output names a domain concept (an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary avoids. + +If the concept you need isn't in the glossary yet, that's a signal - either you're inventing language the project doesn't use (reconsider), or there's a real gap (note it). + +## Flag ADR conflicts + +If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: + +> _Contradicts ADR-0001 (...) - but worth reopening because..._ diff --git a/.agents/docs/issue-tracker.md b/.agents/docs/issue-tracker.md new file mode 100644 index 0000000..aa7b6e8 --- /dev/null +++ b/.agents/docs/issue-tracker.md @@ -0,0 +1,19 @@ +# Issue tracker: Local Markdown + +Issues and specs (you may know a spec as a PRD) for this repo live as markdown files in `.scratch/`. + +## Conventions + +- One feature per directory: `.scratch//` +- The spec is `.scratch//spec.md` +- Implementation issues are one file per ticket at `.scratch//issues/-.md`, numbered from `01` - never a single combined tickets file +- Triage state is recorded as a `Status:` line near the top of each issue file +- Comments and conversation history append to the bottom of the file under a `## Comments` heading + +## When a skill says "publish to the issue tracker" + +Create a new file under `.scratch//` (creating the directory if needed). + +## When a skill says "fetch the relevant ticket" + +Read the file at the referenced path. The user will normally pass the path or the issue number directly. diff --git a/.agents/skills/add-feed-post/SKILL.md b/.agents/skills/add-feed-post/SKILL.md new file mode 100644 index 0000000..0ed8ffa --- /dev/null +++ b/.agents/skills/add-feed-post/SKILL.md @@ -0,0 +1,82 @@ +--- +name: add-feed-post +description: Add a new Feed post (short announcement / social-style update) to the Data Controller marketing site. Use when the user wants to publish a Feed post, add a /feed/ entry, or create a short announcement that also goes out via RSS. +--- + +# Add a Feed post + +The **Feed** section (`/feed/`) is for short announcements and social-media style updates - things that don't warrant a full `content/blog/` article but are still worth publishing and syndicating via RSS. Feed posts work exactly like blog posts (one markdown file per post, in its own directory) but live under `content/feed/` and publish under `/feed/`. + +Both Blog and Feed share a single combined RSS feed at `/rss.xml` (via `gatsby-plugin-feed` in `gatsby-config.js`), so a new Feed post appears in RSS automatically on the next build - no extra config. + +## Steps + +### 1. Create the post directory + +Create a folder under `content/feed/`, named after the post slug (this becomes the URL): + +``` +content/feed/my-new-announcement/index.md +``` + +Pick a short, hyphenated, lowercase slug. + +### 2. Write the front matter + content + +```md +--- +title: 'My New Announcement' +description: A one or two sentence summary used for SEO and RSS. +date: '2024-06-01 09:00:00' +author: 'Your Name' +authorLink: https://www.linkedin.com/in/yourprofile/ +tags: + - Announcements +--- + +Your announcement content goes here, written in regular Markdown. +``` + +Front matter fields: + +| Field | Required | Notes | +| ------------- | -------- | --------------------------------------------------------------------- | +| `title` | Yes | Used on the page, in the sidebar and in the RSS item. | +| `description` | Yes | Short summary for SEO meta tags and the RSS item description. | +| `date` | Yes | Format `'YYYY-MM-DD HH:MM:SS'`. Controls sort order and the archive. | +| `author` | Yes | Displayed under the post title. | +| `authorLink` | No | If set, the author name links out (e.g. to a LinkedIn profile). | +| `tags` | Yes | One or more tags. Drives the sidebar category list and RSS category. | +| `previewImg` | No | Relative path to an image in the same folder (e.g. `'./cover.png'`). Feed posts usually omit this since they're short-form. | + +Use regular dashes (`-`) in content, not em-dashes. + +### 3. Add images (optional) + +If you set `previewImg` or reference images in the body, place the image files in the same post directory and reference them with a relative path. + +### 4. Build / preview + +```shell +npm run develop +``` + +The post will be available at `/my-new-announcement/` and will appear on the `/feed/` listing page, in the site search index, and in `/rss.xml` alongside blog posts. + +## How Feed differs from Blog + +| Aspect | Blog | Feed | +| ----------------- | ----------------------------- | --------------------------------- | +| Content directory | `content/blog/` | `content/feed/` | +| Listing page | `/blog/` | `/feed/` | +| Year archive | `/{year}/` | `/feed/{year}/` | +| Category page | `/category/{tag}/` | `/feed/category/{tag}/` | +| Template | `src/templates/blog-post.tsx`, `src/templates/blog-list.tsx` | `src/templates/feed-post.tsx`, `src/templates/feed-list.tsx` | +| RSS | Included in `/rss.xml` | Included in `/rss.xml` | + +Feed archive/category routes are prefixed with `/feed/` to avoid colliding with the equivalent Blog routes, since both are rendered by the shared `src/templates/sidebar.tsx` component (via its `basePath` prop). + +## Notes + +- To add a **blog** post instead, follow the same steps but use `content/blog/` and the `/blog/` routes. +- The canonical human-readable version of this guide is `docs/adding-feed-posts.md`. diff --git a/.agents/skills/grill-with-docs/SKILL.md b/.agents/skills/grill-with-docs/SKILL.md deleted file mode 100644 index bed05d2..0000000 --- a/.agents/skills/grill-with-docs/SKILL.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: grill-with-docs -description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go. -disable-model-invocation: true ---- - -Run a `/grilling` session, using the `/domain-modeling` skill. diff --git a/.agents/skills/grill-with-docs/agents/openai.yaml b/.agents/skills/grill-with-docs/agents/openai.yaml deleted file mode 100644 index 5dbe278..0000000 --- a/.agents/skills/grill-with-docs/agents/openai.yaml +++ /dev/null @@ -1,5 +0,0 @@ -interface: - display_name: "Grill with Docs" - short_description: "Grill a design and write its docs" -policy: - allow_implicit_invocation: false diff --git a/.agents/skills/setup-matt-pocock-skills/SKILL.md b/.agents/skills/setup-matt-pocock-skills/SKILL.md deleted file mode 100644 index aecf855..0000000 --- a/.agents/skills/setup-matt-pocock-skills/SKILL.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -name: setup-matt-pocock-skills -description: Configure this repo for the engineering skills — set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills. -disable-model-invocation: true ---- - -# Setup Matt Pocock's Skills - -Scaffold the per-repo configuration that the engineering skills assume: - -- **Issue tracker** — where issues live (GitHub by default; local markdown is also supported out of the box) -- **Triage labels** — the strings used for the five canonical triage roles -- **Domain docs** — where `CONTEXT.md` and ADRs live, and the consumer rules for reading them - -This is a prompt-driven skill, not a deterministic script. Explore, present what you found, confirm with the user, then write. - -## Process - -### 1. Explore - -Look at the current repo to understand its starting state. Read whatever exists; don't assume: - -- `git remote -v` and `.git/config` — is this a GitHub repo? Which one? -- `AGENTS.md` and `CLAUDE.md` at the repo root — does either exist? Is there already an `## Agent skills` section in either? -- `CONTEXT.md` and `CONTEXT-MAP.md` at the repo root -- `docs/adr/` and any `src/*/docs/adr/` directories -- `docs/agents/` — does this skill's prior output already exist? -- `.scratch/` — sign that a local-markdown issue tracker convention is already in use -- Is the `triage` skill installed? (a `triage` skill folder alongside this one, or `triage` in your available skills.) This decides whether Section B runs at all. -- Monorepo signals — a `pnpm-workspace.yaml`, a `workspaces` field in `package.json`, or a populated `packages/*` with its own `src/`. Present only in a genuinely large multi-package repo; their absence means single-context, which is almost every repo. - -### 2. Present findings and ask - -Summarise what's present and what's missing. Then take the sections in order — one section, one answer, then the next. - -Lead each section with the recommended answer so the user can accept it in a word. Give a one-line explainer only when the choice genuinely branches; skip the section entirely when exploration already settled it (Section B when `triage` isn't installed, Section C when there's no monorepo). - -**Section A — Issue tracker.** - -> Explainer: The "issue tracker" is where issues live for this repo. Skills like `to-tickets`, `triage`, `to-spec`, and `qa` read from and write to it — they need to know whether to call `gh issue create`, write a markdown file under `.scratch/`, or follow some other workflow you describe. Pick the place you actually track work for this repo. - -Default posture: these skills were designed for GitHub. If a `git remote` points at GitHub, propose that. If a `git remote` points at GitLab (`gitlab.com` or a self-hosted host), propose GitLab. Otherwise (or if the user prefers), offer: - -- **GitHub** — issues live in the repo's GitHub Issues (uses the `gh` CLI) -- **GitLab** — issues live in the repo's GitLab Issues (uses the [`glab`](https://gitlab.com/gitlab-org/cli) CLI) -- **Local markdown** — issues live as files under `.scratch//` in this repo (good for solo projects or repos without a remote) -- **Other** (Jira, Linear, etc.) — ask the user to describe the workflow in one paragraph; the skill will record it as freeform prose - -Record the choice in `docs/agents/issue-tracker.md`. The GitHub and GitLab templates carry a "PRs as a request surface" flag, defaulted **off** — leave it off and don't raise it; a user who wants external PRs in the triage queue can flip the flag in the file later. - -**Section B — Triage label vocabulary.** Skip this section entirely if the `triage` skill isn't installed (exploration told you) — an uninstalled skill needs no labels. - -If it is installed, ask exactly one question: - -> Do you want to keep the default triage labels? (recommended: **yes**) - -The defaults are the five canonical roles, each label string equal to its name: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. On **yes**, write them as-is. Only if the user says no — usually because their tracker already uses other names (e.g. `bug:triage` for `needs-triage`) — collect the overrides so `triage` applies existing labels instead of creating duplicates. - -**Section C — Domain docs.** Default to **single-context** — one `CONTEXT.md` + `docs/adr/` at the repo root. This fits almost every repo; write it without asking. - -Offer **multi-context** — a root `CONTEXT-MAP.md` pointing to per-context `CONTEXT.md` files — only when exploration found monorepo signals. Then confirm which layout they want. - -### 3. Confirm and edit - -Show the user a draft of: - -- The `## Agent skills` block to add to whichever of `CLAUDE.md` / `AGENTS.md` is being edited (see step 4 for selection rules) -- The contents of `docs/agents/issue-tracker.md`, `docs/agents/domain.md`, and `docs/agents/triage-labels.md` (the last only when `triage` is installed) - -Let them edit before writing. - -### 4. Write - -**Pick the file to edit:** - -- If `CLAUDE.md` exists, edit it. -- Else if `AGENTS.md` exists, edit it. -- If neither exists, ask the user which one to create — don't pick for them. - -Never create `AGENTS.md` when `CLAUDE.md` already exists (or vice versa) — always edit the one that's already there. - -If an `## Agent skills` block already exists in the chosen file, update its contents in-place rather than appending a duplicate. Don't overwrite user edits to the surrounding sections. - -The block: - -```markdown -## Agent skills - -### Issue tracker - -[one-line summary of where issues are tracked]. See `docs/agents/issue-tracker.md`. - -### Triage labels - -[one-line summary of the label vocabulary]. See `docs/agents/triage-labels.md`. - -### Domain docs - -[one-line summary of layout — "single-context" or "multi-context"]. See `docs/agents/domain.md`. -``` - -Include the `### Triage labels` sub-block, and write `docs/agents/triage-labels.md`, only when `triage` is installed and Section B ran. When it isn't, both are omitted. - -Then write the docs files using the seed templates in this skill folder as a starting point: - -- [issue-tracker-github.md](./issue-tracker-github.md) — GitHub issue tracker -- [issue-tracker-gitlab.md](./issue-tracker-gitlab.md) — GitLab issue tracker -- [issue-tracker-local.md](./issue-tracker-local.md) — local-markdown issue tracker -- [triage-labels.md](./triage-labels.md) — label mapping (only if `triage` is installed) -- [domain.md](./domain.md) — domain doc consumer rules + layout - -For "other" issue trackers, write `docs/agents/issue-tracker.md` from scratch using the user's description. - -### 5. Done - -Tell the user the setup is complete and which engineering skills will now read from these files. Mention they can edit `docs/agents/*.md` directly later — re-running this skill is only necessary if they want to switch issue trackers or restart from scratch. diff --git a/.agents/skills/setup-matt-pocock-skills/agents/openai.yaml b/.agents/skills/setup-matt-pocock-skills/agents/openai.yaml deleted file mode 100644 index 65a0da8..0000000 --- a/.agents/skills/setup-matt-pocock-skills/agents/openai.yaml +++ /dev/null @@ -1,5 +0,0 @@ -interface: - display_name: "Setup Matt Pocock Skills" - short_description: "Configure a repo for the skills" -policy: - allow_implicit_invocation: false diff --git a/.agents/skills/setup-matt-pocock-skills/domain.md b/.agents/skills/setup-matt-pocock-skills/domain.md deleted file mode 100644 index b548c53..0000000 --- a/.agents/skills/setup-matt-pocock-skills/domain.md +++ /dev/null @@ -1,51 +0,0 @@ -# Domain Docs - -How the engineering skills should consume this repo's domain documentation when exploring the codebase. - -## Before exploring, read these - -- **`CONTEXT.md`** at the repo root, or -- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic. -- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src//docs/adr/` for context-scoped decisions. - -If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved. - -## File structure - -Single-context repo (most repos): - -``` -/ -├── CONTEXT.md -├── docs/adr/ -│ ├── 0001-event-sourced-orders.md -│ └── 0002-postgres-for-write-model.md -└── src/ -``` - -Multi-context repo (presence of `CONTEXT-MAP.md` at the root): - -``` -/ -├── CONTEXT-MAP.md -├── docs/adr/ ← system-wide decisions -└── src/ - ├── ordering/ - │ ├── CONTEXT.md - │ └── docs/adr/ ← context-specific decisions - └── billing/ - ├── CONTEXT.md - └── docs/adr/ -``` - -## Use the glossary's vocabulary - -When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids. - -If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`). - -## Flag ADR conflicts - -If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: - -> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_ diff --git a/.agents/skills/setup-matt-pocock-skills/issue-tracker-github.md b/.agents/skills/setup-matt-pocock-skills/issue-tracker-github.md deleted file mode 100644 index 82cfbf5..0000000 --- a/.agents/skills/setup-matt-pocock-skills/issue-tracker-github.md +++ /dev/null @@ -1,45 +0,0 @@ -# Issue tracker: GitHub - -Issues and PRDs for this repo live as GitHub issues. Use the `gh` CLI for all operations. - -## Conventions - -- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies. -- **Read an issue**: `gh issue view --comments`, filtering comments by `jq` and also fetching labels. -- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters. -- **Comment on an issue**: `gh issue comment --body "..."` -- **Apply / remove labels**: `gh issue edit --add-label "..."` / `--remove-label "..."` -- **Close**: `gh issue close --comment "..."` - -Infer the repo from `git remote -v` — `gh` does this automatically when run inside a clone. - -## Pull requests as a triage surface - -**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_ - -When set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents: - -- **Read a PR**: `gh pr view --comments` and `gh pr diff ` for the diff. -- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`). -- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`. - -GitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`. - -## When a skill says "publish to the issue tracker" - -Create a GitHub issue. - -## When a skill says "fetch the relevant ticket" - -Run `gh issue view --comments`. - -## Wayfinding operations - -Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets. - -- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`. -- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #` at the top of the child body. Labels: `wayfinder:` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev. -- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos///issues//dependencies/blocked_by -F issue_id=`, where `` is the blocker's numeric **database id** (`gh api repos///issues/ --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #, #` line at the top of the child body. A ticket is unblocked when every blocker is closed. -- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins. -- **Claim**: `gh issue edit --add-assignee @me` — the session's first write. -- **Resolve**: `gh issue comment --body ""`, then `gh issue close `, then append a context pointer (gist + link) to the map's Decisions-so-far. diff --git a/.agents/skills/setup-matt-pocock-skills/issue-tracker-gitlab.md b/.agents/skills/setup-matt-pocock-skills/issue-tracker-gitlab.md deleted file mode 100644 index 8a54714..0000000 --- a/.agents/skills/setup-matt-pocock-skills/issue-tracker-gitlab.md +++ /dev/null @@ -1,46 +0,0 @@ -# Issue tracker: GitLab - -Issues and PRDs for this repo live as GitLab issues. Use the [`glab`](https://gitlab.com/gitlab-org/cli) CLI for all operations. - -## Conventions - -- **Create an issue**: `glab issue create --title "..." --description "..."`. Use a heredoc for multi-line descriptions. Pass `--description -` to open an editor. -- **Read an issue**: `glab issue view --comments`. Use `-F json` for machine-readable output. -- **List issues**: `glab issue list -F json` with appropriate `--label` filters. -- **Comment on an issue**: `glab issue note --message "..."`. GitLab calls comments "notes". -- **Apply / remove labels**: `glab issue update --label "..."` / `--unlabel "..."`. Multiple labels can be comma-separated or by repeating the flag. -- **Close**: `glab issue close `. `glab issue close` does not accept a closing comment, so post the explanation first with `glab issue note --message "..."`, then close. -- **Merge requests**: GitLab calls PRs "merge requests". Use `glab mr create`, `glab mr view`, `glab mr note`, etc. — the same shape as `gh pr ...` with `mr` in place of `pr` and `note`/`--message` in place of `comment`/`--body`. - -Infer the repo from `git remote -v` — `glab` does this automatically when run inside a clone. - -## Merge requests as a triage surface - -**MRs as a request surface: no.** _(Set to `yes` if this repo treats external merge requests as feature requests; `/triage` reads this flag.)_ - -When set to `yes`, MRs run through the same labels and states as issues, using the `glab mr` equivalents: - -- **Read an MR**: `glab mr view --comments` and `glab mr diff ` for the diff. -- **List external MRs for triage**: `glab mr list -F json`, then keep only MRs whose author is not a project member/owner (a contributor's MR, not a maintainer's in-flight work). -- **Comment / label / close**: `glab mr note`, `glab mr update --label`/`--unlabel`, `glab mr close`. - -Unlike GitHub, GitLab numbers issues and MRs separately, so `#42` is unambiguous once you know which surface the maintainer means. - -## When a skill says "publish to the issue tracker" - -Create a GitLab issue. - -## When a skill says "fetch the relevant ticket" - -Run `glab issue view --comments`. - -## Wayfinding operations - -Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets. - -- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `glab issue create --label wayfinder:map`. (On GitLab tiers with native epics, an epic may hold the map instead; a labelled issue works everywhere.) -- **Child ticket**: an issue carrying `Part of #` at the top of its description and labels `wayfinder:` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev. -- **Blocking**: GitLab's **native blocking link** — the canonical, UI-visible representation. Add it with the `/blocked_by #` quick action, posted as a note (`glab issue note --message "/blocked_by #"`). Native blocking links are a Premium/Ultimate feature; on the free tier (or where unavailable) fall back to a `Blocked by: #, #` line at the top of the description. A ticket is unblocked when every blocker is closed. -- **Frontier query**: `glab issue list -F json` scoped to the map's children, drop any with an open blocker — a native `blocked_by` link to an open issue (`glab api projects/:id/issues/:iid/links`), or an open issue in the `Blocked by` line — or an assignee; first in map order wins. -- **Claim**: `glab issue update --assignee @me` — the session's first write. -- **Resolve**: `glab issue note --message ""`, then `glab issue close `, then append a context pointer (gist + link) to the map's Decisions-so-far. diff --git a/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md b/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md deleted file mode 100644 index 6b124b3..0000000 --- a/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md +++ /dev/null @@ -1,30 +0,0 @@ -# Issue tracker: Local Markdown - -Issues and specs (you may know a spec as a PRD) for this repo live as markdown files in `.scratch/`. - -## Conventions - -- One feature per directory: `.scratch//` -- The spec is `.scratch//spec.md` -- Implementation issues are one file per ticket at `.scratch//issues/-.md`, numbered from `01` — never a single combined tickets file -- Triage state is recorded as a `Status:` line near the top of each issue file (see `triage-labels.md` for the role strings) -- Comments and conversation history append to the bottom of the file under a `## Comments` heading - -## When a skill says "publish to the issue tracker" - -Create a new file under `.scratch//` (creating the directory if needed). - -## When a skill says "fetch the relevant ticket" - -Read the file at the referenced path. The user will normally pass the path or the issue number directly. - -## Wayfinding operations - -Used by `/wayfinder`. The **map** is a file with one **child** file per ticket. - -- **Map**: `.scratch//map.md` — the Notes / Decisions-so-far / Fog body. -- **Child ticket**: `.scratch//issues/NN-.md`, numbered from `01`, with the question in the body. A `Type:` line records the ticket type (`research`/`prototype`/`grilling`/`task`); a `Status:` line records `claimed`/`resolved`. -- **Blocking**: a `Blocked by: NN, NN` line near the top. A ticket is unblocked when every file it lists is `resolved`. -- **Frontier**: scan `.scratch//issues/` for files that are open, unblocked, and unclaimed; first by number wins. -- **Claim**: set `Status: claimed` and save before any work. -- **Resolve**: append the answer under an `## Answer` heading, set `Status: resolved`, then append a context pointer (gist + link) to the map's Decisions-so-far in `map.md`. diff --git a/.agents/skills/setup-matt-pocock-skills/triage-labels.md b/.agents/skills/setup-matt-pocock-skills/triage-labels.md deleted file mode 100644 index b716855..0000000 --- a/.agents/skills/setup-matt-pocock-skills/triage-labels.md +++ /dev/null @@ -1,15 +0,0 @@ -# Triage Labels - -The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker. - -| Label in mattpocock/skills | Label in our tracker | Meaning | -| -------------------------- | -------------------- | ---------------------------------------- | -| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue | -| `needs-info` | `needs-info` | Waiting on reporter for more information | -| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent | -| `ready-for-human` | `ready-for-human` | Requires human implementation | -| `wontfix` | `wontfix` | Will not be actioned | - -When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table. - -Edit the right-hand column to match whatever vocabulary you actually use. diff --git a/AGENTS.md b/AGENTS.md index 5678a6b..a5a30ca 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,33 @@ -## Agent skills +## Related repositories + +This is the Data Controller **marketing site, blog and feed** (Gatsby). It has two sibling repos, usually checked out side by side: + +- **`dc`** - the product source (Angular client + SAS backend). Behaviour of the product itself is defined there; see its `CONTEXT.md` for the domain glossary. +- **`docs.datacontroller.io`** - the user-facing product documentation (MkDocs), published at docs.datacontroller.io. + +When writing marketing/blog/feed copy about a feature, treat `docs.datacontroller.io` and `dc` as the source of truth for how the product actually behaves. + +## Content structure + +- **Blog** (`content/blog/`) - long-form articles, published at `/blog/`. +- **Feed** (`content/feed/`) - short announcements, published at `/feed/`. +- Both are combined into a single RSS feed at `/rss.xml`. +- To add a feed post, use the `add-feed-post` skill (`.agents/skills/add-feed-post/SKILL.md`). + +## Agent files + +All agent-facing material lives under `.agents/`: + +- `.agents/skills/` - pi-discovered skills (e.g. `add-feed-post`). +- `.agents/docs/` - reference docs consumed by skills and these instructions. ### Issue tracker -Issues live as markdown files under `.scratch/`. See `docs/agents/issue-tracker.md`. +Issues live as markdown files under `.scratch/`. See `.agents/docs/issue-tracker.md`. ### Domain docs -Single-context layout - `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`. +Single-context layout - `CONTEXT.md` at the repo root + ADRs in `.agents/adr/`. See `.agents/docs/domain.md`. ### Writing style diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 0000000..6641cf3 --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,30 @@ +# Context: datacontroller.io (marketing site) + +The public marketing website for Data Controller for SAS®, built with **Gatsby** (React + TypeScript, styled-components). It hosts the product's marketing pages, blog and feed. It is separate from the product itself (`dc`) and the product documentation (`docs.datacontroller.io`). + +## What the product is + +Data Controller for SAS® is a web application that lets users safely add, modify and delete data in SAS datasets and databases, with an edit-stage-approve workflow and full change history. It runs on SAS Viya, SAS 9 EBI and SASjs Server. For the product's own domain vocabulary (roles, load types, MPE control tables, validations, security), see `dc/CONTEXT.md`; for user-facing feature docs, see the `docs.datacontroller.io` repo. Treat those as the source of truth when writing copy about how the product behaves. + +## Layout + +- `content/blog/` - long-form articles (published at `/blog/`). +- `content/feed/` - short announcements (published at `/feed/`). See the `add-feed-post` skill. +- `src/pages/` - top-level pages (`index`, `about`, `contact`, `faq`, plus the markdown-driven `{MarkdownRemark.frontmatter__slug}.tsx`). +- `src/markdown-pages/` - standalone markdown pages (e.g. `pricing.md`). +- `src/templates/` - list/post/sidebar templates for blog and feed. +- `src/components/` - shared React components (layout, navibar, footer, hero, seo). +- `static/` - static assets served as-is; `gatsby-*.js` - Gatsby config (feed, node APIs, etc.). + +## Conventions + +- Use regular dashes (`-`) in content, not em-dashes. +- Blog and feed share a single combined RSS feed at `/rss.xml` (via `gatsby-plugin-feed`); new posts appear automatically on the next build. +- Lint with `npm run lint` (prettier) and typecheck with `npm run typecheck` before considering front-end changes done. +- Preview locally with `npm run develop`. + +## Agent files + +All agent-facing material lives under `.agents/`: skills in `.agents/skills/` (e.g. `add-feed-post`), and reference docs in `.agents/docs/` (`domain.md`, `issue-tracker.md`). + +See `AGENTS.md` for agent skills, writing rules, and where these files live. diff --git a/content/feed/fsedit-paging/index.md b/content/feed/fsedit-paging/index.md new file mode 100644 index 0000000..be3ad93 --- /dev/null +++ b/content/feed/fsedit-paging/index.md @@ -0,0 +1,21 @@ +--- +title: 'FSEDIT-Style Paging in the Edit Record Form' +description: Page through your data one record at a time in the Edit Record dialog - a modern take on the classic SAS PROC FSEDIT full-screen editor. +date: '2026-07-30 09:00:00' +author: 'Data Controller' +authorLink: https://www.linkedin.com/showcase/data_controller +tags: + - Announcements +--- + +# FSEDIT-Style Paging in the Edit Record Form + +Anyone who has worked with SAS for a while will remember `PROC FSEDIT` - the full-screen editor that let you step through a dataset one observation at a time, seeing every variable for a single record laid out on screen. It was a simple, focused way to review and amend data without getting lost in a wide grid. + +Data Controller's **Edit Record** dialog brings that experience into the browser. Instead of scanning across dozens of columns in the grid, you open a single row as a form - every field labelled and stacked vertically, with dropdowns, validations and formatting applied just as they are in the main editor. + +Now you can **page through your records** without leaving the form. Previous and Next arrows move you one record at a time, and a **Current row** indicator shows exactly where you are in the extract. It's the fastest way to work through a set of rows methodically - reviewing, correcting and moving on - especially for wide tables where horizontal scrolling in the grid slows you down. + +As always, everything flows through the standard Data Controller workflow: your changes are staged, validated and sent for approval before they reach the target table, with a full audit trail retained. + +Administrators who prefer to keep the grid-only experience can still disable the dialog with the [`DC_RESTRICT_EDITRECORD`](https://docs.datacontroller.io/dcc-options/#dc_restrict_editrecord) option. diff --git a/docs/agents/domain.md b/docs/agents/domain.md deleted file mode 100644 index fbaef2a..0000000 --- a/docs/agents/domain.md +++ /dev/null @@ -1,36 +0,0 @@ -# Domain Docs - -How the engineering skills should consume this repo's domain documentation when exploring the codebase. - -## Before exploring, read these - -- **`CONTEXT.md`** at the repo root, or -- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic. -- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src//docs/adr/` for context-scoped decisions. - -If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved. - -## File structure - -Single-context repo (most repos): - -``` -/ -├── CONTEXT.md -├── docs/adr/ -│ ├── 0001-event-sourced-orders.md -│ └── 0002-postgres-for-write-model.md -└── src/ -``` - -## Use the glossary's vocabulary - -When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids. - -If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`). - -## Flag ADR conflicts - -If your output contradicts an existing ADR, surface it explicitly rather than silently overriding: - -> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_ diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md deleted file mode 100644 index 6b124b3..0000000 --- a/docs/agents/issue-tracker.md +++ /dev/null @@ -1,30 +0,0 @@ -# Issue tracker: Local Markdown - -Issues and specs (you may know a spec as a PRD) for this repo live as markdown files in `.scratch/`. - -## Conventions - -- One feature per directory: `.scratch//` -- The spec is `.scratch//spec.md` -- Implementation issues are one file per ticket at `.scratch//issues/-.md`, numbered from `01` — never a single combined tickets file -- Triage state is recorded as a `Status:` line near the top of each issue file (see `triage-labels.md` for the role strings) -- Comments and conversation history append to the bottom of the file under a `## Comments` heading - -## When a skill says "publish to the issue tracker" - -Create a new file under `.scratch//` (creating the directory if needed). - -## When a skill says "fetch the relevant ticket" - -Read the file at the referenced path. The user will normally pass the path or the issue number directly. - -## Wayfinding operations - -Used by `/wayfinder`. The **map** is a file with one **child** file per ticket. - -- **Map**: `.scratch//map.md` — the Notes / Decisions-so-far / Fog body. -- **Child ticket**: `.scratch//issues/NN-.md`, numbered from `01`, with the question in the body. A `Type:` line records the ticket type (`research`/`prototype`/`grilling`/`task`); a `Status:` line records `claimed`/`resolved`. -- **Blocking**: a `Blocked by: NN, NN` line near the top. A ticket is unblocked when every file it lists is `resolved`. -- **Frontier**: scan `.scratch//issues/` for files that are open, unblocked, and unclaimed; first by number wins. -- **Claim**: set `Status: claimed` and save before any work. -- **Resolve**: append the answer under an `## Answer` heading, set `Status: resolved`, then append a context pointer (gist + link) to the map's Decisions-so-far in `map.md`.