Skip to content
Open
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
146 changes: 146 additions & 0 deletions PLAN-close-and-intents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# gsync Feature Plan: Plan Closing & Intents System (V1)

> **Authors:** rdlekuch
> **Status:** Implemented
> **Branch:** `feat/close-and-intents`

---

## Context

gsync V1 is a repo-native file-based context system — no Firebase, no CLI binary, no dashboard, no backend. Context lives as markdown files in `.gsync/` directories within each project repo. Agents interact with gsync by reading/writing local files following skill-defined conventions.

This plan covers two features redesigned from the original Firebase prototype to work natively with V1's file-based, skill-driven architecture.

---

## Feature A: Plan Closing / Archiving

### Problem

Plans are markdown files in the activity collection. There's no lifecycle — a plan file just exists or doesn't. Stale, obsolete, or superseded plans sit alongside active ones, cluttering agent context.

### Solution

Plan lifecycle expressed through YAML frontmatter + archive subdirectory:

1. **Frontmatter `status` field** — `active` (default) or `closed`, plus `closed_date` and `closed_reason`
2. **Archive directory** — closed plans move to `.gsync/data/activity/archive/` so agents scanning for active plans only see the root directory

```yaml
---
status: closed
summary: Refactor auth module to use JWT
touches: [src/auth/jwt.ts, src/middleware/auth.ts]
created: 2026-04-08
closed_date: 2026-04-10
closed_reason: Completed and merged in PR #42
---
```

### Rules

- Never delete plan files — always close and archive
- A plan without a `status` field is treated as active (backward compatible)
- Frontmatter `status` is the source of truth regardless of file location
- Only scan activity root for active plans, not `archive/`

---

## Feature B: Intents System

### Problem

When someone thinks "I should build X eventually," that thought has nowhere to go. They either create a premature plan or say nothing, leading to duplicated work.

### Solution

Intents are lightweight pre-plan signals stored as `intent-<slug>.md` files in `.gsync/data/activity/intents/`:

```yaml
---
status: open
summary: Speed up CI builds by parallelizing test suites
touches: [.github/workflows/ci.yml, jest.config.ts]
created: 2026-04-10
claimed_by:
claimed_note:
---

Optional longer description or context here.
```

### Intent Lifecycle

```
open → claimed → closed
│ ↑
└─────────────────┘ (can close directly)
```

- `open` — available, no one working on it
- `claimed` — someone is actively starting work (with a required note, max 150 chars)
- `closed` — fulfilled by a plan or no longer relevant

### Rules

- Anyone can create intents, anyone can claim open intents
- `claimed` means "do not duplicate without coordinating"
- Closed intents stay in `intents/` (not archived — they're small)
- Agents must check intents before creating new plans (overlap check)

---

## Overlap Matching

Before creating a new plan, agents read all open/claimed intent files and check for:
- Shared key terms in `summary` fields
- Overlapping entries in `touches` arrays

This is judgment-based, not algorithmic. The agent flags potential overlaps to the user and asks whether the plan fulfills, extends, or is unrelated to each matching intent.

---

## Activity Collection Structure

```
.gsync/data/activity/
activity.md # collection doc
refactor-auth.md # active plan
migrate-db.md # active plan
intents/
intent-faster-builds.md # open intent
intent-dark-mode.md # claimed intent
archive/
old-feature.md # closed plan
```

---

## Implementation

All behavior is defined through skill instructions — no code, no infrastructure.

### Files Modified

1. **`skills/gsync/SKILL.md`** — Added three sections: Plan Lifecycle, Intents, Overlap Check Before Plan Creation. Updated Required Workflow (added step 6: check intents) and example activity collection doc.

2. **`skills/gsync-onboarding/SKILL.md`** — Updated recommended `activity.md` draft with intent files, archive conventions, and plan/intent lifecycle sections. Updated starter `GSYNC.md` draft with collection conventions.

3. **`README.md`** — Added plan lifecycle and intents to V1 feature list.

### No New Files at Repo Level

`intents/` and `archive/` directories are created at runtime by agents following skill instructions in target projects. No config.json schema changes needed.

---

## Verification

Read both skills as a fresh agent and verify:

- [ ] Following Plan Lifecycle instructions, an agent can close a plan (set frontmatter, move to archive)
- [ ] Following Intents instructions, an agent can create, claim, and close intents
- [ ] Following Overlap Check instructions, an agent creating a plan checks intents first
- [ ] The onboarding skill's `activity.md` draft mentions intents and archive conventions
- [ ] The starter `GSYNC.md` draft mentions plan lifecycle and intents in collection conventions
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ V1 is intentionally small:
- a reusable `gsync-onboarding` skill
- a minimal `.gsync/config.json` contract
- project-local docs that tell agents how this repo uses `gsync`
- plan lifecycle (active/closed with archive) and intents (lightweight pre-plan coordination signals)

The old Firebase prototype is preserved in [legacy/firebase-prototype](/Users/nathanwang/Projects/nomergeconflicts/legacy/firebase-prototype).

Expand Down
24 changes: 24 additions & 0 deletions skills/gsync-onboarding/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,18 @@ This project uses `gsync` to keep agent-readable context in the working tree its
## Collection Conventions

- `activity` is for current work context and plan artifacts
- `activity` plans use frontmatter with `status: active` or `status: closed`
- `activity` intents live in the `intents/` subdirectory as lightweight pre-plan signals
- closed plans are moved to the `archive/` subdirectory
- `company` is for broader context that should inform planning and execution

## Guardrails

- do not invent new collection structure without updating docs
- do not silently add collections
- ask before changing core conventions
- before creating a new plan, check `intents/` for overlapping intents
- never delete plan or intent files; close and archive instead

## Not Yet Implemented

Expand Down Expand Up @@ -272,17 +277,35 @@ Store developer coordination artifacts for current and upcoming work.
## Canonical Artifacts

- plan files
- intent files

## Read Before Writing

- read existing plan files that look relevant to the task
- avoid duplicating parallel plans for the same work
- check the `intents/` subdirectory for open intents before creating a new plan

## Write Conventions

- use markdown files for plans
- keep one plan per workstream
- name files descriptively according to the project's chosen convention
- store intents in the `intents/` subdirectory with `intent-<slug>.md` naming
- archive closed plans to the `archive/` subdirectory
- plans and intents use YAML frontmatter with at least `status`, `summary`, and `created`

## Plan Lifecycle

- plans start with `status: active` (or no status field, which implies active)
- to close a plan, set `status: closed`, add `closed_date` and `closed_reason`, and move the file to `archive/`
- never delete plan files

## Intent Lifecycle

- intents start with `status: open`
- intents can be claimed (`status: claimed`) with a `claimed_by` and `claimed_note` (max 150 chars)
- `claimed` means someone is actively working toward a plan — do not duplicate without coordinating
- intents are closed in place (not moved to archive) with `status: closed`, `closed_date`, and `closed_reason`

## Scripts and Automation

Expand All @@ -292,6 +315,7 @@ No collection-local scripts yet.

- do not introduce a global summary format in V1
- do not create extra coordination artifacts unless the project docs ask for them
- do not delete plan or intent files; close and archive instead
```

### Recommended `company.md` Draft
Expand Down
137 changes: 136 additions & 1 deletion skills/gsync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,21 @@ Store developer coordination artifacts for current and upcoming work.
## Canonical Artifacts

- plan files
- intent files

## Read Before Writing

- read existing plan files that look relevant to the task
- avoid creating parallel plans for the same workstream
- check the `intents/` subdirectory for open intents before creating a new plan

## Write Conventions

- use markdown files for plans
- keep one plan per workstream
- name files descriptively according to the current project's chosen convention
- store intents in the `intents/` subdirectory with `intent-<slug>.md` naming
- archive closed plans to the `archive/` subdirectory

## Scripts and Automation

Expand All @@ -211,6 +215,7 @@ No collection-local scripts yet.

- do not introduce a universal summary format in V1
- do not create extra coordination artifacts unless the project docs ask for them
- do not delete plan or intent files; close and archive them instead
```

## Required Read Order
Expand Down Expand Up @@ -282,7 +287,8 @@ After reading config and docs:
3. Find the collection or collections relevant to the task
4. Read each relevant collection doc
5. Inspect the existing canonical artifacts in those collections
6. Make the minimum change that follows the documented conventions
6. If creating a new plan, check intents for overlap first (see "Overlap Check Before Plan Creation")
7. Make the minimum change that follows the documented conventions

## Behavior Inside Collections

Expand All @@ -294,6 +300,135 @@ When writing inside a collection:
- reference collection-local scripts only if the collection doc tells you to use them
- keep the write proportional to the task instead of redesigning the collection

## Plan Lifecycle

Plans use YAML frontmatter to track their lifecycle status.

**Frontmatter fields:**

| Field | Required | Description |
|-------|----------|-------------|
| `status` | no | `active` (default) or `closed`. Omitting `status` means active. |
| `summary` | yes | One-line description of the plan. |
| `touches` | no | List of file paths this plan affects. |
| `created` | yes | Date the plan was created (YYYY-MM-DD). |
| `closed_date` | when closing | Date the plan was closed. |
| `closed_reason` | when closing | Why the plan was closed. |

**Active plan example:**

```yaml
---
status: active
summary: Refactor auth module to use JWT
touches: [src/auth/jwt.ts, src/middleware/auth.ts]
created: 2026-04-08
---
```

**Closed plan example:**

```yaml
---
status: closed
summary: Refactor auth module to use JWT
touches: [src/auth/jwt.ts, src/middleware/auth.ts]
created: 2026-04-08
closed_date: 2026-04-10
closed_reason: Completed and merged in PR #42
---
```

**How to close a plan:**

1. Set `status: closed` in the frontmatter
2. Add `closed_date` and `closed_reason`
3. Move the file to the `archive/` subdirectory of the activity collection
4. Create `archive/` if it does not exist

**Rules:**

- Never delete plan files. Always close and archive them.
- A plan without a `status` field is treated as active (backward compatible).
- When listing active plans, read files from the activity collection root directory only. Do not scan `archive/`.
- The frontmatter `status` field is the source of truth. A file with `status: closed` is closed regardless of where it is located.

## Intents

Intents are lightweight pre-plan signals. They express "I want to work on this" without committing to a full plan's scope, timeline, or alignment.

Intents are stored in the `intents/` subdirectory of the activity collection as `intent-<slug>.md` files.

**Intent frontmatter fields:**

| Field | Required | Description |
|-------|----------|-------------|
| `status` | yes | `open`, `claimed`, or `closed`. |
| `summary` | yes | Short description of the intended work. |
| `touches` | no | List of file paths this intent would affect. |
| `created` | yes | Date the intent was created (YYYY-MM-DD). |
| `claimed_by` | when claiming | Name or identifier of who claimed it. |
| `claimed_note` | when claiming | What the claimer plans to do (max 150 characters). |
| `closed_date` | when closing | Date the intent was closed. |
| `closed_reason` | when closing | Why it was closed (e.g., "Fulfilled by plan refactor-auth.md"). |

**Intent lifecycle:**

```
open → claimed → closed
│ ↑
└─────────────────┘ (can close directly without claiming)
```

**Open intent example:**

```yaml
---
status: open
summary: Speed up CI builds by parallelizing test suites
touches: [.github/workflows/ci.yml, jest.config.ts]
created: 2026-04-10
claimed_by:
claimed_note:
---

Optional longer description or context here.
```

**Claimed intent example:**

```yaml
---
status: claimed
summary: Speed up CI builds by parallelizing test suites
touches: [.github/workflows/ci.yml, jest.config.ts]
created: 2026-04-10
claimed_by: nathan
claimed_note: Starting with vitest parallel config first
---
```

**Rules:**

- Anyone can create an intent. Anyone can claim an open intent.
- `claimed` means someone is actively working toward a plan for this. Do not open a duplicate intent or plan without coordinating first.
- To close an intent, set `status: closed`, add `closed_date` and `closed_reason`. Leave the file in the `intents/` directory (do not move it to archive — intents are small enough that closed ones are not noisy).
- When listing open intents, filter by `status: open` or `status: claimed`.
- Keep `claimed_note` to 150 characters or fewer.

## Overlap Check Before Plan Creation

Before creating a new plan in the activity collection, check for overlapping intents:

1. Read all `intent-*.md` files in the `intents/` subdirectory.
2. For each intent with `status: open` or `status: claimed`, check whether your plan describes similar work:
- Look for shared key terms in the `summary` fields (shared nouns, shared domain concepts).
- Look for overlapping entries in the `touches` arrays (shared file paths or shared parent directories).
3. If you find a likely overlap, tell the user which intent(s) may be related and ask whether the plan fulfills, extends, or is unrelated to each.
4. If the plan fulfills an intent, close the intent: set `status: closed`, `closed_date` to today, and `closed_reason` to `Fulfilled by plan <plan-filename>.md`.

This check is judgment-based, not algorithmic. Flag potential overlaps and let the user decide. False negatives are acceptable — this is a coordination signal, not a locking mechanism.

## What To Surface To The User

Flag these instead of deciding silently:
Expand Down