Commit Graph

41 Commits

Author SHA1 Message Date
df3dd82572 feat: add Safe Exit protocol for blocked tasks under new task file convention
Agents no longer commit task files, so when an agent safe-exits:
- Agent notifies coordinator with detailed blocking message (what happened, what was tried, suggested fix)
- Agent commits any partial source code progress and pushes
- Coordinator updates task file on main with status: blocked and the reason
- Coordinator attempts resolution, spawns new agent if resolved

Also removed stale 'task file conflicts' from merge workflow since
agents no longer commit task files.
2026-05-11 11:38:52 +00:00
1d2a3c2133 feat: agents stop committing task files — coordinator owns task status on main
Agents no longer commit task files (tasks/*.md) to their feature branches.
This eliminates the highest-frequency merge conflict category (parallel
agents committing metadata to the same file set). The coordinator updates
task status on main after merging source code changes.

Implementation specialist changes:
- Removed 'Update Task' workflow step (status/summary updates)
- Completion summary now included in worktree notify message
- Simplified Safe Exit (no task file commit step)
- Added 'do not commit task files' instruction to commit step

Coordinator changes:
- Added Task File Handling section with coordinator ownership model
- Updated spawn prompt template to include task file convention
- Added post-merge task status update step
2026-05-11 11:37:32 +00:00
30ef54b337 docs: update coordinator agent spec with lessons from first implementation round 2026-05-11 11:25:32 +00:00
933b80d7a6 docs: remove ADR-006 drift tables, finalize all doc statuses to stable 2026-05-11 03:34:31 +00:00
f534004615 feat(unified-env-remove-callmap): clean up 'direct mode' references in env tests
Remove outdated 'direct mode' terminology from test descriptions
since there is now only one invocation path (registry.execute).
The callMap option was removed from buildEnv() in previous tasks.
2026-05-11 03:29:28 +00:00
95d9b95d13 feat(unified-callhandler): simplify CallHandler to delegate to registry.execute()
- Remove separate spec lookup, handler lookup, access control, and input validation from buildCallHandler
- Call registry.execute() directly; access control enforced via execute() (trusted not set)
- On error, look up spec for errorSchemas and pass to mapError()
- Make callMap required in CallHandlerConfig (no longer optional)
- Update tests: remove no-callMap tests, use callMap for all handler tests
- Add test for mapError with spec errorSchemas
- All 226 tests passing
2026-05-11 03:19:26 +00:00
ac94ac59d8 Merge unified-execute-access-control: resolve doc conflicts, keep ADR-006 changes 2026-05-11 03:08:33 +00:00
e138866fcd feat(unified-execute): implement ADR-006 unified invocation path with access control
- Add access control to registry.execute(): checks requiredScopes, requiredScopesAny,
  and resourceType/resourceAction; rejects with ACCESS_DENIED when identity required
  but absent; skips when context.trusted is true
- Add trusted field to OperationContext schema (internal, set by buildEnv for
  nested calls to skip redundant scope checks)
- Simplify CallHandler to thin adapter: delegates to registry.execute() instead of
  duplicating lookup, validation, and access control
- Remove callMap option from buildEnv(): always uses execute(), propagates context
  with trusted: true for nested calls
- Add access control to subscribe(): same default-deny logic as execute()
- Change execute() to throw CallError instead of plain Error for not found,
  no handler, and validation errors
- Export checkAccess from call.ts and index.ts for external use
- Remove CallMap type export, update EnvOptions
- Update architecture docs: api-surface.md, call-protocol.md,
  ADR-006 status to implemented, source vs spec drift sections
- All 228 tests passing
2026-05-11 03:04:19 +00:00
ddc0607b90 docs: clean up ADR-005 architecture docs after envelope implementation
Remove stale ADR-005 drift tables across all architecture docs since
ResponseEnvelope types, factories, detection, and integration points
are now fully implemented in source code. Key changes:

- api-surface.md: Remove ADR-005 drift table (all items implemented),
  retain ADR-006 drift table without execute() return type (now done)
- call-protocol.md: Remove ADR-005 drift table, update ADR-006 table,
  fix CallHandlerConfig to show callMap? (current source)
- adapters.md: Remove 'current source state' and 'implementation
  changes needed' tables for from_mcp and from_openapi, replace with
  current-accurate descriptions of envelope behavior
- response-envelopes.md: Remove 'current source state' blocks,
  update migration checklist to show all code changes completed
- 005-response-envelopes.md: Change status from Draft to Implemented
- 006-unified-invocation-path.md: Update Prerequisites section to note
  ADR-005 is now implemented
- build-distribution.md: Add response-envelope.ts to source layout
- architecture.md: Add response-envelopes.md link and ADR-005/006
  entries to design decisions table
- README.md: Add response-envelopes.md to documents table
- Update last_updated dates on all changed docs
2026-05-11 02:55:13 +00:00
d74b750ecb feat(env): complete envelope integration for buildEnv - propagate identity in call protocol mode and add comprehensive tests
- Pass context.identity through to callMap.call() in call protocol mode
  for proper identity propagation in nested operation calls
- Add identity propagation test coverage for both with-identity and
  without-identity scenarios
- Add test for parentRequestId propagation through callMap
- Add test for PendingRequestMap as callMap integration
- Add test for pre-built ResponseEnvelope pass-through in direct mode
- Add test for Value.Cast normalization via execute in direct mode
- Add test for empty registry, namespace grouping, and local source
  metadata verification
- All 216 tests passing, build and lint clean
2026-05-11 02:37:44 +00:00
7a25cb9c0c Clean up stale worktree from index 2026-05-11 02:24:02 +00:00
b63c5ce3de Merge registry-envelope-integration into main (resolve conflicts with call-envelope-integration) 2026-05-11 02:23:52 +00:00
3150a49578 feat(registry-envelope-integration): update execute(), call, subscribe, env to return ResponseEnvelope
- OperationRegistry.execute() now returns Promise<ResponseEnvelope<TOutput>>
- Applies shared result pipeline: detect → wrap → normalize → validate
- Uses KindGuard.IsUnknown() to check if Value.Cast should be applied
- PendingRequestMap.call() returns Promise<ResponseEnvelope>
- PendingRequestMap.respond() validates envelope via isResponseEnvelope()
- CallHandler captures handler result, wraps, normalizes, validates, publishes
- CallEventSchema call.responded.output changed to ResponseEnvelopeSchema
- subscribe() yields ResponseEnvelope with isResponseEnvelope() passthrough
- OperationEnv inner functions return Promise<ResponseEnvelope>
- Tests updated for all new return types and behaviors
- 171 tests passing, build and lint clean
2026-05-11 02:19:05 +00:00
58a4d06be0 Merge branch 'feat/call-envelope-integration' 2026-05-11 02:15:59 +00:00
95d421d621 docs: update task status to completed for call-envelope-integration 2026-05-11 02:15:14 +00:00
bf6d07938c feat(call-envelope-integration): integrate ResponseEnvelope into call protocol
- CallEventSchema['call.responded'].output changed from Type.Unknown() to ResponseEnvelopeSchema
- PendingRequestMap.respond() now validates output with isResponseEnvelope(), throws on raw values
- PendingRequestMap.call() return type changed from Promise<unknown> to Promise<ResponseEnvelope>
- CallHandler captures handler return value instead of discarding it
- CallHandler applies result pipeline: detect envelope → wrap with localEnvelope → normalize with Value.Cast → validate with collectErrors
- CallHandler publishes call.responded via callMap.respond() with the envelope
- CallHandler publishes call.error via callMap.emitError() when callMap is provided (instead of re-throwing)
- CallHandlerConfig changed from eventTarget? to callMap? (PendingRequestMap)
- Adapter handlers pass through via isResponseEnvelope() detection (mcpEnvelope/httpEnvelope)
- All 189 tests passing, including 23 new tests for envelope behavior
2026-05-11 02:14:01 +00:00
6290feffb0 feat(subscribe): wrap yields in ResponseEnvelope
- Change subscribe() return type to AsyncGenerator<ResponseEnvelope, void, unknown>
- Check isResponseEnvelope() on each yielded value: pass through if already an envelope
- Wrap raw values with localEnvelope(value, operationId) with fresh timestamp per yield
- Preserve generator cleanup (generator.return()) in finally block
- Preserve existing spec/handler not-found error behavior
- Add 13 tests covering wrapping, passthrough, timestamps, mixed yields, early termination
2026-05-11 02:06:20 +00:00
e111e1b4d8 Merge branch 'feat/mcp-envelope-integration' 2026-05-11 02:00:22 +00:00
f833fe3d53 chore: update mcp-envelope-integration task status to completed 2026-05-11 01:59:52 +00:00
b0283aa662 feat(mcp-envelope-integration): update from_mcp adapter to use mcpEnvelope, structuredContent, and outputSchema extraction
- Add mapMCPContentBlocks() helper mapping SDK ContentBlock[] to MCPContentBlock[]
- Extract tool.outputSchema via FromSchema() when present, fall back to Type.Unknown()
- Handler returns mcpEnvelope() with structured/legacy data path
- structuredContent preferred as data when present, Value.Cast() when outputSchema is known
- isError: true wrapped in envelope meta, NOT thrown
- Transport-level config errors throw CallError
- Unknown MCP content block types fall back to { type: 'text', text: JSON.stringify(block) }
- Add 20 tests for mapMCPContentBlocks and envelope detection
2026-05-11 01:59:30 +00:00
e58d95a6dc Merge branch 'feat/docs-cleanup-bugs' 2026-05-11 01:59:30 +00:00
4616faa084 chore(docs-cleanup-bugs): mark task as completed 2026-05-11 01:59:22 +00:00
24255c6c52 feat(docs-cleanup-bugs): remove resolved Bugs section from call-protocol.md
Remove the Bugs subsection from Source vs. Spec Drift since both bugs
(checkAccess resource bypass and PendingRequestMap type name conflict)
have been resolved. Update intro sentence to remove Bug mention.
ADR-005 and ADR-006 drift tables remain intact.
2026-05-11 01:59:07 +00:00
dc34eb29ea Merge branch 'feat/response-envelope-tests' 2026-05-11 01:57:06 +00:00
1d754b7d0a feat(response-envelope): add comprehensive tests for envelope types, factories, detection, schemas, and unwrap 2026-05-11 01:56:32 +00:00
854d5c7f3f Merge branch 'feat/openapi-envelope-integration' 2026-05-11 01:55:26 +00:00
3f6bfe4972 Merge branch 'feat/response-envelope-types' 2026-05-11 01:55:23 +00:00
f3dac704a7 Merge branch 'feat/bug-pendingrequestmap-type-conflict' 2026-05-11 01:55:20 +00:00
9f4d2fb5f7 fix(PendingRequestMap): resolve type name conflict between env.ts interface and call.ts class
- Remove PendingRequestMap interface from env.ts (had reduced signature missing deadline, identity typed as unknown)
- Add CallMap interface in env.ts with full call() signature matching the class
- Update EnvOptions.callMap to use CallMap type
- Export PendingRequestMap class directly (remove PendingRequestMapClass alias)
- Export CallMap type from index.ts instead of old PendingRequestMap interface
2026-05-11 01:54:04 +00:00
c2c640f480 feat(openapi-envelope): update from_openapi handler to use httpEnvelope and CallError
Handler returns httpEnvelope(data, { statusCode, headers, contentType }) instead of raw response data.
HTTP errors throw CallError('EXECUTION_ERROR', ...) instead of plain Error.
Added tests for envelope wrapping and CallError behavior.
2026-05-11 01:52:09 +00:00
ac28c9308c fix(checkAccess): deny access when resourceType set but identity.resources undefined
The resource access check in checkAccess() was bypassed when identity.resources
was undefined because the condition  evaluated to false, falling through to .

Changed to  with an explicit
 check inside the block, implementing
default-deny semantics per ADR-006.

Added 7 test cases covering:
- undefined resources with resourceType set (denied)
- empty resources with resourceType set (denied)
- non-matching resource type (denied)
- matching type but wrong action (denied)
- matching type and action (granted)
- no resourceType/resourceAction set (granted)
- matching resources with extra scopes (granted)
2026-05-11 01:50:12 +00:00
15a558bace feat(response-envelope-types): add ResponseEnvelope types, schemas, factories, detection, and unwrap 2026-05-11 01:47:26 +00:00
b6c2b2c186 Add ADR-006 unified invocation path and source-vs-spec drift tables
ADR-006: Unify on registry.execute() as the single invocation entry point.
Call protocol becomes internal transport for cross-process routing.
CallHandler calls execute() instead of reimplementing lookup/validation.
Access control enforcement in execute() with trusted flag for nested calls.
Default-deny: reject when requiredScopes non-empty and identity absent.

Source-vs-spec drift tables added to call-protocol.md and api-surface.md,
documenting all gaps between architecture docs and current source:
- ADR-005 gaps (envelope types, pipeline, factory functions)
- ADR-006 gaps (unified invocation, access control, CallHandler refactor)
- Two bugs: checkAccess() resource bypass when identity.resources is
  undefined, and PendingRequestMap type/class naming conflict
2026-05-10 09:30:22 +00:00
51f233582d Align call-protocol.md and api-surface.md with envelope model
Remove supersession note from response-envelopes.md — both dependent
docs now reflect the ResponseEnvelope system. Key changes:

- call-protocol.md: CallHandler wraps and publishes (not handlers),
  call.responded.output uses ResponseEnvelopeSchema, respond() enforces
  envelope guard, call() resolves ResponseEnvelope, subscribe() yields
  ResponseEnvelope, references shared result pipeline
- api-surface.md: execute() returns Promise<ResponseEnvelope<TOutput>>,
  OperationEnv functions return Promise<ResponseEnvelope>, CallHandler
  calls handler directly and applies shared pipeline, respond() requires
  ResponseEnvelope, added Response Envelope Types and Utilities sections
- response-envelopes.md: removed supersession note, added Shared Result
  Pipeline section (detect→wrap→normalize→validate), unified execute()
  and CallHandler integration points to reference shared pipeline,
  updated migration checklist to mark doc changes complete
2026-05-10 08:37:40 +00:00
81f89e0f6c Restructure response envelopes architecture: split ADR from spec, add Value.Cast composability, document implementation gaps
- Split monolithic 680-line response-envelopes.md into focused ADR-005
  (decisions/005-response-envelopes.md, 152 lines) and specification
  (response-envelopes.md, 441 lines)
- ADR-005: consolidate 10 inline ADRs into coherent decision record with
  rationale for data+meta envelope shape, handler responsibility shift,
  string discriminant detection, and composability analysis
- Spec: types, factory functions, integration points, constraints, migration
  checklist, and open questions
- Add MCP outputSchema extraction (2025-06-18+ spec) with FromSchema
  conversion and<Value.Cast()> normalization for structuredContent
- Add current-source-vs-spec implementation gap tables to registry, call,
  mcp adapter, and openapi adapter integration points
- Update adapters.md: from_mcp outputSchema extraction, structuredContent
  handling, isError non-throw behavior, Value.Cast() for data normalization
- Add open questions: serving directionality, JSON.stringify in MCP content,
  outputSchema extraction completeness, respond() visibility
- Note: existing call-protocol.md and api-surface.md describe pre-envelope
  behavior; this spec supersedes them until updated per migration checklist
2026-05-10 07:56:27 +00:00
a7e6cc94c7 Add response envelopes architecture spec (ADR-005 through ADR-014)
Introduce ResponseEnvelope as a first-class concept for uniform operation
result handling across MCP, OpenAPI, and local adapters. Key decisions:

- ResponseEnvelope<T> wraps every result with typed metadata
  (LocalResponseMeta, HTTPResponseMeta, MCPResponseMeta)
- CallHandler becomes sole publisher of call.responded (handler
  responsibility shift from publish-to-return)
- Envelope detection via closed-set string discriminant
  (isResponseEnvelope) — no Symbols, JSON-serializable
- MCP isError:true no longer throws; wraps in envelope with
  meta.isError flag preserving error content for consumers
- outputSchema validates envelope.data, not the full envelope
- PendingRequestMap.respond() validates envelope at runtime
- Factory functions (localEnvelope, httpEnvelope, mcpEnvelope)
  ensure consistent construction
- Breaking change: execute() returns ResponseEnvelope<TOutput>,
  call.responded.output is ResponseEnvelopeSchema
- No Client abstraction yet (ADR-014)
2026-05-10 04:58:05 +00:00
d0017df2bf Update architecture docs for handler separation and pubsub API changes
- api-surface.md: Updated registry API table (registerSpec, registerHandler,
  getHandler, separated spec/handler storage), OperationSpec description,
  IOperationDefinition marked as convenience type, adapter return types
- call-protocol.md: Added pubsub EventEnvelope unwrapping details,
  subscribe(type, id) 2-arg API, handler separation in buildCallHandler
  and subscribe(), handler separation section
- adapters.md: Updated return types (OperationSpec & { handler }),
  scanner validates against OperationSpecSchema, new module shape examples
  showing spec-only and spec+handler patterns, typemap mention
- README.md: Core principle updated for spec/handler separation
- build-distribution.md: Updated pubsub dep description, registry.ts description
- AGENTS.md: Updated key points, source layout, provenance status
2026-05-09 08:34:41 +00:00
4f11f8e7a0 Separate handler from spec in OperationRegistry, update pubsub API
- Split OperationRegistry into separate specs and handlers maps
- Add registerSpec(), registerHandler(), getHandler() methods
- register() still accepts IOperationDefinition (backward compatible)
- execute() now requires both spec and handler, throws if missing
- Update @alkdev/pubsub integration for v0.1.0 API:
  - subscribe(type, id) now requires id parameter (use  for all events)
  - publish(type, id, payload) now requires 3 args
  - Events unwrapped from EventEnvelope via .payload
- Update buildCallHandler to use getSpec() + getHandler() separately
- Update subscribe.ts to use getHandler()
- Update buildEnv to use getAllSpecs() instead of list()
- Update scanner to validate against OperationSpecSchema
- Update from_mcp and from_openapi to use OperationSpec & { handler } types
- Remove OperationDefinitionSchema from public exports
- Add 7 new registry tests for handler separation
2026-05-09 08:25:59 +00:00
c5979ecd63 added agent defs 2026-05-08 18:09:02 +00:00
29f0dd7af0 Initial package implementation: operations registry, call protocol, and adapters
Extracted from alkhub_ts packages/core/operations/ and packages/core/mcp/.
- Runtime-agnostic (injected fs/env deps, no Deno globals)
- Direct @logtape/logtape import instead of logger wrapper
- PendingRequestMap with pubsub-wired call protocol
- Peer-dep isolation for MCP adapter (sub-path export)
- Schema const naming convention (XSchema + X type alias)
- 68 tests passing, build + lint + test all green
2026-04-30 12:34:26 +00:00
9c41f683ee init 2026-04-30 09:39:35 +00:00