@lucasreiners/lead 0.1.0

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.
Files changed (98) hide show
  1. package/README.md +337 -0
  2. package/dist/agents/agent-builder.d.ts +30 -0
  3. package/dist/agents/architect/index.d.ts +4 -0
  4. package/dist/agents/builtin-agents.d.ts +32 -0
  5. package/dist/agents/code-analyst/index.d.ts +4 -0
  6. package/dist/agents/cto/index.d.ts +11 -0
  7. package/dist/agents/custom-agent-factory.d.ts +27 -0
  8. package/dist/agents/dynamic-prompt-builder.d.ts +22 -0
  9. package/dist/agents/engineer/index.d.ts +4 -0
  10. package/dist/agents/executor/index.d.ts +6 -0
  11. package/dist/agents/guardian/index.d.ts +4 -0
  12. package/dist/agents/index.d.ts +17 -0
  13. package/dist/agents/lead/index.d.ts +11 -0
  14. package/dist/agents/lead-dev/index.d.ts +6 -0
  15. package/dist/agents/model-resolution.d.ts +44 -0
  16. package/dist/agents/prompt-loader.d.ts +30 -0
  17. package/dist/agents/prompt-utils.d.ts +12 -0
  18. package/dist/agents/researcher/index.d.ts +4 -0
  19. package/dist/agents/reviewer/index.d.ts +4 -0
  20. package/dist/agents/scout/index.d.ts +4 -0
  21. package/dist/agents/tech-lead/index.d.ts +11 -0
  22. package/dist/agents/tester/index.d.ts +4 -0
  23. package/dist/agents/types.d.ts +37 -0
  24. package/dist/config/continuation.d.ts +13 -0
  25. package/dist/config/index.d.ts +6 -0
  26. package/dist/config/loader.d.ts +12 -0
  27. package/dist/config/merge.d.ts +8 -0
  28. package/dist/config/scaffold.d.ts +12 -0
  29. package/dist/config/schema.d.ts +140 -0
  30. package/dist/create-managers.d.ts +32 -0
  31. package/dist/create-tools.d.ts +24 -0
  32. package/dist/domain/plans/index.d.ts +2 -0
  33. package/dist/domain/policy/policy-result.d.ts +23 -0
  34. package/dist/domain/session/index.d.ts +41 -0
  35. package/dist/domain/workflows/index.d.ts +4 -0
  36. package/dist/domain/workflows/workflow-completion.d.ts +9 -0
  37. package/dist/domain/workflows/workflow-context.d.ts +9 -0
  38. package/dist/domain/workflows/workflow-repository.d.ts +19 -0
  39. package/dist/domain/workflows/workflow-service.d.ts +32 -0
  40. package/dist/features/skill-loader/discovery.d.ts +36 -0
  41. package/dist/features/skill-loader/index.d.ts +6 -0
  42. package/dist/features/skill-loader/loader.d.ts +15 -0
  43. package/dist/features/skill-loader/opencode-client.d.ts +6 -0
  44. package/dist/features/skill-loader/resolver.d.ts +8 -0
  45. package/dist/features/skill-loader/types.d.ts +14 -0
  46. package/dist/features/work-state/constants.d.ts +4 -0
  47. package/dist/features/work-state/index.d.ts +5 -0
  48. package/dist/features/work-state/storage.d.ts +20 -0
  49. package/dist/features/work-state/types.d.ts +16 -0
  50. package/dist/features/work-state/validation-types.d.ts +8 -0
  51. package/dist/features/work-state/validation.d.ts +6 -0
  52. package/dist/features/workflow/commands.d.ts +10 -0
  53. package/dist/features/workflow/completion.d.ts +5 -0
  54. package/dist/features/workflow/constants.d.ts +8 -0
  55. package/dist/features/workflow/context.d.ts +16 -0
  56. package/dist/features/workflow/discovery.d.ts +19 -0
  57. package/dist/features/workflow/engine.d.ts +19 -0
  58. package/dist/features/workflow/hook.d.ts +45 -0
  59. package/dist/features/workflow/index.d.ts +9 -0
  60. package/dist/features/workflow/schema.d.ts +43 -0
  61. package/dist/features/workflow/storage.d.ts +7 -0
  62. package/dist/features/workflow/types.d.ts +89 -0
  63. package/dist/hooks/architect-md-only.d.ts +11 -0
  64. package/dist/hooks/compaction-recovery.d.ts +20 -0
  65. package/dist/hooks/compaction-todo-preserver.d.ts +21 -0
  66. package/dist/hooks/context-window-monitor.d.ts +26 -0
  67. package/dist/hooks/create-hooks.d.ts +45 -0
  68. package/dist/hooks/first-message-variant.d.ts +23 -0
  69. package/dist/hooks/index.d.ts +28 -0
  70. package/dist/hooks/keyword-detector.d.ts +17 -0
  71. package/dist/hooks/rules-injector.d.ts +16 -0
  72. package/dist/hooks/session-token-state.d.ts +31 -0
  73. package/dist/hooks/start-implementation-hook.d.ts +26 -0
  74. package/dist/hooks/start-work-hook.d.ts +26 -0
  75. package/dist/hooks/todo-continuation-enforcer.d.ts +22 -0
  76. package/dist/hooks/todo-description-override.d.ts +10 -0
  77. package/dist/hooks/todo-writer.d.ts +20 -0
  78. package/dist/hooks/verification-reminder.d.ts +21 -0
  79. package/dist/hooks/work-continuation.d.ts +23 -0
  80. package/dist/hooks/write-existing-file-guard.d.ts +34 -0
  81. package/dist/index.d.ts +17 -0
  82. package/dist/index.js +3811 -0
  83. package/dist/infrastructure/fs/config-fs-loader.d.ts +6 -0
  84. package/dist/managers/background-manager.d.ts +48 -0
  85. package/dist/managers/config-handler.d.ts +31 -0
  86. package/dist/managers/index.d.ts +6 -0
  87. package/dist/managers/skill-mcp-manager.d.ts +31 -0
  88. package/dist/plugin/index.d.ts +2 -0
  89. package/dist/plugin/plugin-interface.d.ts +7 -0
  90. package/dist/plugin/types.d.ts +18 -0
  91. package/dist/runtime/opencode/plugin-adapter.d.ts +17 -0
  92. package/dist/shared/agent-display-names.d.ts +3 -0
  93. package/dist/shared/index.d.ts +6 -0
  94. package/dist/shared/log.d.ts +9 -0
  95. package/dist/shared/resolve-safe-path.d.ts +7 -0
  96. package/dist/shared/types.d.ts +3 -0
  97. package/dist/shared/version.d.ts +1 -0
  98. package/package.json +39 -0
@@ -0,0 +1,4 @@
1
+ import type { AgentConfig } from "@opencode-ai/sdk";
2
+ import type { AgentFactory } from "../types";
3
+ export declare const TESTER_DEFAULTS: AgentConfig;
4
+ export declare const createTesterAgent: AgentFactory;
@@ -0,0 +1,37 @@
1
+ import type { AgentConfig } from "@opencode-ai/sdk";
2
+ export type LeadAgentName = "tech-lead" | "lead-dev" | "engineer" | "architect" | "code-analyst" | "researcher" | "reviewer" | "tester" | "guardian";
3
+ /**
4
+ * primary — user-facing agent, uses UI-selected model
5
+ * subagent — spawned by other agents, uses its own fallback model
6
+ * all — available in both contexts
7
+ */
8
+ export type AgentMode = "primary" | "subagent" | "all";
9
+ export type AgentFactory = ((model: string) => AgentConfig) & {
10
+ mode: AgentMode;
11
+ };
12
+ export type AgentSource = AgentFactory | AgentConfig;
13
+ export interface DelegationTrigger {
14
+ domain: string;
15
+ trigger: string;
16
+ }
17
+ export interface AgentCost {
18
+ tier: "cheap" | "moderate" | "expensive";
19
+ label: string;
20
+ }
21
+ export interface AgentPromptMetadata {
22
+ name: LeadAgentName | string;
23
+ displayName: string;
24
+ description: string;
25
+ mode: AgentMode;
26
+ triggers?: DelegationTrigger[];
27
+ cost?: AgentCost;
28
+ skills?: string[];
29
+ category?: string;
30
+ }
31
+ export declare function isFactory(source: AgentSource): source is AgentFactory;
32
+ /**
33
+ * Returns true if the model string looks like a GPT-series model.
34
+ * Used for temperature adjustment (GPT models have different defaults).
35
+ */
36
+ export declare function isGptModel(model: string): boolean;
37
+ export type { AgentConfig };
@@ -0,0 +1,13 @@
1
+ import type { ContinuationConfig } from "./schema";
2
+ export interface ResolvedContinuationConfig {
3
+ recovery: {
4
+ compaction: boolean;
5
+ };
6
+ idle: {
7
+ enabled: boolean;
8
+ work: boolean;
9
+ workflow: boolean;
10
+ todo_prompt: boolean;
11
+ };
12
+ }
13
+ export declare function resolveContinuationConfig(raw?: ContinuationConfig): ResolvedContinuationConfig;
@@ -0,0 +1,6 @@
1
+ export { LeadConfigSchema } from "./schema";
2
+ export type { LeadConfig, AgentOverrideConfig, CustomAgentConfig, CategoryConfig, CategoriesConfig, BackgroundConfig, ContinuationConfig, WorkflowConfig, ExperimentalConfig, ToolPermissionMap, } from "./schema";
3
+ export { mergeConfigs } from "./merge";
4
+ export { loadLeadConfig } from "./loader";
5
+ export { resolveContinuationConfig } from "./continuation";
6
+ export type { ResolvedContinuationConfig } from "./continuation";
@@ -0,0 +1,12 @@
1
+ import type { LeadConfig } from "./schema";
2
+ /**
3
+ * Load and merge Lead config from:
4
+ * 1. User global config: ~/.config/opencode/lead.jsonc
5
+ * 2. Project config: {directory}/.opencode/lead.jsonc
6
+ *
7
+ * Project config overrides user config.
8
+ * Returns valid LeadConfig even if no files exist (empty defaults).
9
+ */
10
+ export declare function loadLeadConfig(directory: string, options?: {
11
+ homeDir?: string;
12
+ }): LeadConfig;
@@ -0,0 +1,8 @@
1
+ import type { LeadConfig } from "./schema";
2
+ /**
3
+ * Deep-merges two LeadConfig objects.
4
+ * - Objects (agents, custom_agents, categories): deep-merged, project overrides
5
+ * - Arrays (disabled_*): unioned and deduplicated
6
+ * - Scalars: project overrides user
7
+ */
8
+ export declare function mergeConfigs(user: LeadConfig, project: LeadConfig): LeadConfig;
@@ -0,0 +1,12 @@
1
+ interface ScaffoldOptions {
2
+ directory: string;
3
+ }
4
+ /**
5
+ * Checks if a project-level lead.jsonc exists.
6
+ * If not, creates one with the default model chains documented.
7
+ *
8
+ * Synchronous — safe to call during plugin init without blocking.
9
+ * Returns true if a config was scaffolded, false if one already existed.
10
+ */
11
+ export declare function scaffoldConfigIfMissing(options: ScaffoldOptions): boolean;
12
+ export {};
@@ -0,0 +1,140 @@
1
+ import { z } from "zod";
2
+ declare const ToolPermissionMapSchema: z.ZodRecord<z.ZodString, z.ZodBoolean>;
3
+ declare const AgentOverrideConfigSchema: z.ZodObject<{
4
+ model: z.ZodOptional<z.ZodString>;
5
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
7
+ display_name: z.ZodOptional<z.ZodString>;
8
+ }, z.core.$strip>;
9
+ declare const CustomAgentConfigSchema: z.ZodObject<{
10
+ prompt: z.ZodOptional<z.ZodString>;
11
+ prompt_file: z.ZodOptional<z.ZodString>;
12
+ model: z.ZodOptional<z.ZodString>;
13
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
15
+ display_name: z.ZodOptional<z.ZodString>;
16
+ mode: z.ZodOptional<z.ZodEnum<{
17
+ subagent: "subagent";
18
+ primary: "primary";
19
+ all: "all";
20
+ }>>;
21
+ triggers: z.ZodOptional<z.ZodArray<z.ZodObject<{
22
+ domain: z.ZodString;
23
+ trigger: z.ZodString;
24
+ }, z.core.$strip>>>;
25
+ description: z.ZodOptional<z.ZodString>;
26
+ }, z.core.$strip>;
27
+ declare const CategoryConfigSchema: z.ZodObject<{
28
+ model: z.ZodOptional<z.ZodString>;
29
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
30
+ }, z.core.$strip>;
31
+ declare const CategoriesConfigSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
32
+ model: z.ZodOptional<z.ZodString>;
33
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
34
+ }, z.core.$strip>>;
35
+ declare const BackgroundConfigSchema: z.ZodObject<{
36
+ max_concurrent: z.ZodOptional<z.ZodNumber>;
37
+ }, z.core.$strip>;
38
+ declare const ContinuationRecoveryConfigSchema: z.ZodObject<{
39
+ compaction: z.ZodOptional<z.ZodBoolean>;
40
+ }, z.core.$strip>;
41
+ declare const ContinuationIdleConfigSchema: z.ZodObject<{
42
+ enabled: z.ZodOptional<z.ZodBoolean>;
43
+ work: z.ZodOptional<z.ZodBoolean>;
44
+ workflow: z.ZodOptional<z.ZodBoolean>;
45
+ todo_prompt: z.ZodOptional<z.ZodBoolean>;
46
+ }, z.core.$strip>;
47
+ declare const ContinuationConfigSchema: z.ZodObject<{
48
+ recovery: z.ZodOptional<z.ZodObject<{
49
+ compaction: z.ZodOptional<z.ZodBoolean>;
50
+ }, z.core.$strip>>;
51
+ idle: z.ZodOptional<z.ZodObject<{
52
+ enabled: z.ZodOptional<z.ZodBoolean>;
53
+ work: z.ZodOptional<z.ZodBoolean>;
54
+ workflow: z.ZodOptional<z.ZodBoolean>;
55
+ todo_prompt: z.ZodOptional<z.ZodBoolean>;
56
+ }, z.core.$strip>>;
57
+ }, z.core.$strip>;
58
+ declare const WorkflowConfigSchema: z.ZodObject<{
59
+ disabled_workflows: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
+ directories: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
+ }, z.core.$strip>;
62
+ declare const ExperimentalConfigSchema: z.ZodObject<{
63
+ enabled: z.ZodOptional<z.ZodBoolean>;
64
+ }, z.core.$strip>;
65
+ export declare const LeadConfigSchema: z.ZodObject<{
66
+ $schema: z.ZodOptional<z.ZodString>;
67
+ agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
68
+ model: z.ZodOptional<z.ZodString>;
69
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
71
+ display_name: z.ZodOptional<z.ZodString>;
72
+ }, z.core.$strip>>>;
73
+ custom_agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
74
+ prompt: z.ZodOptional<z.ZodString>;
75
+ prompt_file: z.ZodOptional<z.ZodString>;
76
+ model: z.ZodOptional<z.ZodString>;
77
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
78
+ tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
79
+ display_name: z.ZodOptional<z.ZodString>;
80
+ mode: z.ZodOptional<z.ZodEnum<{
81
+ subagent: "subagent";
82
+ primary: "primary";
83
+ all: "all";
84
+ }>>;
85
+ triggers: z.ZodOptional<z.ZodArray<z.ZodObject<{
86
+ domain: z.ZodString;
87
+ trigger: z.ZodString;
88
+ }, z.core.$strip>>>;
89
+ description: z.ZodOptional<z.ZodString>;
90
+ }, z.core.$strip>>>;
91
+ categories: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
92
+ model: z.ZodOptional<z.ZodString>;
93
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
94
+ }, z.core.$strip>>>;
95
+ disabled_hooks: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
+ disabled_tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
97
+ disabled_agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
98
+ disabled_skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
99
+ skill_directories: z.ZodOptional<z.ZodArray<z.ZodString>>;
100
+ background: z.ZodOptional<z.ZodObject<{
101
+ max_concurrent: z.ZodOptional<z.ZodNumber>;
102
+ }, z.core.$strip>>;
103
+ continuation: z.ZodOptional<z.ZodObject<{
104
+ recovery: z.ZodOptional<z.ZodObject<{
105
+ compaction: z.ZodOptional<z.ZodBoolean>;
106
+ }, z.core.$strip>>;
107
+ idle: z.ZodOptional<z.ZodObject<{
108
+ enabled: z.ZodOptional<z.ZodBoolean>;
109
+ work: z.ZodOptional<z.ZodBoolean>;
110
+ workflow: z.ZodOptional<z.ZodBoolean>;
111
+ todo_prompt: z.ZodOptional<z.ZodBoolean>;
112
+ }, z.core.$strip>>;
113
+ }, z.core.$strip>>;
114
+ workflows: z.ZodOptional<z.ZodObject<{
115
+ disabled_workflows: z.ZodOptional<z.ZodArray<z.ZodString>>;
116
+ directories: z.ZodOptional<z.ZodArray<z.ZodString>>;
117
+ }, z.core.$strip>>;
118
+ experimental: z.ZodOptional<z.ZodObject<{
119
+ enabled: z.ZodOptional<z.ZodBoolean>;
120
+ }, z.core.$strip>>;
121
+ log_level: z.ZodOptional<z.ZodEnum<{
122
+ DEBUG: "DEBUG";
123
+ INFO: "INFO";
124
+ WARN: "WARN";
125
+ ERROR: "ERROR";
126
+ }>>;
127
+ }, z.core.$strip>;
128
+ export type LeadConfig = z.infer<typeof LeadConfigSchema>;
129
+ export type AgentOverrideConfig = z.infer<typeof AgentOverrideConfigSchema>;
130
+ export type CustomAgentConfig = z.infer<typeof CustomAgentConfigSchema>;
131
+ export type CategoryConfig = z.infer<typeof CategoryConfigSchema>;
132
+ export type CategoriesConfig = z.infer<typeof CategoriesConfigSchema>;
133
+ export type BackgroundConfig = z.infer<typeof BackgroundConfigSchema>;
134
+ export type ContinuationConfig = z.infer<typeof ContinuationConfigSchema>;
135
+ export type ContinuationRecoveryConfig = z.infer<typeof ContinuationRecoveryConfigSchema>;
136
+ export type ContinuationIdleConfig = z.infer<typeof ContinuationIdleConfigSchema>;
137
+ export type WorkflowConfig = z.infer<typeof WorkflowConfigSchema>;
138
+ export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>;
139
+ export type ToolPermissionMap = z.infer<typeof ToolPermissionMapSchema>;
140
+ export {};
@@ -0,0 +1,32 @@
1
+ import type { AgentConfig } from "@opencode-ai/sdk";
2
+ import type { PluginInput } from "@opencode-ai/plugin";
3
+ import type { LeadConfig } from "./config/schema";
4
+ import type { ResolvedContinuationConfig } from "./config/continuation";
5
+ import type { ResolveSkillsFn } from "./agents/agent-builder";
6
+ import { ConfigHandler } from "./managers/config-handler";
7
+ import { BackgroundManager } from "./managers/background-manager";
8
+ import { SkillMcpManager } from "./managers/skill-mcp-manager";
9
+ /**
10
+ * L.E.A.D. manager instances created during plugin initialization.
11
+ */
12
+ export interface LeadManagers {
13
+ /** Handles registering agents into OpenCode config */
14
+ configHandler: ConfigHandler;
15
+ /** Manages background task spawning and lifecycle */
16
+ backgroundManager: BackgroundManager;
17
+ /** Manages MCP server connections from skills (v0.1: stub) */
18
+ skillMcpManager: SkillMcpManager;
19
+ /** All registered agent configs (builtin + custom) */
20
+ agents: Record<string, AgentConfig>;
21
+ }
22
+ export interface CreateManagersOptions {
23
+ ctx: PluginInput;
24
+ pluginConfig: LeadConfig;
25
+ continuation: ResolvedContinuationConfig;
26
+ resolveSkills?: ResolveSkillsFn;
27
+ }
28
+ /**
29
+ * Create all L.E.A.D. manager instances.
30
+ * Builds builtin agents, applies config overrides, adds custom agents.
31
+ */
32
+ export declare function createManagers(options: CreateManagersOptions): Promise<LeadManagers>;
@@ -0,0 +1,24 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ import type { LeadConfig } from "./config/schema";
3
+ import type { ResolveSkillsFn } from "./agents/agent-builder";
4
+ import type { LoadedSkill } from "./features/skill-loader/types";
5
+ /**
6
+ * Result of the tools creation step.
7
+ */
8
+ export interface ToolsResult {
9
+ /** Loaded skill instances */
10
+ availableSkills: LoadedSkill[];
11
+ /** Resolver function for skill prompt injection */
12
+ resolveSkills: ResolveSkillsFn;
13
+ /** (Empty in v0.1 — tools come from OpenCode, not the plugin) */
14
+ tools: Record<string, never>;
15
+ }
16
+ export interface CreateToolsOptions {
17
+ ctx: PluginInput;
18
+ pluginConfig: LeadConfig;
19
+ }
20
+ /**
21
+ * Load skills, create the resolver, and return the tools result.
22
+ * In v0.1, the plugin does not register custom tools — OpenCode provides them.
23
+ */
24
+ export declare function createTools(options: CreateToolsOptions): Promise<ToolsResult>;
@@ -0,0 +1,2 @@
1
+ export type { WorkState, PlanProgress } from "../../features/work-state/types";
2
+ export { STATE_FILE, STATE_DIR, ADHOC_DIR } from "../../features/work-state/constants";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Policy result types for the L.E.A.D. policy engine.
3
+ * Policies are evaluated at lifecycle hooks (chat, tool, session).
4
+ * Deny wins over allow when merging multiple policy results.
5
+ */
6
+ export type PolicyVerdict = "allow" | "deny";
7
+ export interface PolicyResult {
8
+ /** Whether this policy allows or denies the action */
9
+ verdict: PolicyVerdict;
10
+ /** Optional reason explaining the verdict */
11
+ reason?: string;
12
+ /** Optional metadata for downstream handling */
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ /**
16
+ * Merge multiple policy results.
17
+ * Deny wins over allow — if any policy denies, the merged result is deny.
18
+ */
19
+ export declare function mergePolicyResults(results: PolicyResult[]): PolicyResult;
20
+ /** Convenience factory — creates an allow result */
21
+ export declare function allow(reason?: string): PolicyResult;
22
+ /** Convenience factory — creates a deny result */
23
+ export declare function deny(reason: string, metadata?: Record<string, unknown>): PolicyResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Session state tracking interfaces.
3
+ * Tracks per-session token usage and idle state for hook coordination.
4
+ */
5
+ export interface SessionTokenState {
6
+ /** Session identifier */
7
+ sessionId: string;
8
+ /** Total input tokens consumed in this session */
9
+ inputTokens: number;
10
+ /** Total output tokens consumed in this session */
11
+ outputTokens: number;
12
+ /** Timestamp of last activity */
13
+ lastActivityAt: Date;
14
+ }
15
+ export interface SessionIdleState {
16
+ /** Session identifier */
17
+ sessionId: string;
18
+ /** Whether the session is currently idle */
19
+ isIdle: boolean;
20
+ /** Last assistant message content, if any */
21
+ lastAssistantMessage?: string;
22
+ /** Last user message content, if any */
23
+ lastUserMessage?: string;
24
+ }
25
+ /**
26
+ * Owner of the execution lease — determines which system drives the session.
27
+ * Workflow takes precedence when both active.
28
+ */
29
+ export type ExecutionLeaseOwner = "none" | "plan" | "workflow";
30
+ export interface ExecutionLeaseSnapshot {
31
+ owner: ExecutionLeaseOwner;
32
+ hasActivePlan: boolean;
33
+ hasActiveWorkflow: boolean;
34
+ activePlanPaused: boolean;
35
+ activeWorkflowPaused: boolean;
36
+ }
37
+ /**
38
+ * Determine which system owns the current execution lease.
39
+ * Workflow takes precedence if both are active and running.
40
+ */
41
+ export declare function determineExecutionOwner(snapshot: ExecutionLeaseSnapshot): ExecutionLeaseOwner;
@@ -0,0 +1,4 @@
1
+ export type { WorkflowRepository } from "./workflow-repository";
2
+ export type { WorkflowService } from "./workflow-service";
3
+ export type { WorkflowCompletion } from "./workflow-completion";
4
+ export type { WorkflowContext } from "./workflow-context";
@@ -0,0 +1,9 @@
1
+ import type { CompletionContext, CompletionCheckResult, CompletionMethod } from "../../features/workflow/types";
2
+ /**
3
+ * Interface for step completion detection.
4
+ * Implementation lives in features/workflow/completion.
5
+ */
6
+ export interface WorkflowCompletion {
7
+ /** Check if the current step is complete */
8
+ check(method: CompletionMethod, context: CompletionContext): CompletionCheckResult;
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { WorkflowInstance, WorkflowStepDefinition, WorkflowDefinition } from "../../features/workflow/types";
2
+ /**
3
+ * Interface for workflow prompt composition.
4
+ * Implementation lives in features/workflow/context.
5
+ */
6
+ export interface WorkflowContext {
7
+ /** Build the step prompt with variable substitution and context threading */
8
+ buildStepPrompt(instance: WorkflowInstance, stepDef: WorkflowStepDefinition, definition: WorkflowDefinition): string;
9
+ }
@@ -0,0 +1,19 @@
1
+ import type { WorkflowInstance } from "../../features/workflow/types";
2
+ /**
3
+ * Repository interface for workflow instance persistence.
4
+ * Implementation lives in features/workflow/storage.
5
+ */
6
+ export interface WorkflowRepository {
7
+ /** Save or update a workflow instance */
8
+ save(directory: string, instance: WorkflowInstance): boolean;
9
+ /** Load a workflow instance by ID */
10
+ load(directory: string, instanceId: string): WorkflowInstance | null;
11
+ /** Get the currently active workflow instance */
12
+ getActive(directory: string): WorkflowInstance | null;
13
+ /** Set the active instance pointer */
14
+ setActive(directory: string, instanceId: string): boolean;
15
+ /** Clear the active instance pointer */
16
+ clearActive(directory: string): boolean;
17
+ /** List all instance IDs */
18
+ list(directory: string): string[];
19
+ }
@@ -0,0 +1,32 @@
1
+ import type { EngineAction, WorkflowDefinition } from "../../features/workflow/types";
2
+ /**
3
+ * Service interface for workflow lifecycle operations.
4
+ * Implementation lives in features/workflow/engine.
5
+ */
6
+ export interface WorkflowService {
7
+ /** Start a new workflow instance */
8
+ start(input: {
9
+ definition: WorkflowDefinition;
10
+ definitionPath: string;
11
+ goal: string;
12
+ sessionId: string;
13
+ directory: string;
14
+ }): EngineAction;
15
+ /** Check if current step is complete and advance if so */
16
+ checkAndAdvance(input: {
17
+ directory: string;
18
+ context: {
19
+ lastAssistantMessage?: string;
20
+ lastUserMessage?: string;
21
+ directory: string;
22
+ };
23
+ }): EngineAction;
24
+ /** Pause the active workflow */
25
+ pause(directory: string, reason?: string): boolean;
26
+ /** Resume the active workflow */
27
+ resume(directory: string): EngineAction;
28
+ /** Skip the current step */
29
+ skipStep(directory: string): EngineAction;
30
+ /** Abort the active workflow */
31
+ abort(directory: string): boolean;
32
+ }
@@ -0,0 +1,36 @@
1
+ import type { LoadedSkill } from "./types";
2
+ interface SkillFrontmatter {
3
+ name?: string;
4
+ description?: string;
5
+ model?: string;
6
+ tools?: string | string[];
7
+ }
8
+ /**
9
+ * Parse YAML frontmatter from a SKILL.md file.
10
+ * Manual parsing — no external YAML dependency.
11
+ */
12
+ export declare function parseFrontmatter(text: string): {
13
+ metadata: SkillFrontmatter;
14
+ content: string;
15
+ };
16
+ /**
17
+ * Load a single SKILL.md file as a LoadedSkill.
18
+ * Returns null if the file cannot be read or lacks a name.
19
+ */
20
+ export declare function loadSkillFile(filePath: string, source: LoadedSkill["source"]): LoadedSkill | null;
21
+ /**
22
+ * Recursively scan a directory for SKILL.md files.
23
+ */
24
+ export declare function scanDirectory(dir: string, source: LoadedSkill["source"]): LoadedSkill[];
25
+ export interface DiscoverSkillsOptions {
26
+ projectDirectory: string;
27
+ customDirs?: string[];
28
+ }
29
+ /**
30
+ * Discover skills from filesystem:
31
+ * 1. User skills: ~/.config/opencode/skills/
32
+ * 2. Project skills: {projectDirectory}/.opencode/skills/
33
+ * 3. Custom dirs from config (sandboxed via resolveSafePath)
34
+ */
35
+ export declare function discoverSkillsFromDirs(options: DiscoverSkillsOptions): LoadedSkill[];
36
+ export {};
@@ -0,0 +1,6 @@
1
+ export type { LoadedSkill, SkillLoadResult } from "./types";
2
+ export { loadSkills } from "./loader";
3
+ export type { LoadSkillsOptions } from "./loader";
4
+ export { createSkillResolver } from "./resolver";
5
+ export { discoverSkillsFromDirs, scanDirectory, parseFrontmatter, loadSkillFile } from "./discovery";
6
+ export { fetchSkillsFromApi } from "./opencode-client";
@@ -0,0 +1,15 @@
1
+ import type { SkillLoadResult } from "./types";
2
+ export interface LoadSkillsOptions {
3
+ serverUrl?: URL | string;
4
+ projectDirectory: string;
5
+ customDirs?: string[];
6
+ disabledSkills?: string[];
7
+ }
8
+ /**
9
+ * Orchestrate skill loading:
10
+ * 1. Try OpenCode API (serverUrl/skill endpoint)
11
+ * 2. Fallback to filesystem discovery
12
+ * 3. Deduplicate by name (API wins)
13
+ * 4. Filter disabled skills
14
+ */
15
+ export declare function loadSkills(options: LoadSkillsOptions): Promise<SkillLoadResult>;
@@ -0,0 +1,6 @@
1
+ import type { LoadedSkill } from "./types";
2
+ /**
3
+ * Fetch skills from the OpenCode server skill endpoint.
4
+ * Returns an empty array on any error (connection refused, timeout, etc.)
5
+ */
6
+ export declare function fetchSkillsFromApi(serverUrl: URL | string, directory: string, timeoutMs?: number): Promise<LoadedSkill[]>;
@@ -0,0 +1,8 @@
1
+ import type { SkillLoadResult } from "./types";
2
+ import type { ResolveSkillsFn } from "../../agents/agent-builder";
3
+ /**
4
+ * Create a skill resolver from a SkillLoadResult.
5
+ * Returns a ResolveSkillsFn closure that, when called with skill names
6
+ * and an optional disabled set, returns concatenated skill content.
7
+ */
8
+ export declare function createSkillResolver(loadResult: SkillLoadResult): ResolveSkillsFn;
@@ -0,0 +1,14 @@
1
+ export interface LoadedSkill {
2
+ name: string;
3
+ content: string;
4
+ source: "api" | "user" | "project" | "custom";
5
+ metadata?: {
6
+ description?: string;
7
+ model?: string;
8
+ tools?: string[];
9
+ };
10
+ }
11
+ export interface SkillLoadResult {
12
+ skills: LoadedSkill[];
13
+ errors: string[];
14
+ }
@@ -0,0 +1,4 @@
1
+ export declare const STATE_DIR = ".lead";
2
+ export declare const STATE_FILE = ".lead/state.json";
3
+ /** Directory for ad-hoc plans (no ticket linked) */
4
+ export declare const ADHOC_DIR = ".lead/_adhoc";
@@ -0,0 +1,5 @@
1
+ export type { WorkState, PlanProgress } from "./types";
2
+ export type { PlanValidationResult, PlanValidationIssue } from "./validation-types";
3
+ export { readWorkState, writeWorkState, clearWorkState, getPlanProgress } from "./storage";
4
+ export { validatePlanFile } from "./validation";
5
+ export { STATE_DIR, STATE_FILE, ADHOC_DIR } from "./constants";
@@ -0,0 +1,20 @@
1
+ import type { WorkState, PlanProgress } from "./types";
2
+ /**
3
+ * Read the active work state from .lead/state.json.
4
+ * Returns null if the file does not exist or cannot be parsed.
5
+ */
6
+ export declare function readWorkState(dir: string): WorkState | null;
7
+ /**
8
+ * Write work state to .lead/state.json.
9
+ * Creates the directory if it does not exist.
10
+ */
11
+ export declare function writeWorkState(dir: string, state: WorkState): void;
12
+ /**
13
+ * Remove the active work state file.
14
+ */
15
+ export declare function clearWorkState(dir: string): void;
16
+ /**
17
+ * Count plan checkboxes in a markdown plan file.
18
+ * Returns PlanProgress with total, completed, and isComplete.
19
+ */
20
+ export declare function getPlanProgress(planPath: string): PlanProgress;
@@ -0,0 +1,16 @@
1
+ export interface WorkState {
2
+ active_plan: string;
3
+ started_at: string;
4
+ session_ids: string[];
5
+ plan_name: string;
6
+ agent?: string;
7
+ start_sha?: string;
8
+ paused?: boolean;
9
+ continuation_completed_snapshot?: number;
10
+ stale_continuation_count?: number;
11
+ }
12
+ export interface PlanProgress {
13
+ total: number;
14
+ completed: number;
15
+ isComplete: boolean;
16
+ }
@@ -0,0 +1,8 @@
1
+ export interface PlanValidationResult {
2
+ valid: boolean;
3
+ issues: PlanValidationIssue[];
4
+ }
5
+ export interface PlanValidationIssue {
6
+ severity: "error" | "warning";
7
+ message: string;
8
+ }
@@ -0,0 +1,6 @@
1
+ import type { PlanValidationResult } from "./validation-types";
2
+ /**
3
+ * Validate a plan markdown file.
4
+ * Checks for required sections and at least one checkbox.
5
+ */
6
+ export declare function validatePlanFile(path: string): PlanValidationResult;
@@ -0,0 +1,10 @@
1
+ import type { EngineAction } from "./types";
2
+ export interface WorkflowCommandResult {
3
+ message: string;
4
+ action?: EngineAction;
5
+ }
6
+ /**
7
+ * Parse and execute workflow subcommands.
8
+ * Supported: status, pause, resume, skip [stepId], abort
9
+ */
10
+ export declare function executeWorkflowCommand(command: string, directory: string, customDirs?: string[]): WorkflowCommandResult;
@@ -0,0 +1,5 @@
1
+ import type { CompletionContext, CompletionCheckResult, CompletionMethod } from "./types";
2
+ /**
3
+ * Check if the current workflow step is complete based on its completion method.
4
+ */
5
+ export declare function checkStepCompletion(method: CompletionMethod, ctx: CompletionContext): CompletionCheckResult;
@@ -0,0 +1,8 @@
1
+ export declare const WORKFLOW_STATE_DIR = ".lead/workflows";
2
+ export declare const ACTIVE_INSTANCE_FILE = ".lead/workflows/active-instance.json";
3
+ export declare const WORKFLOW_DIRS: {
4
+ project: string;
5
+ user: string;
6
+ };
7
+ export declare const WORKFLOW_CONTINUATION_MARKER = "<!-- lead:workflow-continuation -->";
8
+ export declare const WORKFLOW_STEP_COMPLETE_SIGNAL = "<!-- workflow:step-complete -->";