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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions .archon/commands/maintainer-standup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
---
description: Synthesize the maintainer's morning standup brief from gathered git/PR/issue/state data
argument-hint: (no arguments — all context provided via upstream nodes)
---

# Maintainer Standup Synthesis

You are producing a daily maintainer briefing for the Archon project. The user is the maintainer running this workflow. Your job is to read the gathered facts, cross-reference against the project's direction document and the maintainer's profile, and produce a prioritized brief plus state to persist for tomorrow's run.

**Workflow ID**: $WORKFLOW_ID

---

## Phase 1: LOAD INPUTS

You have three sources of upstream context, all already gathered. Each is a JSON string that you should parse.

### Git status (origin/dev movement since last run)

```
$git-status.output
```

Fields: `current_dev_sha`, `prior_dev_sha`, `current_branch`, `is_dirty`, `pull_status`, `new_commits`, `diff_stat`.

### GitHub data (PRs, issues, review requests, recently closed)

```
$gh-data.output
```

Fields: `gh_handle`, `since_date`, `all_open_prs`, `review_requested`, `authored_by_me`, `issues_assigned`, `recent_unlabeled_issues`, `recently_closed_prs`, `recently_closed_issues`, `my_recent_commits`.

### Local context (direction doc, maintainer profile, prior state, recent briefs)

```
$read-context.output
```

Fields: `direction` (markdown string), `profile` (markdown string), `prior_state` (object or null), `recent_briefs` (array of `{date, content}`).

---

## Phase 2: ANALYZE

### 2a. Detect first-run vs ongoing

If `prior_state` is `null` and `recent_briefs` is empty, this is a **first run**. Skip "Since last run" comparisons; produce a baseline triage and state snapshot the next run can diff against.

### 2b. Compare prior state to current reality (progress detection)

When `prior_state` exists:

- **Resolved since last run**: PRs in `prior_state.observed_prs` whose numbers do NOT appear in current `gh-data.output.all_open_prs` — they were closed or merged. Cross-reference against `gh-data.output.recently_closed_prs` to know whether they merged or were closed without merging. Same for issues.
- **Carry-over revisited**: each item in `prior_state.carry_over` — is it still open? Did its status change? If resolved, mention briefly under "Resolved since last run" and DROP from `next_state.carry_over`. If still pending, keep with original `first_seen` date (so age is preserved).
- **What you shipped**: `gh-data.output.my_recent_commits` lists the maintainer's commits since the last run. Summarize meaningfully — group by area, highlight notable ones. Don't just list shas.
- **New since last run**: PRs in current `all_open_prs` whose numbers are NOT in `prior_state.observed_prs` are new this run. Same for issues.

### 2c. Read the direction doc and profile

The `direction` markdown defines what Archon IS / IS NOT. The `profile` markdown describes the maintainer's role, scope, and current focus. Both inform the triage:

- **Profile scope** drives breadth of coverage. `scope: everything` (main maintainer) means classify all open PRs, not just ones touching the maintainer's focus areas.
- **Direction clauses** drive the polite-decline classification. PRs adding multi-tenancy, hosted-service features, or anything contradicting the IS-NOT list go to P4 with a citation.
- **Profile focus areas** weight prioritization within P1-P3 — items aligned with current focus rank higher.

### 2d. Triage all open PRs into P1-P4

For each PR in `all_open_prs`:

- **P1 (Do today)**: ready-to-merge PRs awaiting your review (`reviewDecision: APPROVED` or null AND `mergeStateStatus: clean`), security fixes, items breaking dev, blockers for an in-flight release. **Note**: `mergeStateStatus` is the only CI/merge signal in the gathered payload (values: `clean`, `unstable`, `dirty`, `blocked`, `behind`, `unknown`). For ambiguous cases run `gh pr checks <number>` to verify CI before classifying as P1.
- **P2 (This week)**: in-flight PRs needing review or maintainer feedback, PRs with merge conflicts that can be unblocked, PRs from the maintainer's current focus areas that are progressing.
- **P3 (Whenever)**: low-urgency items, drafts you authored, exploratory PRs, items outside current focus that aren't time-sensitive.
- **P4 (Polite-decline candidates)**: PRs that conflict with `direction.md`. Each P4 entry MUST cite a specific clause (e.g., `direction.md §single-developer-tool`).

You may use `gh pr view <number>`, `gh pr diff <number>`, or `gh pr checks <number>` to drill into PRs whose triage classification cannot be determined from the metadata alone. Be selective — drilling into all 60+ PRs is wasteful. Drill into 5-10 of the most ambiguous or interesting cases.

### 2e. Triage issues

Issues in `issues_assigned` and `recent_unlabeled_issues` follow the same P1-P4 classification. Use `gh issue view <number>` to drill into ambiguous ones. Recently-filed unlabeled issues are likely candidates for first-pass labeling.

### 2f. Surface direction questions

If any PR raises a "we don't have a stance on this" question that `direction.md` doesn't answer, surface it under **Direction questions raised**. These go into `next_state.direction_questions` so the maintainer can absorb them into `direction.md` over time.

### 2g. Carry-over aging

Items that have been in `prior_state.carry_over` for multiple runs (check `first_seen` dates) are higher priority — surface them prominently and consider escalating their P-level.

---

## Phase 3: GENERATE OUTPUT

Return a JSON object matching the workflow's `output_format` schema. Do not write any files yourself — the workflow's `persist` node handles disk writes from your structured response.

### `brief_markdown` (string)

A maintainer-ready markdown brief. Adapt sections — omit empty ones, add others if useful. Keep entries to one line each. The brief should be readable on a single screen.

```markdown
# Maintainer Standup — YYYY-MM-DD

## Since last run
- (Summary of new commits on dev with notable highlights, or "first run — baseline snapshot")
- (Mention pull_status if not 'pulled': dirty/not_on_dev/pull_failed)

## What you shipped
- (One-line summary grouped by area, derived from `my_recent_commits`. Omit if empty.)

## Resolved since last run
- **PR #N** — [title] — merged ✓ / closed
- **Issue #N** — [title] — closed
- (Omit section if nothing resolved.)

## P1 — Do today
- **PR #N** — [title] ([+X/-Y]) — [why P1, e.g. "ready to merge, awaiting your review"]
- **Issue #N** — [title] — [why P1]

## P2 — This week
- (Same format)

## P3 — Whenever
- (Same format)

## P4 — Polite-decline candidates
- **PR #N** — [title] by @[author] — Conflicts with `direction.md §[clause]`. [One-line reason.]

## Direction questions raised
- (PR #N raises: should Archon support [Y]? Add a stance to direction.md.)
- (Or omit if none.)

## Carry-over still pending
- **PR #N** — [title] — first seen YYYY-MM-DD ([N] runs ago) — [current status]
- (Omit section if nothing carried over.)
```

### `next_state` (object)

Carry-over state for tomorrow's run. Schema:

- `last_run_at`: current ISO-8601 timestamp (use the actual timestamp at synthesis time).
- `last_dev_sha`: value from `git-status.output.current_dev_sha`.
- `carry_over`: items the next run should remember as "still pending." For items already in `prior_state.carry_over` that are still pending, **preserve the original `first_seen` date** so age is tracked correctly.
- `observed_prs`: snapshot of ALL currently-open PRs (number + title only) — used to detect new PRs and resolved PRs next run. This must include every entry in `all_open_prs`, not just ones you classified.
- `observed_issues`: same for assigned + unlabeled issues.
- `direction_questions`: new direction questions surfaced this run (string array).

### PHASE_3_CHECKPOINT

- [ ] Every PR in `all_open_prs` is either classified into P1-P4 OR included in `observed_prs` (no PR silently dropped).
- [ ] All P4 entries cite a specific `direction.md §clause`.
- [ ] Carry-over items still pending have their original `first_seen` preserved.
- [ ] Resolved-since-last-run items are surfaced in the brief AND removed from `next_state.carry_over`.
- [ ] `next_state.last_dev_sha` is set from `git-status.output.current_dev_sha`.
- [ ] `next_state.observed_prs` includes ALL currently-open PRs.

---

## Phase 4: REPORT

Return the JSON object only. The workflow's `persist` node writes `brief_markdown` to `.archon/maintainer-standup/briefs/<date>.md` and `next_state` to `.archon/maintainer-standup/state.json`. Do not write files yourself.
53 changes: 53 additions & 0 deletions .archon/maintainer-standup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Maintainer Standup

Daily morning briefing for Archon maintainers. Pulls latest `dev`, fetches all open PRs and assigned issues, classifies them **P1–P4** against `direction.md`, and surfaces progress versus the previous run (merged, closed, what you shipped).

## Files in this folder

| File | Committed? | Purpose |
|------|:---:|---------|
| `direction.md` | ✓ | Project north-star — what Archon IS / IS NOT. **Shared by all maintainers.** Drives PR triage and polite-decline classification. |
| `README.md` | ✓ | This file. |
| `profile.md.example` | ✓ | Template for new maintainers to copy. |
| `profile.md` | gitignored | Your personal config (gh handle, role, focus areas). |
| `state.json` | gitignored | Auto-written carry-over for the next run. |
| `briefs/YYYY-MM-DD.md` | gitignored | Daily prose briefs. Last 3 are read into the next run. |

`direction.md` is committed because triage decisions should be consistent across maintainers and across runs. `profile.md`, `state.json`, and `briefs/` are personal — your focus, your daily notes, your reading material — so each maintainer manages their own.

## Setup for a new maintainer

1. Copy the template:
```bash
cp .archon/maintainer-standup/profile.md.example .archon/maintainer-standup/profile.md
```
2. Edit `profile.md`:
- Set `gh_handle` to your GitHub login.
- Set `role` and `scope` to match your maintainer focus (`main_maintainer` / `everything` for full coverage; narrower for sub-maintainers).
- Optionally fill in **Currently focused on** — the synthesizer weights items toward what you list there.
3. Run it:
```bash
archon workflow run maintainer-standup ""
```
4. The first run is a baseline (no prior state to diff). Subsequent runs compare against `state.json` and surface "Resolved since last run" / "What you shipped" / aged carry-over items.

## How it works (engine view)

1. **Three gather scripts** run in parallel (`bun`, no AI):
- `maintainer-standup-git-status.ts` — fetches `origin/dev`, fast-forwards if safe, captures new commits + diff stat since the last recorded SHA.
- `maintainer-standup-gh-data.ts` — pulls open PRs (full metadata), review-requested PRs, authored-by-me PRs, assigned issues, recently-filed unlabeled issues, and recently-closed PRs/issues since the last run.
- `maintainer-standup-read-context.ts` — reads `direction.md`, `profile.md`, `state.json`, and the last 3 briefs.
2. **Synthesis node** (`command: maintainer-standup`, Claude Sonnet, structured output) reads everything, optionally drills into specific PRs/issues with `gh pr view` / `gh issue view`, classifies P1–P4 against `direction.md`, and returns `{ brief_markdown, next_state }`.
3. **Persist node** writes `brief_markdown` to `briefs/YYYY-MM-DD.md` and `next_state` to `state.json`.

The workflow runs **in the live checkout** (`worktree.enabled: false`) — it has to read this folder and pull `dev`. `--branch` and `--no-worktree` flags are rejected.

## Editing direction.md

`direction.md` is the source of truth for "what Archon is / isn't" during PR triage. Add a clause when a triage decision needs justification (so the next maintainer can reach the same conclusion). When declining a PR, cite the clause inline (e.g., `direction.md §single-developer-tool`).

The synthesizer also surfaces **Direction questions raised** — PRs that touch areas where `direction.md` has no stance yet. Use those to evolve the doc deliberately rather than deciding case-by-case.

## Customizing the brief format

The output structure is defined in `.archon/commands/maintainer-standup.md`. Adjust the Phase 3 template if you want different sections or a different P-tier scheme. The synthesizer's `output_format` schema lives in `.archon/workflows/maintainer-standup.yaml`.
41 changes: 41 additions & 0 deletions .archon/maintainer-standup/direction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Archon Direction

The maintainer-standup workflow consults this document when triaging PRs and issues to suggest which contributions align with the project and which are likely polite-decline candidates.

This file is **committed and shared by all maintainers**. Edit deliberately — direction calls live here so that PR triage stays consistent across runs and across maintainers. When declining a PR, cite the specific clause (e.g., `direction.md §single-developer-tool`).

---

## What Archon IS

- **A remote agentic coding platform.** Control AI coding assistants (Claude Code SDK, Codex SDK, Pi community provider) remotely from Slack, Telegram, GitHub, Discord, CLI, and Web UI.
- **A single-developer tool.** No multi-tenant complexity. Built for one practitioner running their own instance.
- **Platform-agnostic at the conversation layer.** Unified interface across adapters via `IPlatformAdapter`. Stream/batch AI responses in real time.
- **Workflow-driven.** Reproducible AI execution chains defined as YAML DAGs in `.archon/workflows/`. Workflows run in isolated git worktrees by default.
- **Type-safe.** Strict TypeScript everywhere. No `any` without justification.
- **Composable.** Scripts in `.archon/scripts/`, commands in `.archon/commands/`, workflows compose them.
- **Self-hostable.** Bun + TypeScript runtime. SQLite by default; PostgreSQL optional. Zero external service dependencies for core operation.

## What Archon is NOT

- **Not multi-tenant.** No user accounts, role management, billing, or SaaS scaffolding. PRs adding these conflict with the single-developer thesis.
- **Not a hosted service.** No proprietary backend dependencies. Self-hosted by design.
- **Not a general-purpose chat UI.** Adapters are conversation surfaces for *workflow execution*, not standalone chat experiences.
- **Not a replacement for the AI coding agent itself.** Archon orchestrates Claude Code / Codex / Pi — it doesn't reimplement them.
- **Not opinionated about the dev environment.** No mandatory editor integrations, framework lock-in, or Docker requirement beyond what users opt into.
- **Not a workflow marketplace.** Bundled workflows are reference patterns; Archon is not aiming to be a hub for third-party workflow distribution.

## Open questions (no stance yet)

These are direction calls we haven't made. PRs that touch these areas should surface the question for explicit decision rather than be silently accepted or rejected. The workflow may add to this list as new questions appear.

- (No open questions yet — populated over time.)

---

## How to evolve this doc

- Add a "What Archon IS" or "is NOT" line when a PR triage forces a direction call.
- Move "Open questions" entries to the IS / IS NOT sections once decided.
- Reference the relevant clause in PR comments when declining: `direction.md §single-developer-tool`.
- Keep entries short — one or two lines each. The point is fast lookup during triage, not a manifesto.
28 changes: 28 additions & 0 deletions .archon/maintainer-standup/profile.md.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
# Required: your GitHub login (used by gh queries for review-requested / assigned filters).
gh_handle: your-github-login

# Suggested: drives how broadly the synthesizer classifies the queue.
# - main_maintainer / everything → triage all open PRs, not just yours
# - reviewer / focus-area → narrower coverage
role: main_maintainer
scope: everything
---

# Maintainer Profile — Your Name

One paragraph on how you want the brief tuned. The synthesizer reads this verbatim, so write what you actually want it to do.

Example:

> I'm a sub-maintainer focused on the workflow engine. Show me PRs that touch packages/workflows/ first; deprioritize adapter-only PRs unless they're P1.

## What I want from the brief

- (Whatever level of full-repo coverage you want)
- (How aggressively to flag polite-decline candidates)
- (Whether to surface drafts, third-party PRs, etc.)

## Currently focused on

- (Update as priorities shift. Items here rank higher within their P-tier.)
Loading
Loading