Commit Graph

696 Commits

Author SHA1 Message Date
xiaoju 341ff656dc feat(planner,coder,moderator): integrate CAS for phase tracking
Phase 2 of #23:
- Planner schema compact: {hash, title} only, details stored via CAS CLI
- Planner prompt instructs agent to shell out `cas put` for each phase
- Coder prompt instructs agent to `cas get` for phase details, report hash
- Moderator compares hashes instead of names
- Removed COMPLETED_PHASE_SENTINELS — hash matching eliminates ambiguity

Refs #23
2026-05-07 04:54:25 +00:00
xiaoju 4b44665c7e feat(workflow): add thread-scoped CAS (Content-Addressable Storage)
Phase 1 of #23:
- createThreadCas() core API: put/get/delete/list with XXH64 hashing
- hashString() utility for string → 13-char Crockford Base32
- CLI: uncaged-workflow cas get/put/list/rm subcommands
- thread rm now cleans up .cas/ directory
- 10 new tests for CAS operations

Refs #23
2026-05-07 04:30:19 +00:00
xiaoju 172e9b34cc feat(planner): add hash and title fields to phase schema
Each phase now carries a hash (Crockford Base32 identifier) and a
one-line title alongside the existing name/description/acceptance.
This gives agents immediate semantic context in the prompt without
needing to load full phase details from CAS.

Refs #23
2026-05-07 04:18:42 +00:00
xiaoju 96fc3e220a fix(solve-issue): handle one-shot coder completing all phases at once
The moderator now treats completedPhase matching the last planned phase name
as full completion. Also recognizes sentinel values (all-done, all_done,
complete) for robustness.

Fixes #21

小橘 🍊(NEKO Team)
2026-05-07 03:13:44 +00:00
xiaoju 43e1f82303 refactor: extractPrompt out of ExtractContext, into ExtractFn parameter
ExtractFn = (schema, prompt, ctx) => Promise<T>
extractPrompt stays in RoleDefinition (definition layer), not in context (state layer).
Callers pass their own prompt — engine uses roleDef.extractPrompt, cursor agent uses its own.

小橘 <xiaoju@shazhou.work>
2026-05-07 01:27:12 +00:00
xiaoju d472de1247 refactor: three-phase context (Moderator/Agent/Extract) + extractPrompt + unified ExtractFn
- ModeratorContext → AgentContext → ExtractContext progressive types
- ThreadContext is now alias for AgentContext
- RoleDefinition adds extractPrompt field
- ExtractFn = (schema, ctx: ExtractContext) => Promise<T>
- createWorkflow takes ExtractFn, engine loop: moderator → agent → extract
- Remove ExtractConfig, extractMetaOrThrow, extract-meta.ts

小橘 <xiaoju@shazhou.work>
2026-05-07 01:05:31 +00:00
xiaoju 99a137422c feat: add ExtractFn utility, cursor agent workspace from thread context
- New ExtractFn = <T>(schema, prompt) => (ctx) => Promise<T>
- createExtract(provider) creates an LLM-backed ExtractFn
- CursorAgent removes workdir config, uses ExtractFn to resolve workspace from ThreadContext at runtime
- buildAgentPrompt(ctx) — reads systemPrompt from ctx.currentRole

小橘 <xiaoju@shazhou.work>
2026-05-07 00:17:31 +00:00
xiaoju d351343aa8 fix: pure data role packages use 'echo no tests' instead of 'bun test'
workflow-role-coder and workflow-role-planner have no test files —
bun test exits 1 on empty. Changed to 'echo no tests' for clean CI.

小橘 <xiaoju@shazhou.work>
2026-05-06 14:33:16 +00:00
xiaoju 2482fb7e62 chore: remove all dryRun infrastructure
dryRun no longer needed — tests use mock agents + mock fetch instead.
Removes isDryRun from WorkflowFnOptions, dryRun from ExtractConfig,
dryRunMeta from RoleDefinition, --dry-run from CLI, and all related
plumbing in engine/worker/fork/extract.

小橘 <xiaoju@shazhou.work>
2026-05-06 14:25:44 +00:00
xiaoju fa9163e462 refactor: all-agentic architecture — roles as pure data, agent binding at runtime
BREAKING: Major architecture change.

- RoleDefinition = pure data (systemPrompt + schema + dryRunMeta)
- AgentFn = (ctx: ThreadContext) => Promise<string>, reads ctx.currentRole
- WorkflowDefinition decoupled from agents, bound via AgentBinding at runtime
- createWorkflow(def, binding, extract) replaces createRoleModerator
- Meta extraction moved into engine loop
- Delete workflow-util-role package (createRole, decorators, extract all gone)
- Role packages become pure data exports
- Agent packages updated to single-arg AgentFn

小橘 <xiaoju@shazhou.work>
2026-05-06 14:14:33 +00:00
xiaoju fce2bf7441 refactor: systemPrompt → pure string, threadId injected by agent layer
- CreateRoleArgs.systemPrompt simplified to string (no more ctx callback)
- buildAgentPrompt injects real ctx.threadId in Tools section
- All four roles compute prompt at construction time from config only
- Removed duplicate ctx.threadId injection from reviewer/committer prompts

小橘 <xiaoju@shazhou.work>
2026-05-06 12:25:41 +00:00
xiaoju c9cdfe37db refactor: extract planner and coder into standalone role packages
- New @uncaged/workflow-role-planner (phaseSchema, createPlannerRole)
- New @uncaged/workflow-role-coder (coderMetaSchema, createCoderRole)
- solve-issue template imports from new packages, keeps dry-run defaults

小橘 <xiaoju@shazhou.work>
2026-05-06 11:40:19 +00:00
xiaoju 45bb5af99a feat: per-role agent config + phased planner/coder in solve-issue template
- SolveIssueRolesConfig.agents allows per-role AgentFn overrides
- PlannerMeta now outputs phases (name, description, acceptance)
- CoderMeta reports completedPhase, works one phase at a time
- Moderator routes coder→coder until all phases done, then reviewer

小橘 <xiaoju@shazhou.work>
2026-05-06 11:35:45 +00:00
xiaoju c7b0beb6be refactor: unify RoleDefinition + WorkflowDefinition with description & schema
- Add RoleDefinition<Meta> = { description, run, schema } to core types
- WorkflowDefinition now carries description and RoleDefinition per role
- Add buildDescriptor() in core to derive WorkflowDescriptor from WorkflowDefinition
- Remove buildDescriptorFromRoles / RoleDescriptorInput from workflow-util-role
- Update solve-issue template, examples, and all tests

小橘 <xiaoju@shazhou.work>
2026-05-06 11:19:49 +00:00
xiaoju 79cf97e617 refactor: remove name from WorkflowDefinition, fix threadId type errors
WorkflowDefinition no longer carries 'name' — name is a registry-level
concern, not a bundle property. Also fixed all missing threadId in test
fixtures to match the updated ThreadContext type.

小橘 <xiaoju@shazhou.work>
2026-05-06 11:01:09 +00:00
xiaoju 196562c82a feat: committer distinguishes recoverable vs unrecoverable failures
CommitterMeta is now a 3-way discriminated union:
- committed: success with branch + commitSha
- recoverable: coder can fix (hook failures, lint, test, conflicts)
- unrecoverable: can't be fixed by code (auth, permissions, disk)

Moderator routes recoverable → coder for retry.
2026-05-06 10:53:17 +00:00
xiaoju 267ca73a1b fix: committer prompt — don't fix failures, just report them 2026-05-06 10:49:22 +00:00
xiaoju aee71fd2e7 refactor: simplify committer — minimal prompt, config simplified
- CommitterGitConfig → CommitterConfig { cwd } (remote dropped)
- threadId from ctx.threadId, not config
- Remove summarizeThreadContext — agent uses uncaged-workflow thread CLI
- Prompt doesn't teach git or require structured output
2026-05-06 10:39:09 +00:00
xiaoju 8ce1dd3cca refactor: remove JSON output requirement from reviewer prompt
Let extractMetaOrThrow do its job — agent outputs naturally,
LLM extract handles structuring.
2026-05-06 10:35:53 +00:00
xiaoju 4b27943871 refactor: simplify reviewer — discriminated union meta, minimal prompt
- ReviewerMeta → discriminated union: approved | rejected (with issues)
- Remove method-heavy prompt — agent has built-in code review capability
- Prompt now just says: project path, threadId for context, approve or reject
- No non-blocking suggestions (they get ignored anyway)
- ReviewerConfig simplified to just { cwd }
2026-05-06 10:29:48 +00:00
xiaoju 8d5b97c67e feat: add threadId to ThreadContext and WorkflowFnOptions
Agentic roles can now access ctx.threadId to query thread details
via uncaged-workflow CLI for richer context.
2026-05-06 10:23:25 +00:00
xiaoju 513c006ce3 refactor: rename workflow-role-llm → workflow-agent-llm
The package only contains createLlmAdapter (OpenAI chat → AgentFn),
which is an agent adapter, not a role. Aligns with workflow-agent-cursor
and workflow-agent-hermes naming.
2026-05-06 10:14:35 +00:00
xingyue 94fa964b84 fix(workflow): add typecheck script and fix remaining type errors
- Add typecheck script (bunx tsc --build) to package.json
- Update check script to run typecheck before biome
- Fix mock fetch casts in test files (bun-types preconnect)
- Fix RequestInfo → Request | string | URL in llm-extract test
- Fix ThreadContext generic cast in solve-issue-template test
- Fix git-exec.ts missing return and module resolution
- Remove @types/node from workflow-role-committer
- Add exports field to workflow-util-agent/package.json
2026-05-06 18:10:25 +08:00
xiaoju 2c642b1a53 refactor: committer as pure agent role with discriminated union meta (#17)
- Remove hardcoded git commands (git-exec.ts deleted)
- CommitterMeta is now a discriminated union: committed | failed
- Agent handles git operations, committer extracts structured result
- Moderator can route on meta.status for retry logic

Closes #17
2026-05-06 10:06:27 +00:00
xiaoju c15a5554c0 refactor: replace gitExec with spawnCli from workflow-util-agent
Remove hand-rolled execFile + promisify, delegate to spawnCli.
Same throw-on-error interface, better error messages.
2026-05-06 09:51:06 +00:00
xiaoju e38852a761 Merge pull request 'fix(workflow): resolve type errors across all packages' (#16) from fix/type-errors-and-tsbuildinfo into main 2026-05-06 09:44:49 +00:00
xiaoju fd8f1f2491 refactor: move createRole to workflow-util-role
workflow-role-llm now only contains createLlmAdapter (OpenAI chat
completions → AgentFn). All role infrastructure lives in util-role.
2026-05-06 09:42:49 +00:00
xingyue 98b6153070 fix(workflow): resolve type errors across all packages and remove tsbuildinfo from tracking
- Add bun-types and @types/xxhashjs to root devDependencies
- Add types: ['bun-types'] to root and package tsconfigs
- Fix AST Node type narrowing in bundle-validator.ts with AcornNode type and narrowNode helper
- Fix generic ThreadContext variance in create-role-moderator.ts
- Add explicit parameter types in worker.ts
- Fix ChildProcess type in worker-spawn.ts to match spawn() stdio config
- Remove all tsconfig.tsbuildinfo from git tracking
- Add tsconfig.tsbuildinfo to .gitignore
2026-05-06 17:41:11 +08:00
xiaoju c04e7c31af refactor: move llmExtract, extractMeta, buildDescriptor, types to workflow-util-role
workflow-role-llm now only contains LLM-as-agent specifics:
  - createRole (wires agent + extract)
  - createLlmAdapter (OpenAI chat completions agent)

workflow-util-role now provides all role infrastructure:
  - decorators (decorateRole, withDryRun, onFail)
  - llmExtract / extractMetaOrThrow (structured extraction)
  - buildDescriptorFromRoles (zod → JSON Schema)
  - LlmProvider, LlmMessage types
2026-05-06 08:13:27 +00:00
xiaoju 6e62c7458d refactor: remove schemaDefaults, use caller-provided dryRunMeta
Cursor completed removal of schemaDefaults. All dry-run paths now
use explicit dryRunMeta from the caller.
2026-05-06 08:10:40 +00:00
xiaoju 82d3478895 refactor: extract @uncaged/workflow-util-role from role-llm (#15)
Move pure role utilities (decorateRole, withDryRun, onFail, schemaDefaults)
into @uncaged/workflow-util-role. extractMetaOrThrow stays in role-llm
since it depends on LLM capabilities.

Dependency graph (no cycles):
  util-role → workflow
  role-llm → workflow, util-role
  committer → workflow, util-role, role-llm

Closes #15
2026-05-06 07:27:11 +00:00
xiaoju 2a71454c10 refactor: extract @uncaged/workflow-util-agent + smart prompt
- New package: spawn-cli + build-agent-prompt shared utils
- Smart prompt: start + meta summaries for middle steps + last step full
- Cursor/Hermes adapters now import from util-agent (no duplicate code)
- 109 tests pass, biome clean

Closes #14
小橘 <xiaoju@shazhou.work>
2026-05-06 07:17:59 +00:00
xiaoju db5cbd49e2 feat: @uncaged/workflow-template-solve-issue — first workflow template
planner → coder → reviewer → committer flow with retry logic.
- createSolveIssueWorkflow factory (agent-agnostic)
- buildSolveIssueDescriptor with zod@4 JSON Schema
- Moderator: reviewer reject → coder retry, maxRounds → END
- 103 tests pass, biome clean

Closes #13
小橘 <xiaoju@shazhou.work>
2026-05-06 07:04:28 +00:00
xiaoju 78d883ec5d feat: @uncaged/workflow-role-committer + @uncaged/workflow-role-reviewer
- Committer: git add/commit/push with LLM-generated branch+message
- Reviewer: code review role with approval meta
- Both use zod@4 schemas, no nerve-core deps
- 98 tests pass, biome clean

Closes #12
小橘 <xiaoju@shazhou.work>
2026-05-06 06:59:44 +00:00
xiaoju f21014fcdd feat: @uncaged/workflow-agent-cursor + @uncaged/workflow-agent-hermes
- Cursor adapter: spawn cursor-agent CLI, auto/specified model
- Hermes adapter: spawn hermes chat CLI
- Both: AgentFn interface, no nerve-core deps, Result-based config validation
- 93 tests pass, biome clean

Closes #10, Closes #11
小橘 <xiaoju@shazhou.work>
2026-05-06 06:54:24 +00:00
xiaoju c2a8f2d81b feat: @uncaged/workflow-role-llm — role factory + zod@4 schema
Migrated from nerve/workflow-utils:
- createRole with zod@4 schema → typed meta + JSON Schema
- createLlmAdapter — LLM provider abstraction
- llmExtract/llmExtractWithRetry — structured output extraction
- decorateRole/withDryRun/onFail — role decorators
- buildDescriptorFromRoles — auto-generate descriptor from zod schemas
- Zero nerve-core dependencies
- 83 tests pass, biome clean

Closes #9
小橘 <xiaoju@shazhou.work>
2026-05-06 06:50:19 +00:00
xiaoju 3467b772e6 refactor: named exports (run + descriptor), remove build pipeline
- Bundle contract: export const run + export const descriptor (no default export)
- add only accepts .esm.js, extracts descriptor via dynamic import → .yaml
- Removed: build-pipeline, generate-types, json-schema-to-ts
- Worker loads mod.run instead of mod.default
- Biome: no more noDefaultExport overrides for bundles
- 62 tests pass, biome clean

Closes #8
小橘 <xiaoju@shazhou.work>
2026-05-06 06:39:15 +00:00
xiaoju e670047e6a feat: build pipeline — .ts → .esm.js + .yaml + .d.ts 三件套
- add command auto-detects .ts vs .esm.js input
- .ts: Bun.build → bundle + descriptor extraction + JSON Schema → .d.ts
- .esm.js: requires .yaml alongside, .d.ts optional
- JSON Schema → TypeScript type converter
- hello-world example workflow
- 63 tests pass, biome clean

Closes #7
小橘 <xiaoju@shazhou.work>
2026-05-06 06:26:14 +00:00
xiaoju 47e8fdf5b3 chore: replace hand-written xxhashjs.d.ts with @types/xxhashjs
小橘 <xiaoju@shazhou.work>
2026-05-06 06:21:46 +00:00
xiaoju dfbba0f58c feat: Phase 4 — fork threads + bun publish verified
- fork-thread.ts: parse .data.jsonl, trim steps by role
- cmd-fork.ts: --from-role <role> or retry last step
- engine: forkFrom lineage tracking, prefilled step replay
- worker: accept steps in run IPC command
- bun publish --dry-run: both packages pass
- 53 tests pass, biome clean

Closes #5
小橘 <xiaoju@shazhou.work>
2026-05-06 05:45:01 +00:00
xiaoju 0becafeb44 feat: Phase 3 — version history/rollback + pause/resume threads
- CLI: history, rollback, pause, resume commands
- Registry: rollbackWorkflowToHistoryHash
- Engine: awaitAfterEachYield hook for pause gate
- Worker: ThreadPauseGate with Promise-based latch
- TCP IPC: bidirectional response for kill/pause/resume
- 44 tests pass, biome clean

小橘 <xiaoju@shazhou.work>
2026-05-06 05:36:33 +00:00
xiaoju 9943f21f5c refactor: WorkflowFn input → ThreadInput, remove threadId from bundle contract
- WorkflowFn first param is now ThreadInput { prompt, steps }
- threadId removed from WorkflowFnOptions and ThreadContext (engine-only)
- createRoleModerator seeds context from input.steps (fork/resume ready)
- New test: pre-filled steps skip already-completed roles

Closes #6
小橘 <xiaoju@shazhou.work>
2026-05-06 05:27:14 +00:00
xiaoju 9a4cec2b2d docs(rfc-001): WorkflowFn input → ThreadInput for fork/resume support
- First param is now { prompt, steps } instead of bare prompt
- steps: [] for new thread, pre-filled for fork/resume
- createRoleModerator naturally handles resume via moderator routing
- No special replay logic needed

小橘 <xiaoju@shazhou.work>
2026-05-06 05:25:00 +00:00
xiaoju 7582a88d6b feat: Phase 2 — Thread lifecycle, execution engine, worker, CLI
- types.ts: START/END, RoleMeta, ThreadContext, Role, Moderator, WorkflowDefinition
- engine.ts: executeThread with JSONL persistence + AbortSignal
- worker.ts: per-bundle process, TCP IPC, kill individual threads
- CLI: run/ps/kill/threads/thread/thread rm commands
- 32 tests pass, biome clean

小橘 <xiaoju@shazhou.work>
2026-05-06 04:59:54 +00:00
xiaoju 01e930df8f docs(rfc-001): add execution model — Role, Moderator, Agent types
Ported from nerve's workflow types. Covers ThreadContext, StartStep,
RoleStep, Moderator (pure router), Role (async actor), AgentFn (LLM adapter),
WorkflowDefinition, and execution flow.

小橘 <xiaoju@shazhou.work>
2026-05-06 04:41:52 +00:00
xiaoju 8939194133 init: bun workspace + RFC-001 workflow engine design
- @uncaged/workflow (core lib) + @uncaged/cli-workflow (CLI)
- RFC-001: full design doc covering storage, threading, CLI

小橘 <xiaoju@shazhou.work>
2026-05-06 04:20:05 +00:00