feat: add four agent packages + knowing-state-sdk + AtomDirective schema#74
feat: add four agent packages + knowing-state-sdk + AtomDirective schema#74Wescome wants to merge 7 commits into
Conversation
Packages added: - @factory/knowing-state-sdk — domain-agnostic Knowing-State Prosthesis SDK Provisional name; will move to @koales/knowing-state-sdk (DECISIONS N+3) - @factory/mediation-agent — per-repo Knowing-State Prosthesis DO Append-only event log, Bead graph flush, Verification-Process hosting SPEC-MEDIATION-AGENT-DO-001 v2.0 - @factory/commissioning-agent — per-repo spec-execution governance Worker Commission flow, polling, Hypothesis formation, Amendment proposal SPEC-COMMISSIONING-AGENT-001 - @factory/conducting-agent — execution substrate interface Gas City session dispatch, AtomDirective execution, trace reporting SPEC-CONDUCTING-AGENT-001 - @factory/architect-agent — Factory-wide governance singleton DO D1 patch governance, D2 CRP resolution, D3 vertical slicing, D4 pipeline config SPEC-ARCHITECT-AGENT-DO-001 Schema addition: - packages/schemas/src/atom-directive.ts — canonical AtomDirective schema Closes shared blocker across all four agent specs SPEC-CONDUCTING-AGENT-001 §1.2 All implementations are stubs with // TODO: markers aligned to spec sections. Two shared blockers closed: AtomDirective schema, Divergence severity policy (DECISIONS N+2).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59afd295ac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,21 @@ | |||
| { | |||
| "name": "@factory/architect-agent", | |||
There was a problem hiding this comment.
Update the lockfile for the new packages
This commit adds new workspace package manifests and dependencies, but pnpm-lock.yaml has no importers for packages/architect-agent, packages/commissioning-agent, packages/conducting-agent, packages/knowing-state-sdk, or packages/mediation-agent. I checked .github/workflows/ci.yml, and both CI jobs run pnpm install --frozen-lockfile (lines 28 and 66), so the install will fail before typecheck/tests whenever this commit is built.
Useful? React with 👍 / 👎.
| // Read last 200 events (configurable) | ||
| const events = await this.readRecentEvents(200) |
There was a problem hiding this comment.
Replay enough events before the first snapshot
Before the first snapshot is written at the default 500 events, reconstructState() starts from emptyState() but only replays the last 200 events. In any active repo that records more than 200 traces/divergences after commissioning but before event 500, the original CommissionEvent and LifecycleEvent fall out of this window, so /dispatch reconstructs an UNINITIALIZED/empty policy state and blocks or completes instead of continuing execution.
Useful? React with 👍 / 👎.
| private stateFromSnapshot(s: SnapshotPayload): RepoState { | ||
| return { | ||
| ...this.emptyState(), | ||
| lifecycleState: s.lifecycleState as AgentLifecycleState, | ||
| workGraphVersion: s.workGraphVersion, | ||
| openDivergenceIds: s.openDivergenceIds, | ||
| coherenceVerdict: { value: s.coherenceVerdict as 'favorable' | 'unfavorable' | 'pending' }, | ||
| fidelityVerdict: { value: s.fidelityVerdict as 'favorable' | 'unfavorable' | 'pending' }, | ||
| } |
There was a problem hiding this comment.
Preserve commissioned state in snapshots
When a snapshot exists, this starts from emptyState() and restores only lifecycle/version/verdict/divergence fields, dropping policyBeadId, atoms, detectorSpecs, agentsMd, lastCommissionAt, and lastFlushSeq from the commissioned state. After the first snapshot, a repo can still look ACTIVE and coherent, but /dispatch sees an empty atoms array and returns complete, so execution stops even though the commission data was previously present in the event log.
Useful? React with 👍 / 👎.
| if (spec.exitCode !== undefined) { | ||
| const dr = body.detectorResults.find(r => r.detectorId === spec.detectorId) | ||
| if (dr?.fired) fired = true |
There was a problem hiding this comment.
Guard traces that omit detector results
When any detector spec with an exitCode is configured, this dereferences body.detectorResults.find(...), but the Conducting Agent trace it posts does not include detectorResults in either the normal trace object or the invalid-directive trace. In that scenario /trace throws before returning recorded, losing the trace and preventing divergence handling; either make the field optional here or include it in the emitted trace payload.
Useful? React with 👍 / 👎.
| const crpQueue = (await this.state.storage.get<{ items: { status: string }[] }>('crp:queue')) ?? { items: [] } | ||
| const patches = (await this.state.storage.get<PatchRecord[]>('patches:active')) ?? [] | ||
|
|
||
| return Response.json({ | ||
| factoryLifecycleState: state.lifecycleState, | ||
| activeRepoCount: state.activeRepos.length, | ||
| repoHealthBreakdown: { | ||
| healthy: state.activeRepos.filter(r => r.healthStatus === 'healthy').length, | ||
| degraded: state.activeRepos.filter(r => r.healthStatus === 'degraded').length, | ||
| suspended: state.activeRepos.filter(r => r.healthStatus === 'suspended').length, | ||
| unknown: state.activeRepos.filter(r => r.healthStatus === 'unknown').length, | ||
| }, | ||
| openEscalationCount: 0, // TODO: read from ArangoDB | ||
| activePatchCount: patches.filter(p => p.status === 'propagating').length, | ||
| pendingCrpCount: crpQueue.items?.filter(i => i.status === 'pending').length ?? 0, |
There was a problem hiding this comment.
Count CRPs using the stored queue shape
handleCRP() stores crp:queue as a plain CRPItem[], but the health endpoint reads the same key as { items: [...] }. After any CRP is queued, crpQueue.items is undefined for the stored array, so pendingCrpCount always reports 0 and factory health hides unresolved CRPs.
Useful? React with 👍 / 👎.
…ive.ts Replace manual SuccessConditionType declaration with z.infer-based pattern. The ZodLazy wrapper's _input type was incompatible with the manually declared union because z.default() makes fields optional in input types. Using a base discriminated union + lazy recursive extension fixes the TS2322 error.
…Type<T,_,T> constraint z.default() makes fields optional in Zod input types (number | undefined) but the manual SuccessConditionType declaration requires them to be required. Removing z.default() from variant fields makes input and output types identical, satisfying the recursive ZodType<T, ZodTypeDef, T> constraint. Callers should provide explicit values (e.g. expectedCode: 0) rather than relying on defaults within SuccessCondition.
Repo tsconfig has verbatimModuleSyntax enabled. All type-only re-exports across the five new packages updated to use 'export type' syntax.
- Spread sandboxOutputRef conditionally to satisfy exactOptionalPropertyTypes - Replace lastTrace! non-null assertion with explicit guard
|
Superseded by feat/ksp-implementation (#86). The agent stubs were ArangoDB-bound pre-KSP design with no salvageable implementation — the real CoordinatorDO, bead graph, and loop closure are now live. Route surfaces noted for future agent work. |
Summary
Adds the Factory I-layer runtime governance stack as five new packages.
Packages added
@factory/knowing-state-sdk— domain-agnostic Knowing-State Prosthesis SDK. Provisional name; will move to@koales/knowing-state-sdk(DECISIONS N+3)@factory/mediation-agent— per-repo Knowing-State Prosthesis DO. Append-only event log, Bead graph flush to ArangoDB, Verification-Process hosting. SPEC-MEDIATION-AGENT-DO-001 v2.0@factory/commissioning-agent— per-repo spec-execution governance Worker. Commission flow, polling loop, Hypothesis formation (Claude Opus), Amendment proposal. SPEC-COMMISSIONING-AGENT-001@factory/conducting-agent— execution substrate interface. Gas City session dispatch, AtomDirective execution, trace reporting. SPEC-CONDUCTING-AGENT-001@factory/architect-agent— Factory-wide governance singleton DO. D1 patch governance, D2 CRP resolution, D3 vertical slicing, D4 pipeline config. SPEC-ARCHITECT-AGENT-DO-001Schema addition
packages/schemas/src/atom-directive.ts— canonicalAtomDirectiveschema closing the shared blocker across all four agent specs (SPEC-CONDUCTING-AGENT-001 §1.2)Status
All implementations are stubs with
// TODO:markers aligned to spec section references. Two shared blockers closed:AtomDirectiveschema and Divergence severity classification policy (DECISIONS N+2).Decisions recorded
@factory/knowing-state-sdkstandalone package placement