Implements the three-tag TDD bug-capture system in Robot Framework via a
Listener v3 module, paralleling the Behave implementation. Tests tagged
tdd_expected_fail that fail have their result inverted to PASS (bug still
exists); tests that unexpectedly pass are inverted to FAIL with guidance.
Addresses all 15 findings from code review (PR !673, reviewer hamza.khyari):
P2 fixes:
- Added idempotency guard (_processed_tests set) to prevent double-inversion
when the listener is loaded twice in the same process.
- Rewrote normal-test-unaffected check to run alongside a tdd_expected_fail
fixture in a single Robot invocation, proving the listener is loaded and
selectively applies rather than being a tautological pass.
P3 fixes:
- Added output.xml existence guard with clear diagnostics in _run_fixture.
- Documented intentional use of data.tags (static definition) vs result.tags
(runtime-modifiable) in end_test docstring.
- Added SKIP status test fixture and integration test case.
- Added message content assertion in cmd_expected_fail_inverted.
- Tightened substring assertions to match specific error text.
- Added tdd_expected_fail-alone fixture (both companions missing).
- Added close() hook to clear _validation_errors and _processed_tests.
- Simplified _run_fixture return type to tuple[str, str].
- Changed listener path resolution from CWD-relative to __file__-relative
in noxfile.py (integration_tests, slow_integration_tests, e2e_tests).
P4 fixes:
- Added __all__ declaration to helper module.
- Changed module docstring from "mirroring" to "paralleling".
- Added comment documenting accepted XML parsing risk (self-generated XML).
Additional fixes:
- Increased M4 E2E plan-tree test timeout from 30s to 120s (pre-existing
timeout failure unrelated to this feature).
Quality gates (post-rebase onto latest master):
- nox -s lint: PASS
- nox -s typecheck: PASS (0 errors)
- nox -s unit_tests: PASS (10,700 scenarios)
- nox -s integration_tests: PASS (1,505 tests)
- nox -s coverage_report: PASS (97.9% >= 97% threshold)
- nox -s benchmark: PASS
- nox -s docs: PASS
- nox -s build: PASS
- nox -s security_scan: PASS
- nox -s dead_code: PASS
ISSUES CLOSED: #628
Implements AuditEventSubscriber that subscribes to all 9 security-relevant
EventType members and persists redacted audit entries via AuditService.record().
Key components:
- AuditEventSubscriber: bridges EventBus and AuditService (SEC7)
- SECURITY_EVENT_MAP: maps EventType enum to audit type strings
- Redaction via redact_dict() on event details before persistence
- Graceful error handling: failures logged, never propagated
Post-review fixes applied:
- BUG-1: Remove dead correlation_id null-check guard (DomainEvent.correlation_id
is always non-None via ULID default_factory)
- SEC-2: Redact exception messages in warning logs via redact_value() to prevent
potential leakage of sensitive internal state (e.g. DB connection strings)
- PERF-3: Pre-generate unique DomainEvent instances in ASV benchmark setup to
avoid skew from reusing a single frozen object
- Wire event_bus from the DI container into CorrectionService (plan.py),
ConfigService (config.py, skill.py x2, server.py), and
PersistentSessionService (session.py) at their CLI construction sites.
Closes#581
Implement the UKOIndexer service that produces UKO triples from resources
using pluggable domain-specific analyzers, wraps each triple with provenance
metadata, and simultaneously indexes into text, vector, and graph backends.
Key design decisions and components:
- UKOIndexer orchestrates the full index lifecycle: add_resource,
update_resource (remove-then-add), remove_resource, and maintenance
triggers. Each operation fires lifecycle hooks (on_indexed, on_removed,
on_error) so callers can observe progress.
- Analyzer selection is pluggable via ContentAnalyzer protocol. The indexer
accepts a registry mapping resource types to analyzers. PythonAnalyzer
and MarkdownAnalyzer are provided as built-in implementations.
- LocationContentReader protocol abstracts file I/O with a base_dir
parameter for path-traversal prevention (post-resolve validation rejects
paths escaping the base directory and non-regular files).
- UKOTriple model includes a @model_validator ensuring at least one of
object_uri or object_value is populated, preventing empty triples at
construction time.
- Triple removal uses scoped deletion via uko:sourceResource predicate to
avoid shared-subject collision — only triples originating from the
specific resource are removed, not all triples for a shared subject.
- _resource_subjects.pop is deferred until after all backend removal
operations succeed, preventing inconsistent state on partial failure.
- analyzer.analyze() is wrapped in try/except so that analyzer errors
produce an IndexResult with error details rather than propagating
exceptions to callers.
- All lifecycle hook calls are guarded via _fire_on_indexed,
_fire_on_removed, and _fire_on_error helpers that catch and log hook
exceptions without disrupting the indexing pipeline.
- max_triples parameter (default 50,000) bounds analyzer output size to
prevent runaway resource consumption.
- ResourceFileWatcher monitors filesystem paths via watchdog and triggers
re-indexing callbacks on file changes with configurable debouncing.
Emits RESOURCE_MODIFIED domain events via EventBus when file changes
are detected. Debounce timers coalesce rapid edits into a single
callback invocation. Thread-safe design with daemon threads for clean
shutdown.
- SearchResult.__post_init__ validates score is in [0.0, 1.0], correctly
rejecting NaN values.
- Placeholder embedding uses [1.0] instead of [float(len(content))] to
avoid leaking content size information.
- isinstance check on graph_backend ensures GraphIndexBackend protocol
compliance at runtime.
- Test doubles extracted to features/mocks/uko_indexer_mocks.py for reuse
across BDD steps and Robot helpers.
Spec reference: Architecture > ACMS > Real-time Index Synchronization
(specification.md lines ~43205-43300).
ISSUES CLOSED: #578
ActorRegistry._actor_name() built names via f"{provider}/{model}", which
produced names with multiple slashes when providers included models
containing "/" (e.g. OpenRouter's "anthropic/claude-sonnet-4-20250514").
The resulting name violated the spec pattern ^[a-z0-9_-]+/[a-z0-9_-]+$
and triggered a ValidationError during actor upsert.
Now sanitises both provider and model components by replacing "/" with "-"
and lowercasing, so multi-slash provider models no longer break actor
listing.
Includes 6 Behave BDD regression scenarios (covering zero-provider,
multi-slash, consecutive-slash, leading-slash, and name-validation
cases), Robot Framework integration smoke tests, and ASV benchmarks.
ISSUES CLOSED: #592
Behave BDD scenarios (3) tagged @tdd_bug @tdd_bug_592 @tdd_expected_fail
exercise the real ActorRegistry._actor_name() code path with a provider
whose default model contains '/' separators. The tests assert correct
behaviour (exit 0, single-slash names, valid JSON) and fail while the
bug is present; the @tdd_expected_fail handler inverts results so CI
stays green.
Includes Robot Framework integration smoke tests (3), ASV benchmarks (3),
and a shared FakeProviderInfo/FakeProviderRegistry mock in
features/mocks/fake_provider.py.
ISSUES CLOSED: #634
Implemented lazy container activation for devcontainer-instance resources
with ContainerLifecycleState enum tracking six states (inactive, starting,
active, stopping, stopped, error) with validated transitions. Extended
DevcontainerHandler with devcontainer up CLI integration and JSON output
parsing for container start. Added periodic health checking via
devcontainer exec ping with configurable interval. Added agents resource
stop and agents resource rebuild CLI commands for manual lifecycle
control. Wired session close and plan completion hooks to automatic
container cleanup. Includes lifecycle state persistence in resource
registry with timestamped transitions. Added Behave BDD tests, Robot
integration tests, and ASV activation latency benchmarks.
- Added remoteWorkspaceFolder absolute-path validation
- Aligned spec: handler name, rebuild types, --yes flag on stop/rebuild
- Added registry re-read in stop_container success path for consistency
- Added session_id field to ContainerLifecycleTracker for scoped cleanup
- Scoped stop_all_active_containers to session_id when provided
- Wired _cleanup_devcontainers into fail_apply and fail_execute
- Wired start_health_check into activate_container success path
- Restructured facade session close to always run container cleanup
even without session service (F4)
- Re-read tracker from registry in activate_container success path
- Added evict_terminal_trackers to cap registry growth
- Updated devcontainer_resources.md: health check auto-start, scoped
cleanup hooks, known limitations for eviction and sandbox_strategy
- Wired evict_terminal_trackers into stop_all_active_containers so
terminal-state trackers are actually evicted in production
- Made stop_container idempotent: returns early when container is
already in a terminal state instead of raising ValueError
- Fixed benchmark health check thread leak in TimeActivationLatency
by clearing registry after each timing loop
- Added rebuild pass-through (--reset-container flag to devcontainer up)
- Added host_workspace_path field on ContainerLifecycleTracker so
health probes use the host-side path for devcontainer exec
- Wired lazy activation into DevcontainerHandler.resolve() for
devcontainer-instance resources in non-running states
- Changed _default_strategy from SNAPSHOT to NONE (container
itself provides isolation; SandboxFactory raises NotImplementedError
for snapshot)
- Restricted _STOPPABLE_TYPES to devcontainer-instance only
(container-instance is not directly stoppable via CLI)
ISSUES CLOSED: #514
Added minimal LSP server entrypoint supporting initialize/shutdown/exit
handshake over JSON-RPC stdin/stdout transport with Content-Length
framing. Unsupported methods return MethodNotFound error with descriptive
message. Wired LSP requests through ACP facade in local mode. Added
agents lsp serve CLI command with --log-level flag, PID output, and
startup banner. Created reference documentation for the stub server.
Includes Behave BDD tests for protocol handshake, Robot smoke test, and
ASV startup latency benchmark.
ISSUES CLOSED: #203
- Extract MockMCPTransport to features/mocks/mock_mcp_transport.py
- Use ToolRegistry type with TYPE_CHECKING in register_tools()
- Move transport config validation into __init__ via _validate_config()