fix: correct task-delegation reference in session-context-pattern (#218)

* fix: correct task-delegation reference in session-context-pattern

- Changed outdated reference from task-delegation.md to task-delegation-basics.md
- The file task-delegation-basics.md exists, task-delegation.md does not
- This caused 'file not found' errors during installation via install.sh

* feat: add install-fork.sh for fork-based installation

- Creates install-fork.sh that installs from digi4care/OpenAgentsControl fork
- Allows users to install the forked version with fixes before upstream merge
- Usage: bash install-fork.sh or curl directly from fork repo

* docs: add root README.md and CONTRIBUTING.md for GitHub best practices

- Add README.md in repository root (GitHub requirement)
- Add CONTRIBUTING.md in repository root with contribution guidelines
- Both files redirect to detailed documentation in docs/ directory
- Fixes installer 404 error for readme config item
- Follows GitHub community standards for repository structure

* chore: remove fork-specific files per maintainer request

---------

Co-authored-by: Chris Engelhard <chris@chrisengelhard.nl>
This commit is contained in:
Chris Engelhard 2026-03-11 19:58:08 +01:00 committed by GitHub
parent 25db9470cc
commit b157241325
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,4 +1,5 @@
<!-- Context: workflows/session-context | Priority: critical | Version: 1.0 | Updated: 2026-02-15 --> <!-- Context: workflows/session-context | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
# Session Context Pattern # Session Context Pattern
## Problem ## Problem
@ -13,6 +14,7 @@ When orchestrating complex features across multiple agents (TaskManager → Code
- **Orchestrator** has to manually pass context in every delegation - **Orchestrator** has to manually pass context in every delegation
This leads to: This leads to:
- ❌ Repeated context discovery (inefficient) - ❌ Repeated context discovery (inefficient)
- ❌ Inconsistent decisions (agents don't see previous choices) - ❌ Inconsistent decisions (agents don't see previous choices)
- ❌ Lost architectural context (bounded contexts, contracts, ADRs) - ❌ Lost architectural context (bounded contexts, contracts, ADRs)
@ -54,57 +56,71 @@ Created: {timestamp}
Status: in_progress | completed | blocked Status: in_progress | completed | blocked
## Current Request ## Current Request
{Original user request - what we're building} {Original user request - what we're building}
## Context Files to Load ## Context Files to Load
- {Standards paths - coding conventions, patterns, security rules} - {Standards paths - coding conventions, patterns, security rules}
## Reference Files ## Reference Files
- {Source material - existing project files to look at} - {Source material - existing project files to look at}
## Architecture ## Architecture
- Bounded Context: {DDD context from ArchitectureAnalyzer} - Bounded Context: {DDD context from ArchitectureAnalyzer}
- Module: {Package/module name} - Module: {Package/module name}
- Vertical Slice: {Feature slice from StoryMapper} - Vertical Slice: {Feature slice from StoryMapper}
## User Stories ## User Stories
- {Story 1 from StoryMapper} - {Story 1 from StoryMapper}
- {Story 2} - {Story 2}
## Priorities ## Priorities
- RICE Score: {score from PrioritizationEngine} - RICE Score: {score from PrioritizationEngine}
- WSJF Score: {score} - WSJF Score: {score}
- Release Slice: {v1.0.0, Q1-2026, MVP} - Release Slice: {v1.0.0, Q1-2026, MVP}
## Contracts ## Contracts
- {type}: {name} ({status}) - {type}: {name} ({status})
Path: {contract file path} Path: {contract file path}
## Architectural Decision Records ## Architectural Decision Records
- {ADR-ID}: {title} - {ADR-ID}: {title}
Path: {adr file path} Path: {adr file path}
## Progress ## Progress
Current Stage: {Stage N: Name} Current Stage: {Stage N: Name}
Completed Stages: Completed Stages:
- {Stage 0: Context Loading} - {Stage 0: Context Loading}
- {Stage 1: Planning} - {Stage 1: Planning}
Stage Outputs: Stage Outputs:
- {Stage 0}: - {Stage 0}:
- {Output 1} - {Output 1}
- {Output 2} - {Output 2}
## Key Decisions ## Key Decisions
- [{timestamp}] {decision} - [{timestamp}] {decision}
Rationale: {why this choice was made} Rationale: {why this choice was made}
## Files Created ## Files Created
- {file path 1} - {file path 1}
- {file path 2} - {file path 2}
## Exit Criteria ## Exit Criteria
- [ ] {criterion 1} - [ ] {criterion 1}
- [ ] {criterion 2} - [ ] {criterion 2}
- [x] {completed criterion} - [x] {completed criterion}
@ -132,16 +148,16 @@ Stage Outputs:
**Stage 0: Initialize Session** **Stage 0: Initialize Session**
```typescript ```typescript
import { createSession } from '.opencode/skill/task-management/scripts/session-context-manager'; import { createSession } from ".opencode/skill/task-management/scripts/session-context-manager";
const result = createSession(feature, request, { const result = createSession(feature, request, {
contextFiles: [], // Will be populated by ContextScout contextFiles: [], // Will be populated by ContextScout
referenceFiles: [], referenceFiles: [],
exitCriteria: [ exitCriteria: [
'All subtasks completed', "All subtasks completed",
'Tests passing', "Tests passing",
'Documentation updated' "Documentation updated",
] ],
}); });
const sessionId = result.sessionId; const sessionId = result.sessionId;
@ -151,35 +167,35 @@ const sessionId = result.sessionId;
**Between Stages: Update Context** **Between Stages: Update Context**
```typescript ```typescript
import { updateSession, markStageComplete } from './session-context-manager'; import { updateSession, markStageComplete } from "./session-context-manager";
// After ContextScout completes // After ContextScout completes
updateSession(sessionId, { updateSession(sessionId, {
contextFiles: [ contextFiles: [
'.opencode/context/core/standards/code-quality.md', ".opencode/context/core/standards/code-quality.md",
'.opencode/context/core/standards/security-patterns.md' ".opencode/context/core/standards/security-patterns.md",
] ],
}); });
// After ArchitectureAnalyzer completes // After ArchitectureAnalyzer completes
updateSession(sessionId, { updateSession(sessionId, {
architecture: { architecture: {
boundedContext: 'authentication', boundedContext: "authentication",
module: '@app/auth' module: "@app/auth",
} },
}); });
// Mark stage complete // Mark stage complete
markStageComplete(sessionId, 'Stage 1: Planning', [ markStageComplete(sessionId, "Stage 1: Planning", [
'.tmp/tasks/auth-system/task.json', ".tmp/tasks/auth-system/task.json",
'.tmp/tasks/auth-system/subtask_01.json' ".tmp/tasks/auth-system/subtask_01.json",
]); ]);
``` ```
**Final Stage: Complete Session** **Final Stage: Complete Session**
```typescript ```typescript
updateSession(sessionId, { status: 'completed' }); updateSession(sessionId, { status: "completed" });
``` ```
### TaskManager ### TaskManager
@ -187,7 +203,7 @@ updateSession(sessionId, { status: 'completed' });
**Stage 0: Load Session Context** **Stage 0: Load Session Context**
```typescript ```typescript
import { loadSession } from '.opencode/skill/task-management/scripts/session-context-manager'; import { loadSession } from ".opencode/skill/task-management/scripts/session-context-manager";
const result = loadSession(sessionId); const result = loadSession(sessionId);
if (!result.success) { if (!result.success) {
@ -222,11 +238,11 @@ const adrs = session.adrs; // Architectural decisions
**Stage 3: Update Progress** **Stage 3: Update Progress**
```typescript ```typescript
import { addDecision } from './session-context-manager'; import { addDecision } from "./session-context-manager";
addDecision(sessionId, { addDecision(sessionId, {
decision: 'Split authentication into 3 subtasks: schema, service, middleware', decision: "Split authentication into 3 subtasks: schema, service, middleware",
rationale: 'Each subtask is atomic (1-2 hours) and has clear dependencies' rationale: "Each subtask is atomic (1-2 hours) and has clear dependencies",
}); });
``` ```
@ -235,18 +251,18 @@ addDecision(sessionId, {
**Before Coding: Load Session Context** **Before Coding: Load Session Context**
```typescript ```typescript
import { loadSession } from '.opencode/skill/task-management/scripts/session-context-manager'; import { loadSession } from ".opencode/skill/task-management/scripts/session-context-manager";
const result = loadSession(sessionId); const result = loadSession(sessionId);
const session = result.session; const session = result.session;
// Read context files (standards) // Read context files (standards)
session.contextFiles.forEach(file => { session.contextFiles.forEach((file) => {
// Load coding standards, security patterns // Load coding standards, security patterns
}); });
// Read reference files (existing code) // Read reference files (existing code)
session.referenceFiles.forEach(file => { session.referenceFiles.forEach((file) => {
// Study existing patterns // Study existing patterns
}); });
@ -259,10 +275,10 @@ const adrs = session.adrs; // Architectural decisions to follow
**After Coding: Track Files Created** **After Coding: Track Files Created**
```typescript ```typescript
import { addFile } from './session-context-manager'; import { addFile } from "./session-context-manager";
addFile(sessionId, 'src/auth/jwt.service.ts'); addFile(sessionId, "src/auth/jwt.service.ts");
addFile(sessionId, 'src/auth/jwt.service.test.ts'); addFile(sessionId, "src/auth/jwt.service.test.ts");
``` ```
### ContextScout ### ContextScout
@ -270,18 +286,18 @@ addFile(sessionId, 'src/auth/jwt.service.test.ts');
**After Discovery: Update Session** **After Discovery: Update Session**
```typescript ```typescript
import { updateSession } from './session-context-manager'; import { updateSession } from "./session-context-manager";
updateSession(sessionId, { updateSession(sessionId, {
contextFiles: [ contextFiles: [
'.opencode/context/core/standards/code-quality.md', ".opencode/context/core/standards/code-quality.md",
'.opencode/context/core/standards/security-patterns.md', ".opencode/context/core/standards/security-patterns.md",
'(example: .opencode/context/core/standards/naming-conventions.md)' "(example: .opencode/context/core/standards/naming-conventions.md)",
], ],
referenceFiles: [ referenceFiles: [
'src/middleware/auth.middleware.ts', "src/middleware/auth.middleware.ts",
'src/config/jwt.config.ts' "src/config/jwt.config.ts",
] ],
}); });
``` ```
@ -290,19 +306,20 @@ updateSession(sessionId, {
**After Analysis: Update Session** **After Analysis: Update Session**
```typescript ```typescript
import { updateSession, addDecision } from './session-context-manager'; import { updateSession, addDecision } from "./session-context-manager";
updateSession(sessionId, { updateSession(sessionId, {
architecture: { architecture: {
boundedContext: 'authentication', boundedContext: "authentication",
module: '@app/auth', module: "@app/auth",
verticalSlice: 'user-login' verticalSlice: "user-login",
} },
}); });
addDecision(sessionId, { addDecision(sessionId, {
decision: 'Place authentication in separate bounded context', decision: "Place authentication in separate bounded context",
rationale: 'Auth is a core domain with clear boundaries, used by multiple features' rationale:
"Auth is a core domain with clear boundaries, used by multiple features",
}); });
``` ```
@ -311,23 +328,23 @@ addDecision(sessionId, {
**After Contract Definition: Update Session** **After Contract Definition: Update Session**
```typescript ```typescript
import { updateSession } from './session-context-manager'; import { updateSession } from "./session-context-manager";
updateSession(sessionId, { updateSession(sessionId, {
contracts: [ contracts: [
{ {
type: 'api', type: "api",
name: 'AuthAPI', name: "AuthAPI",
path: 'src/api/auth.contract.ts', path: "src/api/auth.contract.ts",
status: 'defined' status: "defined",
}, },
{ {
type: 'interface', type: "interface",
name: 'JWTService', name: "JWTService",
path: 'src/auth/jwt.service.ts', path: "src/auth/jwt.service.ts",
status: 'draft' status: "draft",
} },
] ],
}); });
``` ```
@ -338,6 +355,7 @@ updateSession(sessionId, {
Initialize a new session with context.md file. Initialize a new session with context.md file.
**Parameters:** **Parameters:**
- `feature` (string) - Feature name (kebab-case) - `feature` (string) - Feature name (kebab-case)
- `request` (string) - Original user request - `request` (string) - Original user request
- `options` (object) - Optional configuration - `options` (object) - Optional configuration
@ -351,14 +369,16 @@ Initialize a new session with context.md file.
- `adrs` (array) - Architectural decision records - `adrs` (array) - Architectural decision records
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; sessionId?: string; error?: string } { success: boolean; sessionId?: string; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
const result = createSession('auth-system', 'Implement JWT authentication', { const result = createSession("auth-system", "Implement JWT authentication", {
exitCriteria: ['All tests passing', 'JWT tokens signed with RS256'] exitCriteria: ["All tests passing", "JWT tokens signed with RS256"],
}); });
// result.sessionId = "auth-system-2026-02-15T10-30-00-000Z" // result.sessionId = "auth-system-2026-02-15T10-30-00-000Z"
``` ```
@ -368,16 +388,19 @@ const result = createSession('auth-system', 'Implement JWT authentication', {
Read session context from context.md. Read session context from context.md.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; session?: SessionContext; error?: string } { success: boolean; session?: SessionContext; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
const result = loadSession('auth-system-2026-02-15T10-30-00-000Z'); const result = loadSession("auth-system-2026-02-15T10-30-00-000Z");
if (result.success) { if (result.success) {
const contextFiles = result.session.contextFiles; const contextFiles = result.session.contextFiles;
const architecture = result.session.architecture; const architecture = result.session.architecture;
@ -389,6 +412,7 @@ if (result.success) {
Append new information to session context. Append new information to session context.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
- `updates` (object) - Fields to update - `updates` (object) - Fields to update
- `status` - 'in_progress' | 'completed' | 'blocked' - `status` - 'in_progress' | 'completed' | 'blocked'
@ -401,20 +425,27 @@ Append new information to session context.
- `adrs` - Add ADRs - `adrs` - Add ADRs
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; error?: string } { success: boolean; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
updateSession(sessionId, { updateSession(sessionId, {
architecture: { architecture: {
boundedContext: 'authentication', boundedContext: "authentication",
module: '@app/auth' module: "@app/auth",
}, },
contracts: [ contracts: [
{ type: 'api', name: 'AuthAPI', path: 'src/api/auth.contract.ts', status: 'defined' } {
] type: "api",
name: "AuthAPI",
path: "src/api/auth.contract.ts",
status: "defined",
},
],
}); });
``` ```
@ -423,21 +454,24 @@ updateSession(sessionId, {
Mark a workflow stage as complete and record outputs. Mark a workflow stage as complete and record outputs.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
- `stage` (string) - Stage name (e.g., "Stage 1: Planning") - `stage` (string) - Stage name (e.g., "Stage 1: Planning")
- `outputs` (string[]) - Files/artifacts created in this stage - `outputs` (string[]) - Files/artifacts created in this stage
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; error?: string } { success: boolean; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
markStageComplete(sessionId, 'Stage 1: Planning', [ markStageComplete(sessionId, "Stage 1: Planning", [
'.tmp/tasks/auth-system/task.json', ".tmp/tasks/auth-system/task.json",
'.tmp/tasks/auth-system/subtask_01.json', ".tmp/tasks/auth-system/subtask_01.json",
'.tmp/tasks/auth-system/subtask_02.json' ".tmp/tasks/auth-system/subtask_02.json",
]); ]);
``` ```
@ -446,21 +480,25 @@ markStageComplete(sessionId, 'Stage 1: Planning', [
Log a key decision with rationale. Log a key decision with rationale.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
- `decision` (object) - `decision` (object)
- `decision` (string) - What was decided - `decision` (string) - What was decided
- `rationale` (string) - Why this choice was made - `rationale` (string) - Why this choice was made
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; error?: string } { success: boolean; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
addDecision(sessionId, { addDecision(sessionId, {
decision: 'Use RS256 for JWT signing instead of HS256', decision: "Use RS256 for JWT signing instead of HS256",
rationale: 'RS256 (asymmetric) is more secure for distributed systems where tokens are verified by multiple services' rationale:
"RS256 (asymmetric) is more secure for distributed systems where tokens are verified by multiple services",
}); });
``` ```
@ -469,18 +507,21 @@ addDecision(sessionId, {
Track a file created during the session. Track a file created during the session.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
- `filePath` (string) - Path to created file - `filePath` (string) - Path to created file
**Returns:** **Returns:**
```typescript ```typescript
{ success: boolean; error?: string } { success: boolean; error?: string }
``` ```
**Example:** **Example:**
```typescript ```typescript
addFile(sessionId, 'src/auth/jwt.service.ts'); addFile(sessionId, "src/auth/jwt.service.ts");
addFile(sessionId, 'src/auth/jwt.service.test.ts'); addFile(sessionId, "src/auth/jwt.service.test.ts");
``` ```
### getSessionSummary(sessionId) ### getSessionSummary(sessionId)
@ -488,9 +529,11 @@ addFile(sessionId, 'src/auth/jwt.service.test.ts');
Get current session state summary. Get current session state summary.
**Parameters:** **Parameters:**
- `sessionId` (string) - Session identifier - `sessionId` (string) - Session identifier
**Returns:** **Returns:**
```typescript ```typescript
{ {
success: boolean; success: boolean;
@ -510,11 +553,14 @@ Get current session state summary.
``` ```
**Example:** **Example:**
```typescript ```typescript
const result = getSessionSummary(sessionId); const result = getSessionSummary(sessionId);
console.log(`Progress: ${result.summary.completedStages} stages complete`); console.log(`Progress: ${result.summary.completedStages} stages complete`);
console.log(`Files: ${result.summary.filesCreated} created`); console.log(`Files: ${result.summary.filesCreated} created`);
console.log(`Exit Criteria: ${result.summary.exitCriteriaMet}/${result.summary.exitCriteriaTotal}`); console.log(
`Exit Criteria: ${result.summary.exitCriteriaMet}/${result.summary.exitCriteriaTotal}`,
);
``` ```
## CLI Usage ## CLI Usage
@ -542,70 +588,80 @@ npx ts-node session-context-manager.ts summary auth-system-2026-02-15T10-30-00-0
## Best Practices ## Best Practices
### 1. Initialize Early ### 1. Initialize Early
Create session at the start of orchestration, before any agent work begins. Create session at the start of orchestration, before any agent work begins.
### 2. Update After Each Stage ### 2. Update After Each Stage
Every agent that completes work should update the session context. Every agent that completes work should update the session context.
### 3. Read Before Acting ### 3. Read Before Acting
Every agent should load session context before starting work. Every agent should load session context before starting work.
### 4. Track Decisions ### 4. Track Decisions
Use `addDecision()` for any architectural or design choice. Use `addDecision()` for any architectural or design choice.
### 5. Track Files ### 5. Track Files
Use `addFile()` for every file created (helps with cleanup, rollback). Use `addFile()` for every file created (helps with cleanup, rollback).
### 6. Use Exit Criteria ### 6. Use Exit Criteria
Define clear, binary exit criteria at session creation. Define clear, binary exit criteria at session creation.
## Example: Full Orchestration Flow ## Example: Full Orchestration Flow
```typescript ```typescript
// Orchestrator: Initialize // Orchestrator: Initialize
const { sessionId } = createSession('auth-system', 'Implement JWT authentication', { const { sessionId } = createSession(
exitCriteria: ['All tests passing', 'JWT tokens signed with RS256'] "auth-system",
}); "Implement JWT authentication",
{
exitCriteria: ["All tests passing", "JWT tokens signed with RS256"],
},
);
// Stage 0: ContextScout discovers context // Stage 0: ContextScout discovers context
updateSession(sessionId, { updateSession(sessionId, {
contextFiles: ['.opencode/context/core/standards/code-quality.md'], contextFiles: [".opencode/context/core/standards/code-quality.md"],
referenceFiles: ['src/middleware/auth.middleware.ts'] referenceFiles: ["src/middleware/auth.middleware.ts"],
}); });
markStageComplete(sessionId, 'Stage 0: Context Loading', []); markStageComplete(sessionId, "Stage 0: Context Loading", []);
// Stage 1: ArchitectureAnalyzer analyzes // Stage 1: ArchitectureAnalyzer analyzes
updateSession(sessionId, { updateSession(sessionId, {
architecture: { boundedContext: 'authentication', module: '@app/auth' } architecture: { boundedContext: "authentication", module: "@app/auth" },
}); });
addDecision(sessionId, { addDecision(sessionId, {
decision: 'Separate bounded context for auth', decision: "Separate bounded context for auth",
rationale: 'Core domain with clear boundaries' rationale: "Core domain with clear boundaries",
}); });
markStageComplete(sessionId, 'Stage 1: Architecture Analysis', []); markStageComplete(sessionId, "Stage 1: Architecture Analysis", []);
// Stage 2: TaskManager creates tasks // Stage 2: TaskManager creates tasks
const { session } = loadSession(sessionId); const { session } = loadSession(sessionId);
// Use session.contextFiles, session.architecture in task.json // Use session.contextFiles, session.architecture in task.json
markStageComplete(sessionId, 'Stage 2: Task Planning', [ markStageComplete(sessionId, "Stage 2: Task Planning", [
'.tmp/tasks/auth-system/task.json' ".tmp/tasks/auth-system/task.json",
]); ]);
// Stage 3: CoderAgent implements // Stage 3: CoderAgent implements
const { session } = loadSession(sessionId); const { session } = loadSession(sessionId);
// Read session.contextFiles, session.contracts // Read session.contextFiles, session.contracts
addFile(sessionId, 'src/auth/jwt.service.ts'); addFile(sessionId, "src/auth/jwt.service.ts");
markStageComplete(sessionId, 'Stage 3: Implementation', [ markStageComplete(sessionId, "Stage 3: Implementation", [
'src/auth/jwt.service.ts' "src/auth/jwt.service.ts",
]); ]);
// Stage 4: Complete // Stage 4: Complete
updateSession(sessionId, { status: 'completed' }); updateSession(sessionId, { status: "completed" });
``` ```
## Related ## Related
- `.opencode/skill/task-management/scripts/session-context-manager.ts` - Implementation - `.opencode/skill/task-management/scripts/session-context-manager.ts` - Implementation
- `.opencode/context/core/task-management/standards/task-schema.md` - Task JSON schema - `.opencode/context/core/task-management/standards/task-schema.md` - Task JSON schema
- `.opencode/context/core/workflows/task-delegation.md` - Multi-agent orchestration - `.opencode/context/core/workflows/task-delegation-basics.md` - Multi-agent orchestration
- `.tmp/sessions/test-task-manager/context.md` - Example session context - `.tmp/sessions/test-task-manager/context.md` - Example session context