opencode-hive 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -2
- package/dist/hive-core/src/services/index.d.ts +1 -0
- package/dist/hive-core/src/services/sessionService.d.ts +8 -1
- package/dist/hive-core/src/services/taskService.d.ts +9 -3
- package/dist/hive-core/src/types.d.ts +20 -0
- package/dist/hive-core/src/utils/paths.d.ts +1 -0
- package/dist/index.js +945 -308
- package/dist/opencode-hive/src/agents/hive.d.ts +1 -1
- package/dist/opencode-hive/src/agents/swarm.d.ts +1 -1
- package/dist/opencode-hive/src/hooks/variant-hook.d.ts +14 -2
- package/dist/opencode-hive/src/utils/compaction-anchor.d.ts +14 -0
- package/package.json +4 -4
- package/skills/executing-plans/SKILL.md +14 -4
package/README.md
CHANGED
|
@@ -66,8 +66,8 @@ During planning, "don't execute" means "don't implement" (no code edits, no work
|
|
|
66
66
|
### Tasks
|
|
67
67
|
| Tool | Description |
|
|
68
68
|
|------|-------------|
|
|
69
|
-
| `hive_tasks_sync` | Generate tasks from plan |
|
|
70
|
-
| `hive_task_create` | Create manual task |
|
|
69
|
+
| `hive_tasks_sync` | Generate tasks from plan, or rewrite pending plan tasks with `refreshPending: true` after a plan amendment |
|
|
70
|
+
| `hive_task_create` | Create a manual task with explicit `dependsOn` and optional structured metadata |
|
|
71
71
|
| `hive_task_update` | Update task status/summary |
|
|
72
72
|
|
|
73
73
|
### Worktree
|
|
@@ -108,6 +108,43 @@ When using Dynamic Context Pruning (DCP), use a Hive-safe config in `~/.config/o
|
|
|
108
108
|
|
|
109
109
|
For local plugin testing, keep OpenCode plugin entry as `"opencode-hive"` (not `"opencode-hive@latest"`).
|
|
110
110
|
|
|
111
|
+
#### Compaction recovery and session re-anchoring
|
|
112
|
+
|
|
113
|
+
OpenCode can compact long sessions. When that happens mid-orchestration or mid-task, Hive needs the session to recover its role and task boundaries without re-reading the whole repository.
|
|
114
|
+
|
|
115
|
+
The plugin now persists durable session metadata and uses it during `experimental.session.compacting` to rebuild a compact re-anchor prompt.
|
|
116
|
+
|
|
117
|
+
Where:
|
|
118
|
+
|
|
119
|
+
- Global session state is written to `.hive/sessions.json`.
|
|
120
|
+
- Feature-local mirrors are written to `.hive/features/<feature>/sessions.json`.
|
|
121
|
+
- Session classification distinguishes `primary`, `subagent`, `task-worker`, and `unknown`.
|
|
122
|
+
- Primary and subagent recovery can replay the stored user directive once after compaction.
|
|
123
|
+
- Task-worker recovery uses the strict re-anchor plus one bounded worker-specific synthetic replay after compaction.
|
|
124
|
+
- The task-worker replay can reference `.hive/features/<feature>/tasks/<task>/worker-prompt.md`.
|
|
125
|
+
|
|
126
|
+
Task-worker recovery is intentionally strict:
|
|
127
|
+
|
|
128
|
+
- keep the same role
|
|
129
|
+
- do not delegate
|
|
130
|
+
- do not re-read the full codebase
|
|
131
|
+
- re-read `worker-prompt.md`
|
|
132
|
+
- finish only the current task assignment
|
|
133
|
+
- do not merge
|
|
134
|
+
- do not start the next task
|
|
135
|
+
- do not use orchestration tools unless the worker prompt explicitly says so
|
|
136
|
+
- continue from the last known point
|
|
137
|
+
|
|
138
|
+
This split is deliberate: primary and subagent sessions replay the stored user directive once after compaction, while task-workers also receive one worker-specific synthetic replay after compaction that restates the active task identity and worker boundaries.
|
|
139
|
+
|
|
140
|
+
Manual tasks follow the same DAG model as plan-backed tasks:
|
|
141
|
+
|
|
142
|
+
- `hive_task_create()` stores manual tasks with explicit `dependsOn` metadata instead of inferring sequential order.
|
|
143
|
+
- Structured manual-task fields such as `goal`, `description`, `acceptanceCriteria`, `files`, and `references` are turned into worker-facing `spec.md` content.
|
|
144
|
+
- If review feedback changes downstream sequencing or scope, update `plan.md` and run `hive_tasks_sync({ refreshPending: true })` so pending plan tasks pick up the new `dependsOn` graph and regenerated specs.
|
|
145
|
+
|
|
146
|
+
This recovery path applies to the built-in `forager-worker` and custom agents derived from it, because they are the sessions most likely to be compacted mid-implementation.
|
|
147
|
+
|
|
111
148
|
## Prompt Budgeting & Observability
|
|
112
149
|
|
|
113
150
|
Hive automatically bounds worker prompt sizes to prevent context overflow and tool output truncation.
|
|
@@ -136,6 +173,8 @@ When limits are exceeded, content is truncated with `...[truncated]` markers and
|
|
|
136
173
|
|
|
137
174
|
Large prompts are written to `.hive/features/<feature>/tasks/<task>/worker-prompt.md` and passed by file reference (`workerPromptPath`) rather than inlined in tool output. This prevents truncation of large prompts.
|
|
138
175
|
|
|
176
|
+
That same `worker-prompt.md` path is also reused during compaction recovery so task workers can re-anchor to the exact task assignment after a compacted session resumes.
|
|
177
|
+
|
|
139
178
|
## Plan Format
|
|
140
179
|
|
|
141
180
|
```markdown
|
|
@@ -359,6 +398,13 @@ ID guardrails:
|
|
|
359
398
|
- plugin-reserved aliases are blocked (`hive`, `architect`, `swarm`, `scout`, `forager`, `hygienic`, `receiver`)
|
|
360
399
|
- operational IDs are blocked (`build`, `plan`, `code`)
|
|
361
400
|
|
|
401
|
+
Compaction classification follows the base agent:
|
|
402
|
+
|
|
403
|
+
- `forager-worker` derivatives are treated as `task-worker`
|
|
404
|
+
- `hygienic-reviewer` derivatives are treated as `subagent`
|
|
405
|
+
|
|
406
|
+
This ensures custom workers recover with the same execution constraints as their base role.
|
|
407
|
+
|
|
362
408
|
### Custom Models
|
|
363
409
|
|
|
364
410
|
Override models for specific agents:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { FeatureService } from './featureService.js';
|
|
2
2
|
export { PlanService } from './planService.js';
|
|
3
3
|
export { TaskService } from './taskService.js';
|
|
4
|
+
export type { SyncOptions } from './taskService.js';
|
|
4
5
|
export { SubtaskService } from './subtaskService.js';
|
|
5
6
|
export { WorktreeService, createWorktreeService } from './worktreeService.js';
|
|
6
7
|
export type { WorktreeInfo, DiffResult, ApplyResult, CommitResult, MergeResult, WorktreeConfig } from './worktreeService.js';
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { SessionInfo } from '../types.js';
|
|
1
|
+
import type { SessionInfo } from '../types.js';
|
|
2
2
|
export declare class SessionService {
|
|
3
3
|
private projectRoot;
|
|
4
4
|
constructor(projectRoot: string);
|
|
5
|
+
private applySessionPatch;
|
|
5
6
|
private getSessionsPath;
|
|
6
7
|
private getSessions;
|
|
7
8
|
private saveSessions;
|
|
9
|
+
private getGlobalSessions;
|
|
10
|
+
private saveGlobalSessions;
|
|
11
|
+
private updateGlobalSessions;
|
|
12
|
+
trackGlobal(sessionId: string, patch?: Partial<SessionInfo>): SessionInfo;
|
|
13
|
+
bindFeature(sessionId: string, featureName: string, patch?: Partial<SessionInfo>): SessionInfo;
|
|
14
|
+
getGlobal(sessionId: string): SessionInfo | undefined;
|
|
8
15
|
track(featureName: string, sessionId: string, taskFolder?: string): SessionInfo;
|
|
9
16
|
setMaster(featureName: string, sessionId: string): void;
|
|
10
17
|
getMaster(featureName: string): string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LockOptions } from '../utils/paths.js';
|
|
2
|
-
import { TaskStatus, TaskStatusType, TasksSyncResult, TaskInfo, Subtask, SubtaskType, WorkerSession } from '../types.js';
|
|
2
|
+
import { TaskStatus, TaskStatusType, TasksSyncResult, TaskInfo, Subtask, SubtaskType, WorkerSession, ManualTaskMetadata } from '../types.js';
|
|
3
3
|
/** Current schema version for TaskStatus */
|
|
4
4
|
export declare const TASK_STATUS_SCHEMA_VERSION = 1;
|
|
5
5
|
/** Fields that can be updated by background workers without clobbering completion-owned fields */
|
|
@@ -13,17 +13,21 @@ export interface CompletionFields {
|
|
|
13
13
|
summary?: string;
|
|
14
14
|
completedAt?: string;
|
|
15
15
|
}
|
|
16
|
+
export interface SyncOptions {
|
|
17
|
+
refreshPending?: boolean;
|
|
18
|
+
}
|
|
16
19
|
export declare class TaskService {
|
|
17
20
|
private projectRoot;
|
|
18
21
|
constructor(projectRoot: string);
|
|
19
|
-
sync(featureName: string): TasksSyncResult;
|
|
22
|
+
sync(featureName: string, options?: SyncOptions): TasksSyncResult;
|
|
20
23
|
/**
|
|
21
24
|
* Create a manual task with auto-incrementing index.
|
|
22
25
|
* Folder format: "01-task-name", "02-task-name", etc.
|
|
23
26
|
* Index ensures alphabetical sort = chronological order.
|
|
24
27
|
*/
|
|
25
|
-
create(featureName: string, name: string, order?: number): string;
|
|
28
|
+
create(featureName: string, name: string, order?: number, metadata?: ManualTaskMetadata): string;
|
|
26
29
|
private createFromPlan;
|
|
30
|
+
private refreshPendingTask;
|
|
27
31
|
buildSpecContent(params: {
|
|
28
32
|
featureName: string;
|
|
29
33
|
task: {
|
|
@@ -72,6 +76,7 @@ export declare class TaskService {
|
|
|
72
76
|
*/
|
|
73
77
|
private detectCycles;
|
|
74
78
|
writeSpec(featureName: string, taskFolder: string, content: string): string;
|
|
79
|
+
readSpec(featureName: string, taskFolder: string): string | null;
|
|
75
80
|
/**
|
|
76
81
|
* Update task status with locked atomic write.
|
|
77
82
|
* Uses file locking to prevent race conditions between concurrent updates.
|
|
@@ -120,5 +125,6 @@ export declare class TaskService {
|
|
|
120
125
|
readSubtaskReport(featureName: string, taskFolder: string, subtaskId: string): string | null;
|
|
121
126
|
private listSubtaskFolders;
|
|
122
127
|
private findSubtaskFolder;
|
|
128
|
+
private buildManualTaskSpec;
|
|
123
129
|
private slugify;
|
|
124
130
|
}
|
|
@@ -50,6 +50,16 @@ export interface WorkerSession {
|
|
|
50
50
|
/** Number of messages exchanged in session */
|
|
51
51
|
messageCount?: number;
|
|
52
52
|
}
|
|
53
|
+
export interface ManualTaskMetadata {
|
|
54
|
+
goal?: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
acceptanceCriteria?: string[];
|
|
57
|
+
references?: string[];
|
|
58
|
+
files?: string[];
|
|
59
|
+
reason?: string;
|
|
60
|
+
source?: 'review' | 'operator' | 'ad_hoc';
|
|
61
|
+
dependsOn?: string[];
|
|
62
|
+
}
|
|
53
63
|
export interface TaskStatus {
|
|
54
64
|
/** Schema version for forward compatibility (default: 1) */
|
|
55
65
|
schemaVersion?: number;
|
|
@@ -71,6 +81,8 @@ export interface TaskStatus {
|
|
|
71
81
|
* Resolved from plan.md dependency annotations during hive_tasks_sync.
|
|
72
82
|
*/
|
|
73
83
|
dependsOn?: string[];
|
|
84
|
+
/** Structured metadata for manual tasks */
|
|
85
|
+
metadata?: ManualTaskMetadata;
|
|
74
86
|
}
|
|
75
87
|
export type ReviewDocument = 'plan' | 'overview';
|
|
76
88
|
export interface ReviewThread {
|
|
@@ -120,9 +132,17 @@ export interface ContextFile {
|
|
|
120
132
|
content: string;
|
|
121
133
|
updatedAt: string;
|
|
122
134
|
}
|
|
135
|
+
export type SessionKind = 'primary' | 'subagent' | 'task-worker' | 'unknown';
|
|
123
136
|
export interface SessionInfo {
|
|
124
137
|
sessionId: string;
|
|
138
|
+
featureName?: string;
|
|
125
139
|
taskFolder?: string;
|
|
140
|
+
agent?: string;
|
|
141
|
+
baseAgent?: string;
|
|
142
|
+
sessionKind?: SessionKind;
|
|
143
|
+
workerPromptPath?: string;
|
|
144
|
+
directivePrompt?: string;
|
|
145
|
+
replayDirectivePending?: boolean;
|
|
126
146
|
startedAt: string;
|
|
127
147
|
lastActiveAt: string;
|
|
128
148
|
messageCount?: number;
|
|
@@ -3,6 +3,7 @@ export declare function normalizePath(filePath: string): string;
|
|
|
3
3
|
export declare function getHivePath(projectRoot: string): string;
|
|
4
4
|
export declare function getFeaturesPath(projectRoot: string): string;
|
|
5
5
|
export declare function getActiveFeaturePath(projectRoot: string): string;
|
|
6
|
+
export declare function getGlobalSessionsPath(projectRoot: string): string;
|
|
6
7
|
export declare function listFeatureDirectories(projectRoot: string): FeatureDirectoryInfo[];
|
|
7
8
|
export declare function resolveFeatureDirectoryName(projectRoot: string, featureName: string): string;
|
|
8
9
|
export declare function getNextIndexedFeatureDirectoryName(projectRoot: string, featureName: string): string;
|