158 lines
6.2 KiB
Markdown
158 lines
6.2 KiB
Markdown
---
|
|
type: reference
|
|
title: "Page contracts"
|
|
tags:
|
|
- reference
|
|
---
|
|
|
|
# Page contracts
|
|
|
|
**Read this when creating or editing a page.** The `.md` files beside this one are copy-ready skeletons; this file is the rule they implement. **When a contract changes, change its skeleton in the same edit** — a skeleton that drifts from its contract produces pages the skills can't read.
|
|
|
|
---
|
|
|
|
## Area hub — `2. Areas/<Area>/<Area>_hub.md`
|
|
|
|
```yaml
|
|
type: area
|
|
status: standing # standing | archived
|
|
id_prefix: WEB # short, uppercase, set once, never changed
|
|
workstream_counter: 0 # highest ID issued. Source of truth for IDs
|
|
parent: # nested Areas only. Never points at itself
|
|
updated: YYYY-MM-DD
|
|
tags: [hub, <area-tag>]
|
|
```
|
|
|
|
Body: `## What this is` (one sentence) · `## Workstreams` (each Project by ID, with status) · `## Open items` · `## Key files` · `## People`.
|
|
|
|
**Areas take no `next:`, no `deadline:`, and no freshness computation.** A container doesn't compete for attention.
|
|
|
|
Every Area has `2. Areas/<Area>/knowledge/_index.md` — seeded at creation, stating what belongs there.
|
|
|
|
---
|
|
|
|
## Project hub — `1. Projects/<Area>/<Name>/<ID>_hub.md`
|
|
|
|
```yaml
|
|
type: project # never `hub`
|
|
id: WEB-1 # from the Area's workstream_counter
|
|
area: <Area folder name> # or the literal `none` — absent ≠ none
|
|
done_when: "one sentence, testable"
|
|
status: open # open | paused | closed | archived
|
|
next: "verb → target — detail [since YYYY-MM-DD]" # optional; may be a YAML list
|
|
paused_because: "one line" # required when paused
|
|
deadline: YYYY-MM-DD # optional — the single next delivery gate
|
|
threads: [slug]
|
|
updated: YYYY-MM-DD
|
|
tags: [hub, <area-tag>]
|
|
```
|
|
|
|
Body: `## What this is` · `## Tasks` (checkboxes, `(owned by: name)` when not the owner's) · `## Open items` · `## Key files` · `## People`.
|
|
|
|
- **`done_when:` is required.** If you can't write it, it isn't a Project. If it needs the words "ongoing", "maintain" or "as needed", it's an Area.
|
|
- **`next:` — one move per entry.** Two moves go in a YAML list, never packed into one string. Grammar and verbs → `AGENTS.md`, *The `next:` field*.
|
|
- **`area: none` is legal but must be written.** Such a project has no knowledge base to receive its deliverable; `polaris-close` archives it whole.
|
|
|
|
**A workstream *is* a Project.** It opens when an Area needs finite work done, and closes via `polaris-close`, which returns its deliverable to the Area:
|
|
|
|
```
|
|
Area ──spawns──▶ Project (id, done_when)
|
|
▲ │ on close
|
|
└── knowledge/ ◀───┤ deliverable
|
|
└── process record ──▶ 5. Archive/<Area>/<ID>/
|
|
```
|
|
|
|
A workstream belongs to exactly one Area. A concern spanning several is a **thread**.
|
|
|
|
---
|
|
|
|
## Person — `3. Resources/People/<Full Name>.md`
|
|
|
|
```yaml
|
|
type: person
|
|
tier: contact # relationship | contact
|
|
name: Full Name
|
|
pronouns: # ask; never infer from a name. Blank until known
|
|
role:
|
|
orgs: []
|
|
contact:
|
|
status: active # active | dormant
|
|
cadence: # relationship tier ONLY: weekly | biweekly | monthly | organic
|
|
last_contact: YYYY-MM-DD
|
|
follow_up_by: # relationship tier ONLY — a real date
|
|
updated: YYYY-MM-DD
|
|
tags: [person]
|
|
```
|
|
|
|
Body: `## Role & Relationship` · `## Background` · `## Context` · `## Open Items` · `## Contact History` (dated lines, newest first).
|
|
|
|
**Two tiers, and only one can flag:**
|
|
|
|
| Tier | Carries | Can flag? |
|
|
|---|---|---|
|
|
| `relationship` | `cadence` + `follow_up_by`, both required | **Yes** — the only pages follow-up checks read |
|
|
| `contact` | Neither — their presence is a lint finding | **Never** |
|
|
|
|
**A contact is not a neglected relationship.** It's someone the vault knows facts about. If someone doesn't warrant a real follow-up date, they're a contact.
|
|
|
|
- **`organic` cadence** means "no fixed interval — the next contact is pegged to a specific event." It still requires a real `follow_up_by`, set against that event.
|
|
- **A relationship page with no `follow_up_by` cannot flag and is invisible.** Lint reports it as a defect.
|
|
- **Spent follow-ups.** A `follow_up_by` on or before `last_contact` has been overtaken by contact. Compute the live due date instead: `weekly`/`biweekly`/`monthly` → `last_contact` + 7/14/30 days, rendered *(from last contact)*; `organic` → **no date since contact** (never overdue). **Never write the computed date back** — the stored field stays what a person set.
|
|
- **`status: dormant`** — the engagement ended; the page and every fact stay.
|
|
|
|
---
|
|
|
|
## Decision — `4. Decisions/YYYY-MM-DD-<slug>.md`
|
|
|
|
```yaml
|
|
type: decision
|
|
date: YYYY-MM-DD
|
|
topic: Short title
|
|
areas: [Area or Project]
|
|
status: open # open | closed | reversed
|
|
updated: YYYY-MM-DD
|
|
tags: [decision]
|
|
```
|
|
|
|
Body: `## Context` · `## Decision` · `## Rationale` · `## Expected outcome` · `## Follow-up` (dated lines).
|
|
|
|
**Never edit a past decision's substance.** A reversal is a new decision file that links the old one; the old one's `status` becomes `reversed`.
|
|
|
|
---
|
|
|
|
## Thread — `3. Resources/Threads/<slug>.md`
|
|
|
|
```yaml
|
|
type: thread
|
|
title: Short title
|
|
status: open # open | watching | resolved | dropped
|
|
domains: [Area or Project]
|
|
people: [Full Name]
|
|
opened: YYYY-MM-DD
|
|
updated: YYYY-MM-DD
|
|
tags: [thread]
|
|
```
|
|
|
|
Body: `## What it is` · `## Why cross-cutting` · `## Current state` (replace, don't stack) · `## What's needed` · `## Update log` (append-only, newest first).
|
|
|
|
**A thread opens** when one signal shows up in two or more separate Areas or Projects. **It closes** when a decision resolves it, or it collapses to a single domain. Resolved and dropped threads move to `5. Archive/Threads/`.
|
|
|
|
---
|
|
|
|
## Reference note — `3. Resources/Research/` or `2. Areas/<Area>/knowledge/`
|
|
|
|
```yaml
|
|
type: reference
|
|
title:
|
|
source: # file, URL, sender, conversation — or "source unrecorded"
|
|
updated: YYYY-MM-DD
|
|
tags: [reference, <topic or area tag>]
|
|
```
|
|
|
|
**`source:` is never blank.** Placement → `AGENTS.md`, *The classification test*.
|
|
|
|
---
|
|
|
|
## Inbox notes
|
|
|
|
Daily notes and weekly sweeps carry `date:` and `tags: [inbox, daily-note]` / `[inbox, weekly-sweep]` — no `type:`. Captures carry `date:` and `tags: [inbox]`.
|