Skip to content

feat: add four agent packages + knowing-state-sdk + AtomDirective schema#74

Closed
Wescome wants to merge 7 commits into
mainfrom
feat/agent-infrastructure-packages
Closed

feat: add four agent packages + knowing-state-sdk + AtomDirective schema#74
Wescome wants to merge 7 commits into
mainfrom
feat/agent-infrastructure-packages

Conversation

@Wescome

@Wescome Wescome commented Jun 5, 2026

Copy link
Copy Markdown
Owner

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-001

Schema addition

  • packages/schemas/src/atom-directive.ts — canonical AtomDirective schema 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: AtomDirective schema and Divergence severity classification policy (DECISIONS N+2).

Decisions recorded

  • DECISIONS N+2: Divergence severity classification (blocking / advisory / informational)
  • DECISIONS N+3: @factory/knowing-state-sdk standalone package placement

claude added 2 commits June 5, 2026 17:22
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).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +307 to +308
// Read last 200 events (configurable)
const events = await this.readRecentEvents(200)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +372 to +380
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' },
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +188 to +190
if (spec.exitCode !== undefined) {
const dr = body.detectorResults.find(r => r.detectorId === spec.detectorId)
if (dr?.fired) fired = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +219 to +233
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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

claude added 5 commits June 5, 2026 17:45
…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
@Wescome

Wescome commented Jun 10, 2026

Copy link
Copy Markdown
Owner Author

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.

@Wescome Wescome closed this Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants