Skip to content

Commit 4c76dc2

Browse files
committed
chore: update version numbers and improve documentation across multiple files
1 parent e3615f6 commit 4c76dc2

File tree

7 files changed

+88
-32
lines changed

7 files changed

+88
-32
lines changed

PROTOCOL_SPEC.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
> **Canonical Specification** - This document is the authoritative specification for the apcore protocol
44
5-
> Version: 1.0.0-draft
5+
> Version: 1.2.0-draft
66
> Status: Draft Specification (RFC 2119 Conformant)
77
> Stability: Specification content is stable, pending reference implementation verification
8-
> Last Updated: 2026-02-07
8+
> Last Updated: 2026-02-22
99
1010
---
1111

docs/api/context-object.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
2828
from apcore import Executor
2929

3030

31-
@dataclass
31+
@dataclass(frozen=True)
3232
class Identity:
3333
"""Caller identity (human/service/AI generic)"""
3434

@@ -39,7 +39,8 @@ class Identity:
3939
type: str = "user" # user | service | agent | api_key | system
4040

4141
# Role list (ACL engine dependency)
42-
roles: list[str] = field(default_factory=list)
42+
# Implementations SHOULD use immutable collection types (e.g. Python tuple, TypeScript readonly array)
43+
roles: tuple[str, ...] = field(default_factory=tuple)
4344

4445
# Extended attributes (business fields like tenant_id, email)
4546
attrs: dict[str, Any] = field(default_factory=dict)
@@ -68,9 +69,10 @@ class Context:
6869
# Caller identity (ACL engine dependency)
6970
identity: Identity | None = None
7071

71-
# ====== Logging and redaction ======
72+
# ── SHOULD-level members (optional for implementations) ──────────
7273

7374
# Context-aware logger (automatically injects trace_id, module_id, caller_id)
75+
# Level: SHOULD (not MUST). Implementations may provide equivalent functionality via a standalone ContextLogger class.
7476
@property
7577
def logger(self) -> "ContextLogger":
7678
"""Returns a logger that automatically injects context information"""
@@ -633,12 +635,12 @@ from datetime import datetime
633635
import uuid
634636

635637

636-
@dataclass
638+
@dataclass(frozen=True)
637639
class Identity:
638640
"""Caller identity"""
639641
id: str
640642
type: str = "user"
641-
roles: list[str] = field(default_factory=list)
643+
roles: tuple[str, ...] = field(default_factory=tuple)
642644
attrs: dict[str, Any] = field(default_factory=dict)
643645

644646

docs/api/executor-api.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Executor:
3535
def call(
3636
self,
3737
module_id: str,
38-
inputs: dict[str, Any],
38+
inputs: dict[str, Any] | None = None,
3939
context: Context | None = None
4040
) -> dict[str, Any]:
4141
"""
@@ -63,7 +63,7 @@ class Executor:
6363
async def call_async(
6464
self,
6565
module_id: str,
66-
inputs: dict[str, Any],
66+
inputs: dict[str, Any] | None = None,
6767
context: Context | None = None
6868
) -> dict[str, Any]:
6969
"""
@@ -75,6 +75,21 @@ class Executor:
7575
"""
7676
...
7777

78+
async def stream(
79+
self,
80+
module_id: str,
81+
inputs: dict[str, Any] | None = None,
82+
context: Context | None = None
83+
) -> AsyncIterator[dict[str, Any]]:
84+
"""
85+
Stream module output chunk by chunk
86+
87+
Yields partial results as they become available.
88+
Calls the module's stream() method if defined,
89+
otherwise falls back to standard execute().
90+
"""
91+
...
92+
7893
def validate(
7994
self,
8095
module_id: str,

docs/api/module-interface.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,14 +391,15 @@ class SendEmailModule(Module):
391391
from dataclasses import dataclass
392392

393393

394-
@dataclass
394+
@dataclass(frozen=True)
395395
class ModuleAnnotations:
396396
"""Module behavior annotations"""
397397
readonly: bool = False # Read-only, no side effects
398398
destructive: bool = False # Has destructive operations
399399
idempotent: bool = False # Idempotent, safe to call repeatedly
400400
requires_approval: bool = False # Requires human confirmation
401401
open_world: bool = True # Involves external systems
402+
streaming: bool = False # Supports streaming output
402403
```
403404

404405
| Field | Default | Meaning | AI Behavior |
@@ -408,6 +409,7 @@ class ModuleAnnotations:
408409
| `idempotent` | `False` | Repeated calls have no additional side effects | `True` → Safe to retry |
409410
| `requires_approval` | `False` | Requires human confirmation | `True` → Seek consent |
410411
| `open_world` | `True` | Connects to external systems | `True` → May be slow |
412+
| `streaming` | `False` | Supports streaming chunk-by-chunk output | `True` → Read output incrementally |
411413

412414
```python
413415
# Query module - read-only, safe

docs/api/registry-api.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ class Registry:
7373
...
7474

7575
# ============ Schema Query and Export ============
76+
#
77+
# Note: In implementations, these schema methods MAY be provided as
78+
# independent helper functions rather than Registry methods, e.g.:
79+
# get_schema(registry, module_id)
80+
# export_schema(registry, module_id, format=...)
81+
# The Registry interface below defines the recommended convenience
82+
# interface. Implementations may choose standalone function form
83+
# if it better fits their architecture.
7684

7785
def get_schema(self, module_id: str) -> dict | None:
7886
"""Get module Schema (structured dict, for in-program processing)"""
@@ -669,6 +677,8 @@ Steps:
669677

670678
### 9.1 Custom Discoverer
671679

680+
> **Reserved — Not Implemented.** The `set_discoverer()` API below is a reserved design; current SDKs do not support it. Documentation is retained for future reference.
681+
672682
```python
673683
from apcore import Registry, ModuleDiscoverer
674684

@@ -696,6 +706,8 @@ registry.discover()
696706

697707
### 9.2 Module Validator
698708

709+
> **Reserved — Not Implemented.** The `set_validator()` API below is a reserved design; current SDKs do not support it. Documentation is retained for future reference.
710+
699711
```python
700712
from apcore import Registry, ModuleValidator
701713

@@ -723,6 +735,8 @@ registry.discover()
723735

724736
### 9.3 Hot Reload (Development Mode)
725737

738+
> **Reserved — Not Implemented.** The `watch()` / `unwatch()` API below is a reserved design; current SDKs do not support it. Documentation is retained for future reference.
739+
726740
```python
727741
from apcore import Registry
728742

docs/architecture.md

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -413,30 +413,47 @@ Throw ModuleError
413413
apcore/
414414
├── __init__.py # Public API
415415
├── module.py # Module base class
416-
├── registry.py # Registry implementation
416+
├── decorator.py # Module decorator and FunctionModule
417+
├── bindings.py # YAML binding loader for zero-code integration
417418
├── executor.py # Executor implementation
418419
├── context.py # Context definition
419420
├── acl.py # ACL implementation
420-
├── schema.py # Schema utilities
421421
├── errors.py # Exception definitions
422422
├── config.py # Config loading
423423
424-
├── discovery/ # Module discovery
424+
├── registry/ # Module discovery & registration
425425
│ ├── __init__.py
426-
│ ├── discoverer.py # Discoverer interface
427-
│ ├── python.py # Python discoverer
428-
│ └── id_map.py # ID Map handling
426+
│ ├── registry.py # Central Registry class
427+
│ ├── types.py # ModuleDescriptor, DiscoveredModule, DependencyInfo
428+
│ ├── scanner.py # Directory/file scanning
429+
│ ├── validation.py # Module interface validation
430+
│ ├── metadata.py # Module metadata extraction
431+
│ ├── dependencies.py # Dependency resolution & load order
432+
│ ├── entry_point.py # Entry point resolution
433+
│ └── schema_export.py # Schema export helpers
429434
430-
├── validation/ # Validation
435+
├── schema/ # Schema processing
431436
│ ├── __init__.py
432-
│ ├── module.py # Module interface validation
433-
│ └── schema.py # Schema validation
437+
│ ├── types.py # SchemaStrategy, ExportProfile, type definitions
438+
│ ├── loader.py # Schema loading
439+
│ ├── validator.py # Schema validation
440+
│ ├── exporter.py # Schema export (JSON/YAML)
441+
│ ├── ref_resolver.py # $ref resolution
442+
│ ├── strict.py # Strict mode transformation
443+
│ └── annotations.py # x-* annotation handling
434444
435445
├── middleware/ # Middleware
436-
│ ├── __init__.py # Middleware base class + public API
437-
│ ├── logging.py # Logging middleware
438-
│ ├── metrics.py # Metrics middleware
439-
│ └── retry.py # Retry middleware
446+
│ ├── __init__.py # Public API
447+
│ ├── base.py # Middleware base class
448+
│ ├── adapters.py # BeforeMiddleware, AfterMiddleware adapters
449+
│ ├── manager.py # MiddlewareManager pipeline engine
450+
│ └── logging.py # Logging middleware
451+
452+
├── observability/ # Observability
453+
│ ├── __init__.py
454+
│ ├── tracing.py # Distributed tracing
455+
│ ├── metrics.py # Metrics collection
456+
│ └── context_logger.py # Context-aware logging
440457
441458
└── utils/ # Utilities
442459
├── __init__.py
@@ -473,11 +490,14 @@ my-project/
473490

474491
### 5.1 Custom Discoverer
475492

493+
> **Note:** This example shows the conceptual interface pattern. The actual
494+
> Python SDK uses a function-based API (`apcore.registry.scanner.scan_extensions`).
495+
476496
```python
477-
from apcore.discovery import ModuleDiscoverer
497+
from apcore.registry.scanner import scan_extensions
478498

479499

480-
class RemoteDiscoverer(ModuleDiscoverer):
500+
class RemoteDiscoverer:
481501
"""Discover modules from remote service"""
482502

483503
def discover(self, config: dict) -> list[tuple[str, Type[Module]]]:
@@ -492,15 +512,18 @@ class RemoteDiscoverer(ModuleDiscoverer):
492512

493513
### 5.2 Custom Validator
494514

515+
> **Note:** This example shows the conceptual interface pattern. The actual
516+
> Python SDK uses a function-based API (`apcore.registry.validation.validate_module`).
517+
495518
```python
496-
from apcore.validation import ModuleValidator
519+
from apcore.registry.validation import validate_module
497520

498521

499-
class StrictValidator(ModuleValidator):
522+
class StrictValidator:
500523
"""Strict module validator"""
501524

502525
def validate(self, module_class: Type[Module]) -> list[str]:
503-
errors = super().validate(module_class)
526+
errors = validate_module(module_class)
504527

505528
# Custom rules
506529
if len(module_class.tags) == 0:
@@ -643,7 +666,7 @@ def sync_caller():
643666
- **ACL check timeout**: independent timing (default 1 second)
644667
- Timing starts from first `before()` middleware
645668

646-
**Cancellation Strategy:**
669+
**Cancellation Strategy:** **Future (Not Implemented)** — The following is a planned design; current SDKs have not yet implemented this.
647670

648671
1. **Cooperative cancellation** (recommended):
649672
- Module checks `context.cancel_token.is_cancelled()` and actively exits
@@ -673,7 +696,7 @@ See [PROTOCOL_SPEC §11.7.4 Timeout Enforcement](../PROTOCOL_SPEC.md#1174-timeou
673696

674697
- `context.data` across entire call chain is **the same** dict object (reference sharing)
675698
- Parent module modifications to `context.data` visible to child modules, and vice versa
676-
- When `derive()` creates new Context, `data` field copies reference (not deep copy)
699+
- When `child()` creates new Context, `data` field copies reference (not deep copy)
677700

678701
**Isolation:**
679702

@@ -688,7 +711,7 @@ context1 = Context(data={})
688711
executor.call("module_a", {}, context1)
689712
# module_a internally:
690713
context.data["key"] = "value_a"
691-
sub_context = context.derive("module_b")
714+
sub_context = context.child("module_b")
692715
executor.call("module_b", {}, sub_context)
693716
# module_b reads "value_a" (reference sharing)
694717

docs/spec/conformance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ implementation:
490490
name: "apcore-python" # Implementation name
491491
version: "0.1.0" # Implementation version
492492
language: "python" # Implementation language
493-
spec_version: "1.0.0-draft" # Corresponding PROTOCOL_SPEC version
493+
spec_version: "1.2.0-draft" # Corresponding PROTOCOL_SPEC version
494494
maintainer: "AI Partner Up" # Maintainer
495495
repository: "https://github.com/aipartnerup/apcore-python" # Repository address
496496

0 commit comments

Comments
 (0)