feat(P02): opencode integration layer (#2)
18 CI agents, 11 workflows, 11 commands, 5 references, 3 contexts. Zero learnship dependencies.
This commit was merged in pull request #2.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
<branch_strategy>
|
||||
|
||||
Canonical branch naming and lifecycle conventions for CI. Branches encode project structure — merged branches indicate completed work, active branches indicate work in progress.
|
||||
|
||||
---
|
||||
|
||||
## Branch Types
|
||||
|
||||
### Phase Branches
|
||||
|
||||
**Format:** `phase/NN-slug`
|
||||
|
||||
| Part | Convention |
|
||||
|------|-----------|
|
||||
| `NN` | Zero-padded phase number (01, 02, ..., 12) |
|
||||
| `slug` | Lowercase, hyphenated phase name |
|
||||
|
||||
**Examples:**
|
||||
- `phase/01-git-native-architecture`
|
||||
- `phase/02-opencode-integration`
|
||||
- `phase/03-agent-implementations`
|
||||
|
||||
**Lifecycle:**
|
||||
1. Created at phase start by `GitBranch.createPhaseBranch()`
|
||||
2. All task commits for the phase land on this branch
|
||||
3. Merged to main (squash) on phase completion
|
||||
4. Merged = phase complete, active = phase in progress, absent = not started
|
||||
|
||||
### Milestone Branches
|
||||
|
||||
**Format:** `milestone/vX.X-slug`
|
||||
|
||||
| Part | Convention |
|
||||
|------|-----------|
|
||||
| `vX.X` | Semver milestone version |
|
||||
| `slug` | Lowercase, hyphenated milestone name |
|
||||
|
||||
**Examples:**
|
||||
- `milestone/v0.2-git-native`
|
||||
- `milestone/v1.0-mvp`
|
||||
|
||||
**Lifecycle:**
|
||||
1. Created at first phase of milestone by `GitBranch.createMilestoneBranch()`
|
||||
2. Spans multiple phases within the same milestone
|
||||
3. Merged to main on milestone completion
|
||||
4. Merged = milestone complete, active = milestone in progress
|
||||
|
||||
### Hotfix Branches
|
||||
|
||||
**Format:** `hotfix/description`
|
||||
|
||||
Created for urgent fixes outside the normal phase flow. Merged directly to main.
|
||||
|
||||
## Branch Status Inference
|
||||
|
||||
The `GitBranch` class and `GitContext` class determine status from the branch list:
|
||||
|
||||
```typescript
|
||||
const branches = gitContext.getBranches();
|
||||
// Phase branches: type = "phase", phaseNumber, merged boolean
|
||||
// Milestone branches: type = "milestone", milestone string, merged boolean
|
||||
```
|
||||
|
||||
| Branch State | Meaning |
|
||||
|-------------|---------|
|
||||
| Branch exists, not merged | Phase/milestone is active (in progress) |
|
||||
| Branch exists, merged | Phase/milestone is complete |
|
||||
| Branch does not exist | Phase/milestone has not started |
|
||||
|
||||
## Merge Strategy
|
||||
|
||||
Default: **squash merge** into main.
|
||||
|
||||
```typescript
|
||||
gitBranch.mergePhaseBranch("phase/01-git-native-architecture", "main", true);
|
||||
```
|
||||
|
||||
Squash merge keeps main clean while preserving full development history in the phase branch. Phase branches can be deleted after merge if desired.
|
||||
|
||||
## Phase Discovery
|
||||
|
||||
```typescript
|
||||
const gitBranch = new GitBranch(projectPath);
|
||||
const phases = gitBranch.listPhases();
|
||||
// Returns: PhaseBranchInfo[] with phaseNumber, slug, branchName, status
|
||||
|
||||
const milestones = gitBranch.listMilestones();
|
||||
// Returns: MilestoneBranchInfo[] with version, slug, branchName, status
|
||||
```
|
||||
|
||||
## Branch Creation Rules
|
||||
|
||||
1. Always create phase branches from main (or the current milestone branch)
|
||||
2. Never create a branch for a completed phase — it should already be merged
|
||||
3. Milestone branches span phases — don't create one per phase
|
||||
4. Use `GitBranch.createPhaseBranch()` to ensure consistent naming
|
||||
5. Use `GitBranch.createMilestoneBranch()` to ensure consistent naming
|
||||
|
||||
## Working with Phase Branches
|
||||
|
||||
```bash
|
||||
# Create a phase branch
|
||||
git checkout -b phase/01-git-native-architecture
|
||||
|
||||
# Commit work with ---ci--- blocks
|
||||
git commit -m "feat(P01-01-01): implement commit parser
|
||||
|
||||
---ci---
|
||||
phase: 1
|
||||
milestone: v0.2
|
||||
plan: 01-01
|
||||
task: 01-01-01
|
||||
status: execute
|
||||
---/ci---"
|
||||
|
||||
# Merge on completion
|
||||
git checkout main
|
||||
git merge --squash phase/01-git-native-architecture
|
||||
git commit -m "docs(P01): complete git-native-architecture phase"
|
||||
```
|
||||
|
||||
</branch_strategy>
|
||||
@@ -0,0 +1,149 @@
|
||||
<ci_files_discipline>
|
||||
|
||||
How CI manages the `.ci/` directory — long-lived reference documents only. Dynamic state lives in the git log via `---ci---` YAML blocks, not in files.
|
||||
|
||||
---
|
||||
|
||||
## What Lives in `.ci/`
|
||||
|
||||
| File | Purpose | Update Frequency |
|
||||
|------|---------|-------------------|
|
||||
| `config.json` | Project-level CI configuration | Rare (initialization, setting changes) |
|
||||
| `PROJECT.md` | Vision, core value, requirements, constraints, key decisions | Low (phase boundaries) |
|
||||
| `ARCHITECTURE.md` | System architecture, component boundaries, data flow | Low (major refactors) |
|
||||
| `ROADMAP.md` | Phase breakdown, milestone mapping, success criteria | Low (phase transitions) |
|
||||
| `REQUIREMENTS.md` | v1/v2 requirements with REQ-IDs, out of scope, traceability | Low (requirement changes) |
|
||||
|
||||
## What Does NOT Live in `.ci/`
|
||||
|
||||
These were removed in v0.2.0 and now live in the git log:
|
||||
|
||||
| Previous Location | Now In | Access Method |
|
||||
|-------------------|--------|---------------|
|
||||
| `.ci/audit/decisions.json` | `---ci---` decisions block | `GitContext.getDecisions()` |
|
||||
| `.ci/audit/escalations.json` | `---ci---` escalations block | `GitContext.getEscalations()` |
|
||||
| `.ci/audit/lessons.json` | `---ci---` lessons block | `GitContext.getLessons()` |
|
||||
| `.planning/` directory | Git log + branches | `GitContext.reconstructState()` |
|
||||
|
||||
## CiFiles API
|
||||
|
||||
| Method | Returns | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `ensureCIDir()` | void | Create `.ci/` if it doesn't exist |
|
||||
| `isInitialized()` | boolean | Check if `.ci/config.json` exists |
|
||||
| `readProjectMd()` | ProjectMd \| null | Read project definition |
|
||||
| `writeProjectMd(project, reason)` | void | Write project definition |
|
||||
| `readRoadmapMd()` | RoadmapMd \| null | Read roadmap |
|
||||
| `writeRoadmapMd(roadmap)` | void | Write roadmap |
|
||||
| `readRequirementsMd()` | RequirementsMd \| null | Read requirements |
|
||||
| `writeRequirementsMd(requirements)` | void | Write requirements |
|
||||
| `readArchitectureMd()` | ArchitectureMd \| null | Read architecture |
|
||||
| `writeArchitectureMd(architecture)` | void | Write architecture |
|
||||
| `updateRequirementStatus(reqId, status)` | void | Update a single requirement status |
|
||||
| `updatePhaseStatus(phaseNumber, status)` | void | Update a single phase status |
|
||||
|
||||
## Update Discipline
|
||||
|
||||
1. **Update with reason** — `writeProjectMd()` takes a `reason` parameter. Every write must justify why.
|
||||
2. **Phase boundaries** — Major updates happen at phase transitions, not during task execution.
|
||||
3. **Requirements status** — Use `updateRequirementStatus()` for single-status changes, not full rewrites.
|
||||
4. **Phase status** — Use `updatePhaseStatus()` for phase transitions, not full roadmap rewrites.
|
||||
5. **Commit after write** — Every `.ci/` file change should be committed immediately with a `---ci---` block.
|
||||
|
||||
## Update Triggers
|
||||
|
||||
| When | What to Update | Method |
|
||||
|------|---------------|--------|
|
||||
| Project initialization | All files from scratch | `write*` methods |
|
||||
| Phase transition | Phase status in ROADMAP.md | `updatePhaseStatus()` |
|
||||
| Requirement met | Requirement status in REQUIREMENTS.md | `updateRequirementStatus()` |
|
||||
| Architecture change | ARCHITECTURE.md | `writeArchitectureMd()` |
|
||||
| Scope change | PROJECT.md | `writeProjectMd()` |
|
||||
|
||||
## File Schemas
|
||||
|
||||
### PROJECT.md
|
||||
|
||||
```typescript
|
||||
interface ProjectMd {
|
||||
name: string;
|
||||
coreValue: string;
|
||||
requirements: {
|
||||
validated: string[];
|
||||
active: string[];
|
||||
outOfScope: string[];
|
||||
};
|
||||
constraints: string[];
|
||||
context: string;
|
||||
keyDecisions: Array<{
|
||||
decision: string;
|
||||
rationale: string;
|
||||
outcome: string;
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
### ROADMAP.md
|
||||
|
||||
```typescript
|
||||
interface RoadmapMd {
|
||||
overview: string;
|
||||
phases: Array<{
|
||||
number: number;
|
||||
name: string;
|
||||
description: string;
|
||||
status: "not_started" | "in_progress" | "complete" | "deferred";
|
||||
dependsOn: number[];
|
||||
requirements: string[];
|
||||
successCriteria: string[];
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
### REQUIREMENTS.md
|
||||
|
||||
```typescript
|
||||
interface RequirementsMd {
|
||||
v1: Array<{
|
||||
category: string;
|
||||
items: Array<{ id: string; description: string }>;
|
||||
}>;
|
||||
v2: Array<{
|
||||
category: string;
|
||||
items: Array<{ id: string; description: string }>;
|
||||
}>;
|
||||
outOfScope: Array<{ feature: string; reason: string }>;
|
||||
traceability: Array<{
|
||||
requirement: string;
|
||||
phase: number;
|
||||
status: "pending" | "in_progress" | "complete" | "blocked";
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
### ARCHITECTURE.md
|
||||
|
||||
```typescript
|
||||
interface ArchitectureMd {
|
||||
overview: string;
|
||||
components: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
boundaries: string;
|
||||
dependsOn: string[];
|
||||
}>;
|
||||
dataFlow: string;
|
||||
buildOrder: string[];
|
||||
}
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Never write dynamic state (decisions, escalations, lessons) to `.ci/` files
|
||||
- Never update `.ci/` files during task execution — update at phase boundaries
|
||||
- Never skip the `reason` parameter when writing PROJECT.md
|
||||
- Never commit `.ci/` changes without a `---ci---` block
|
||||
- Never create new files in `.ci/` without updating this reference document
|
||||
- Never store counters, timestamps, or session state in `.ci/` files
|
||||
|
||||
</ci_files_discipline>
|
||||
@@ -0,0 +1,108 @@
|
||||
<commit_schema>
|
||||
|
||||
Canonical `---ci---` YAML block schema for CI commits. Every CI-generated commit contains a structured YAML block that enables full project state reconstruction from the git log alone.
|
||||
|
||||
---
|
||||
|
||||
## Block Format
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
---ci---
|
||||
phase: <number>
|
||||
milestone: <string>
|
||||
plan: <string> # optional
|
||||
task: <string> # optional
|
||||
status: <pipeline_stage>
|
||||
decisions: # optional
|
||||
- id: D-001
|
||||
decision: <text>
|
||||
rationale: <text>
|
||||
confidence: <0.0-1.0>
|
||||
alternatives: [<alt1>, <alt2>]
|
||||
escalations: # optional
|
||||
- id: E-001
|
||||
type: <escalation_type>
|
||||
description: <text>
|
||||
resolution: pending|timeout|human|auto
|
||||
requirements: # optional
|
||||
covered: [REQ-01, REQ-02]
|
||||
partial: [REQ-03]
|
||||
lessons: # optional
|
||||
- <text>
|
||||
compound: # optional
|
||||
category: <string>
|
||||
problem: <text>
|
||||
solution: <text>
|
||||
---/ci---
|
||||
```
|
||||
|
||||
## Commit Types
|
||||
|
||||
| Type | Purpose | Scope |
|
||||
|------|---------|-------|
|
||||
| `feat` | New feature | `P##-##-##` |
|
||||
| `fix` | Bug fix | `P##-##-##` |
|
||||
| `test` | Test-only | `P##-##-##` |
|
||||
| `refactor` | Code cleanup | `P##-##-##` |
|
||||
| `docs` | Documentation | `P##`, `init`, `milestone` |
|
||||
| `chore` | Config, deps, tooling | `P##` |
|
||||
| `perf` | Performance | `P##-##-##` |
|
||||
| `wip` | Paused state | `P##` |
|
||||
| `decision` | Standalone decision record | `P##` |
|
||||
| `compound` | Compound learning | `P##` |
|
||||
| `escalation` | Escalation artifact | `P##` |
|
||||
| `verify` | Verification result | `P##` |
|
||||
| `note` | Contextual annotation | `P##` |
|
||||
| `todo` | Future intent | `P##` |
|
||||
|
||||
## Scope Format
|
||||
|
||||
| Context | Format | Example |
|
||||
|---------|--------|---------|
|
||||
| Initialization | `init` | `docs(init): initialize project (5 phases)` |
|
||||
| Milestone | `milestone` | `docs(milestone): complete v1.0-mvp` |
|
||||
| Phase-level | `P##` | `docs(P03): complete auth phase` |
|
||||
| Plan-level | `P##-##` | `feat(P03-01): implement JWT` |
|
||||
| Task-level | `P##-##-##` | `feat(P03-01-02): add refresh rotation` |
|
||||
|
||||
Phase numbers are zero-padded to 2 digits. Plan and task numbers are not zero-padded.
|
||||
|
||||
## Builder Methods
|
||||
|
||||
The `CommitBuilder` class provides typed constructors:
|
||||
|
||||
| Method | Input | Commit Type |
|
||||
|--------|-------|-------------|
|
||||
| `buildInitCommit` | InitCommitInput | `docs(init)` |
|
||||
| `buildTaskCommit` | TaskCommitInput | any task type |
|
||||
| `buildPhaseCompletionCommit` | PhaseCompletionInput | `docs(P##)` |
|
||||
| `buildDecisionCommit` | DecisionCommitInput | `decision(P##)` |
|
||||
| `buildEscalationCommit` | EscalationCommitInput | `escalation(P##)` |
|
||||
| `buildCompoundCommit` | CompoundCommitInput | `compound(P##)` |
|
||||
| `buildVerifyCommit` | VerifyCommitInput | `verify(P##)` |
|
||||
| `buildResearchCommit` | phase, milestone, subject, findings | `docs(P##)` |
|
||||
|
||||
## Reconstruction Guarantee
|
||||
|
||||
An agent with access to only commit messages (no code, no diffs, no .ci/ files) can reconstruct:
|
||||
|
||||
1. **Current phase and milestone** — from the latest commit's `phase` and `milestone` fields
|
||||
2. **Pipeline stage** — from the latest commit's `status` field
|
||||
3. **All decisions** — by collecting `decisions[]` from commits where `type: decision` or any commit with a `decisions` block
|
||||
4. **All escalations** — by collecting `escalations[]` from `type: escalation` commits
|
||||
5. **Requirements coverage** — by aggregating `requirements.covered` and `requirements.partial` across all commits
|
||||
6. **Lessons learned** — by collecting `lessons[]` across all commits
|
||||
7. **Compound learnings** — by collecting `compound` objects across all commits
|
||||
8. **Phase completion status** — from the branch state (merged = complete, active = in progress)
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Never put CI metadata in code comments — it belongs in commit messages
|
||||
- Never omit the `---ci---` block from a CI-generated commit
|
||||
- Never store decisions, escalations, or lessons in files — commit them
|
||||
- Never use a non-standard commit type — use the 14 types above
|
||||
- Never put freeform text inside the YAML block — use the structured fields
|
||||
|
||||
</commit_schema>
|
||||
@@ -0,0 +1,104 @@
|
||||
<decision_engine>
|
||||
|
||||
How CI makes decisions and commits them as git artifacts. The DecisionEngine uses bounded rationality with confidence thresholds to auto-decide or escalate.
|
||||
|
||||
---
|
||||
|
||||
## Confidence Thresholds
|
||||
|
||||
| Level | Range | Action |
|
||||
|-------|-------|--------|
|
||||
| High | > 0.85 | Auto-decide, commit with minimal logging |
|
||||
| Medium | 0.60–0.85 | Auto-decide, commit with assumption logging |
|
||||
| Low | < 0.60 | Escalate to human |
|
||||
|
||||
The threshold is configurable via `config.autonomy.decision_confidence_threshold` (default: 0.60).
|
||||
|
||||
## Decision Flow
|
||||
|
||||
```
|
||||
Input: decision + rationale + confidence + alternatives
|
||||
│
|
||||
├─ confidence >= threshold → Auto-decide
|
||||
│ ├─ High confidence: commit with type `decision`
|
||||
│ └─ Medium confidence: commit with type `decision`, log assumptions
|
||||
│
|
||||
└─ confidence < threshold → Escalate
|
||||
└─ Generate escalation commit, pause for human input
|
||||
```
|
||||
|
||||
## DecisionRecord in Commits
|
||||
|
||||
Every decision is recorded in a `---ci---` block:
|
||||
|
||||
```yaml
|
||||
decisions:
|
||||
- id: D-001
|
||||
decision: "Use YAML blocks in commit messages for project state"
|
||||
rationale: "Git log is queryable, diffable, and survives repo transfers"
|
||||
confidence: 0.92
|
||||
alternatives: [JSON sidecar files, .ci/audit/ directory, database]
|
||||
```
|
||||
|
||||
## DecisionEngine API
|
||||
|
||||
| Method | Returns | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `makeDecision(input)` | DecisionResult | Full decision flow with confidence check |
|
||||
| `makeHighConfidenceDecision(...)` | DecisionResult | Shortcut for confidence = 0.95 |
|
||||
| `makeMediumConfidenceDecision(...)` | DecisionResult | Shortcut for confidence = 0.70 |
|
||||
| `shouldAutoDecide(confidence)` | boolean | Check threshold without making decision |
|
||||
| `isIrreversibleAction(action)` | boolean | Check against escalation hooks |
|
||||
| `commitDecision(commitMessage)` | boolean | Execute git commit |
|
||||
| `setPhase(phase)` | void | Update current phase |
|
||||
| `setMilestone(milestone)` | void | Update current milestone |
|
||||
|
||||
## DecisionResult
|
||||
|
||||
```typescript
|
||||
interface DecisionResult {
|
||||
decision: Decision;
|
||||
escalated: boolean;
|
||||
reason?: string; // set when escalated
|
||||
commitMessage?: string; // set when git.auto_commit is true
|
||||
}
|
||||
```
|
||||
|
||||
## Decision Categories
|
||||
|
||||
| Category | When Used |
|
||||
|----------|-----------|
|
||||
| `architecture` | System structure, component boundaries |
|
||||
| `technology` | Library, framework, tool choices |
|
||||
| `implementation` | Algorithm, data structure, approach |
|
||||
| `prioritization` | Feature ordering, scope decisions |
|
||||
| `security` | Threat disposition, auth approach |
|
||||
| `testing` | Test strategy, coverage targets |
|
||||
| `performance` | Optimization decisions, caching strategy |
|
||||
|
||||
## Irreversible Actions
|
||||
|
||||
The `isIrreversibleAction()` method checks against `config.autonomy.escalation_hooks`. Default hooks include patterns like `delete`, `drop`, `force`, `reset --hard`, and any custom patterns.
|
||||
|
||||
Even with high confidence, irreversible actions are flagged for additional scrutiny.
|
||||
|
||||
## Decision Retrieval
|
||||
|
||||
Decisions are retrieved from the git log, not from files:
|
||||
|
||||
```typescript
|
||||
const gitContext = new GitContext(projectPath);
|
||||
const allDecisions = gitContext.getDecisions(); // All phases
|
||||
const phaseDecisions = gitContext.getDecisions(3); // Phase 3 only
|
||||
const commitDecisions = gitContext.getDecisionsFromCommits(commits, 3);
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Never write decisions to a `.ci/audit/` file — commit them
|
||||
- Never skip recording a decision, even high-confidence ones
|
||||
- Never make a decision without listing alternatives
|
||||
- Never override the confidence threshold without explicit configuration
|
||||
- Never store the decision counter in a file — it's ephemeral per session
|
||||
|
||||
</decision_engine>
|
||||
@@ -0,0 +1,97 @@
|
||||
<git_context_loading>
|
||||
|
||||
How CI agents load project context. The git log IS the project memory — a CI agent's first impulse to gather context is `git log` + `git branch`, not file reads.
|
||||
|
||||
---
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Read the log first, files second.**
|
||||
|
||||
The git log contains every decision, escalation, lesson, and compound learning through structured `---ci---` YAML blocks. Files in `.ci/` are long-lived reference documents (PROJECT.md, ARCHITECTURE.md, ROADMAP.md, REQUIREMENTS.md, config.json) that change infrequently.
|
||||
|
||||
## Context Loading Sequence
|
||||
|
||||
1. **Branch scan** — `GitContext.getBranches()` to discover phase and milestone structure
|
||||
2. **State reconstruction** — `GitContext.reconstructState()` to get current phase, milestone, stage
|
||||
3. **Decision scan** — `GitContext.getDecisions()` for all project decisions
|
||||
4. **Escalation check** — `GitContext.getEscalations()` for any pending escalations
|
||||
5. **Requirements coverage** — `GitContext.getRequirementsCoverage()` for covered/partial
|
||||
6. **Lessons scan** — `GitContext.getLessons()` for all learned lessons
|
||||
7. **Compound learnings** — `GitContext.getCompounds()` for cross-phase patterns
|
||||
8. **File reads** — Only now read `.ci/` files (PROJECT.md, ARCHITECTURE.md, etc.)
|
||||
|
||||
## GitContext API
|
||||
|
||||
| Method | Returns | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `isGitRepo()` | boolean | Check if inside a git repo |
|
||||
| `getCurrentBranch()` | string | Current branch name |
|
||||
| `getRecentCommits(count)` | ParsedCiCommit[] | Recent commits with parsed `---ci---` blocks |
|
||||
| `getLatestCiCommit()` | ParsedCiCommit \| null | Most recent CI commit |
|
||||
| `getBranches()` | BranchInfo[] | All branches with type and merge status |
|
||||
| `getPhaseBranches()` | BranchInfo[] | Phase branches only |
|
||||
| `getMilestoneBranches()` | BranchInfo[] | Milestone branches only |
|
||||
| `reconstructState()` | ProjectState | Full project state from git log |
|
||||
| `getDecisions(phase?)` | CommitDecision[] | Decisions, optionally filtered by phase |
|
||||
| `getLessons(phase?)` | string[] | Learned lessons |
|
||||
| `getCompounds(category?)` | CompoundInfo[] | Compound learnings |
|
||||
| `getEscalations()` | EscalationInfo[] | All escalations |
|
||||
| `getRequirementsCoverage()` | { covered, partial } | Requirement traceability |
|
||||
| `getCommitsForPhase(phase)` | ParsedCiCommit[] | All commits for a phase |
|
||||
| `getCommitsForBranch(branch)` | ParsedCiCommit[] | All commits on a branch |
|
||||
|
||||
## ProjectState
|
||||
|
||||
The `reconstructState()` method returns:
|
||||
|
||||
```typescript
|
||||
interface ProjectState {
|
||||
currentPhase: number;
|
||||
currentMilestone: string;
|
||||
currentStage: PipelineStage;
|
||||
phasesCompleted: number[];
|
||||
phaseBranches: BranchInfo[];
|
||||
milestoneBranches: string[];
|
||||
lastCommit: ParsedCiCommit | null;
|
||||
}
|
||||
```
|
||||
|
||||
Derived entirely from git data — no file reads required.
|
||||
|
||||
## ParsedCiCommit
|
||||
|
||||
Every commit returned by `getRecentCommits()` is parsed into:
|
||||
|
||||
```typescript
|
||||
interface ParsedCiCommit {
|
||||
hash: string;
|
||||
type: CommitType;
|
||||
scope: string;
|
||||
subject: string;
|
||||
ci: CiMetadata | null; // null if no ---ci--- block
|
||||
body: string;
|
||||
}
|
||||
```
|
||||
|
||||
Commits without `---ci---` blocks have `ci: null` — these are treated as non-CI commits (e.g., manual edits by the developer).
|
||||
|
||||
## Context Budget Strategy
|
||||
|
||||
When context is limited:
|
||||
|
||||
1. `reconstructState()` — always (cheap, single call)
|
||||
2. `getDecisions(currentPhase)` — current phase decisions only
|
||||
3. `getRequirementsCoverage()` — aggregate view
|
||||
4. Skip lessons/compounds unless specifically needed
|
||||
5. Read `.ci/ROADMAP.md` instead of scanning all phase branches
|
||||
|
||||
## What NOT to Do
|
||||
|
||||
- Never read `.ci/` files before checking the git log
|
||||
- Never parse commit messages manually — use `CommitParser.parseCommitMessage()`
|
||||
- Never assume the latest commit reflects the current state — check branches
|
||||
- Never reconstruct state from files when git data is available
|
||||
- Never skip the branch scan — merged branches indicate completed phases
|
||||
|
||||
</git_context_loading>
|
||||
Reference in New Issue
Block a user