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
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
---
name: software-factory-bootstrap
description: Use when processing a bootstrap issue — covers how to create Project, IssueTracker, KnowledgeArticle, and implementation Issue cards from a brief.
---

# Software Factory Bootstrap

Use this skill when the current issue has `issueType: bootstrap`. Your job is
to read the brief, create project artifacts, and set up the issue backlog for
the implementation phase.

## How to write tracker-schema cards

Project, KnowledgeArticle, and Issue cards are plain `.json` files in
the workspace. Use the native `Write` tool with the exact JSON:API
document shape documented below for each card type.

**The system prompt names the live tracker module URL** (the value you
should put in `data.meta.adoptsFrom.module` for Project / Board / Issue /
KnowledgeArticle cards). Use that URL verbatim — do not try to derive it.

| File | adoptsFrom.name |
| ---------------------------------- | ------------------ |
| `Projects/<slug>.json` | `Project` |
| `Boards/<slug>.json` | `IssueTracker` |
| `Knowledge Articles/<slug>-*.json` | `KnowledgeArticle` |
| `Issues/<slug>-<card-slug>.json` | `Issue` |

For each card, the document is:

```json
{
"data": {
"type": "card",
"attributes": { ... per the live schema (see below) ... },
"relationships": { ... per the live schema (see below) ... },
"meta": {
"adoptsFrom": {
"module": "<darkfactoryModuleUrl from system prompt>",
"name": "<Project | Issue | KnowledgeArticle>"
}
}
}
}
```

### Fetch the live schema before writing

Do **not** memorize attribute names, enum values, or relationship keys
for these cards — they evolve. Before writing a Project / Issue /
KnowledgeArticle JSON file, call:

```
get_card_schema({ module: "<darkfactoryModuleUrl>", name: "Project" })
```

(and the same for `Issue` / `KnowledgeArticle`). The tool returns the
live `{ attributes, relationships? }` JSON Schema introspected from the
real `CardDef` — including the allowed enum values for fields like
`status` / `priority` / `issueType` / `articleType` / `projectStatus`
and the relationship keys (`project`, `relatedKnowledge`,
`knowledgeBase`, `blockedBy`, etc.). Use the field names, types, and
enums it returns verbatim. Schemas are cached per-process, so repeated
calls are cheap.

Catalog Spec cards (`Spec/<slug>.json`) are different — they adopt from
`https://cardstack.com/base/spec` / `Spec`. Fetch their schema the same
way: `get_card_schema({ module: "https://cardstack.com/base/spec",
name: "Spec" })`. The catalog spec workflow is documented in the
software-factory-operations skill.

## Naming Conventions

Derive names from the brief title:

- **slug**: lowercase, replace non-alphanumeric runs with hyphens, strip leading/trailing hyphens
- `"Sticky Note"` → `sticky-note`
- **projectCode**: 2-4 uppercase initials from the title words
- `"Sticky Note"` → `SN`
- `"Employee Handbook"` → `EH`
- `"Customer Relationship Manager"` → `CRM` (first 3-4 words)

## Card Authoring Guidance

The field/relationship shapes for each card type are fetched at runtime
via `get_card_schema` (see "Fetch the live schema before writing"
above). This section covers what is **not** in the schema: what to put
in those fields and how to organize the bootstrap output.

### Project Card

**Path:** `Projects/<slug>.json`
**adoptsFrom.name:** `Project`

Fetch the schema, then populate the attributes from the brief:

- The project-name attribute → the brief's title (e.g. `"Sticky Note"`).
- The project-code attribute → 2–4 uppercase initials from the title (e.g. `"SN"`).
- The objective / scope / technical-context / success-criteria attributes → derive from the brief content. Use markdown.
- The status attribute → use one of the enum values returned by the schema for an active project (typically the "active" / starting state — the schema's enum is the source of truth, never guess).

**Relationships:** the schema names the array relationship that links a
project to its knowledge articles. Populate one entry per article you
create (paths like `../Knowledge Articles/<slug>-<article-slug>`).

- `board` → `{ links: { self: "../Boards/<slug>" } }`
- `knowledgeBase.0` → `{ links: { self: "../Knowledge Articles/<slug>-<article-slug>" } }` (one entry per article)

### IssueTracker Card

**Path:** `Boards/<slug>.json`
**adoptsFrom:** `{ module: "<darkfactoryModuleUrl>", name: "IssueTracker" }`

Create one board per bootstrapped project. It is the canonical board for that
project's issues and should be linked both ways with the Project card.

| Field | Type | Example |
| ------------------ | ------- | ----------------- |
| `boardTitle` | String | `"<title> Board"` |
| `hideEmptyColumns` | Boolean | `false` |

**Relationships:**

- `project` → `{ links: { self: "../Projects/<slug>" } }`

### KnowledgeArticle Card

**Paths:** `Knowledge Articles/<slug>-<article-slug>.json` (as many as needed)
**adoptsFrom.name:** `KnowledgeArticle`

Always create at least two articles:

- **Brief Context** (`<slug>-brief-context`) — full brief content and background.
- **Agent Onboarding** (`<slug>-agent-onboarding`) — how to work on this project.

Add more as the brief warrants (e.g., detailed visual design, deep
domain knowledge). Keep each article cohesive with a clear guiding
principle. Use the `articleType` enum values returned by the schema to
classify each one (e.g., one for context, one for onboarding); use the
schema's enum literally.

### Issue Card — Organized by Entry-Point Card

**Paths:** `Issues/<slug>-<card-name-slug>.json` (one per entry-point card, named after the card)
**adoptsFrom.name:** `Issue`

Organize implementation issues around **entry-point cards** — the top-level cards users interact with directly and that should be discoverable in the catalog. Create **one issue per entry-point card**, named after that card.

Each issue covers the full scope of its entry-point card:

- Card definition (`.gts`) and any interior/support cards it depends on
- QUnit tests (`.test.gts`) for the entry-point card **and** all its support cards
- Catalog Spec (`Spec/<card-name>.json`) with realistic example instances via `linkedExamples`

Interior cards (field cards, helper cards, linked supporting types) are
implemented as part of their entry-point card's issue. They need tests
but do **not** need their own catalog specs or separate issues.

**Populating attributes** (consult the schema for the exact field names and enum values):

- The issue-id attribute → `"<projectCode>-<N>"` (sequential).
- The summary attribute → `"Implement <card name> card"`.
- The description attribute → markdown describing the card to create, its fields, support cards, tests, spec, and examples. **Immutable after creation** — see Issue Invariants below.
- The issue-type / status / priority attributes → use the enum values returned by the schema. For a fresh bootstrap, all issues start in the "backlog" state with issue-type "feature". Mark the first issue as the highest non-critical priority and the rest a step lower.
- An `order` field (sequential integer 1, 2, 3, …) for the scheduler.
- The acceptance-criteria attribute → markdown checklist: card def, support cards, tests, spec, examples.
- Timestamp fields → ISO timestamps. Note that on Issues these are top-level attributes (e.g. `createdAt` / `updatedAt`) — distinct from the timestamp field inside individual `comments[]` entries (which is named `datetime`, see operations skill). The schema is the source of truth.

**Relationships for each issue** (the schema names the keys):

- A `project` link → `../Projects/<slug>`.
- Knowledge-article links — one entry per knowledge article you want loaded into the agent's context (typically the brief-context and agent-onboarding articles you created above).
- A blocked-by relationship for any issues that must complete first.

**Dependency ordering:** If one entry-point card depends on another
(e.g., card B uses card A as a field type or linked card), order the
issues so the depended-upon card is implemented first. Set `order`
values accordingly (dependency-free cards get lower order numbers) and
wire the blocked-by relationship so consuming cards cannot start until
their dependencies are done.

If the brief describes only one entry-point card, create one issue. If it describes multiple, create one per entry-point card ordered so dependency cards come first.

## Issue Invariants — read carefully

The orchestrator depends on three rules about Issue cards. Before this
skill rewrite they were enforced by a wrapper tool that stripped /
ignored disallowed fields automatically. Now that you write the JSON
directly, you must enforce them yourself:

1. **`description` is immutable after creation.** Never modify an
Issue's `description` once the card exists. To add post-creation
context (blocked reasons, validation failures, progress notes), use
the `comments` array instead — see "Adding a comment to an existing
issue" in the operations skill.
2. **`status` transitions are restricted to the agent.** You may set
`status` to `"blocked"` (cannot proceed) or `"backlog"` (unblock).
Never set `status` to `"done"` or `"in_progress"` — those are owned
by the orchestrator based on `signal_done` + validation results.
3. **Read before write for updates.** When updating an existing Issue
(or any tracker card), `Read` the file first, modify only the
attributes you intend to change, then `Write` (or `Edit`) the merged
document back. Do not overwrite the whole file with only the new
fields — you'll silently drop existing attributes the file had.

## Why Relationships Matter

The `project` and `relatedKnowledge` relationships on implementation issues are
how the orchestrator loads context for the agent. When the agent picks up an
issue, `ContextBuilder.buildForIssue()` traverses these relationships to
load the Project card and Knowledge Articles into the agent's context. Without
these relationships, the agent would have no project scope or brief content.

## Document Envelope

All three card types share the same JSON:API envelope — only the
`attributes`, `relationships`, and `adoptsFrom.name` differ. The
attribute names, enum values, and relationship keys come from the
schema you fetched with `get_card_schema`; the envelope is fixed:

```json
{
"data": {
"type": "card",
"attributes": {
// populate per the schema returned by:
// get_card_schema({ module: "<darkfactoryModuleUrl>", name: "Issue" })
},
"relationships": {
// each relationship key from the schema points at a sibling
// card via a relative path; arrays use indexed keys (key.0, key.1, …)
"<project-relationship-key>": {
"links": { "self": "../Projects/<slug>" }
}
},
"meta": {
"adoptsFrom": {
"module": "<darkfactoryModuleUrl from system prompt>",
"name": "Issue"
}
}
}
}
```

Use relative paths (`../`) for `links.self` since cards live in sibling
directories within the workspace. The same envelope applies to Project
and KnowledgeArticle — only the `adoptsFrom.name` and the
schema-derived attributes/relationships change.

## Completion

After creating all artifacts, call `signal_done()`. The orchestrator manages
issue status transitions — do NOT set the issue status to "done" yourself.
The orchestrator will mark the issue as done after validation passes.
Loading