feat(acms): implement UKO Layer 2 Paradigm Vocabularies (uko-oo, uko-func, uko-proc) #657
Merged
hamza.khyari
merged 1 commits from 2026-03-13 18:28:12 +00:00
feature/m6-uko-layer2-paradigm-vocabularies into master
Dismiss Review
Are you sure you want to dismiss this review?
Labels
Clear labels
auto/needs-reevaluation
controller-managed
overdue
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Needs Feedback
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
Controller deferred this PR; awaiting Phase 6+ scope-evaluator or operator re-enablement.
Auto-agents controller manages this PR/issue (see tools/controller/deploy/RUNBOOK.md). Remove this label to abandon controller management.
PR blocked by an open issue dependency. Operator must close the dep (or remove the dependency link) before the merge driver can act. Auto-cleared by merge_drive when no open deps remain.
Most recent merge cycle hit CI timeout. Driver excludes this PR while last merge_cycle row is < 30 min old; label persists thereafter as visible history.
Currently being processed by an implementer worker.
Currently being processed by the merge driver.
Currently being processed by a reviewer worker.
Merge driver heartbeat stale; pipeline halted. Closed automatically on next clean tick.
Detected master commit violating the strict merge invariant. Tracked as an issue (not a PR label); kept here for label completeness.
In-cycle escalation: most recent attempt ran at the Tier 0 slot (`tier-0`). Slot's model defined in .opencode/models/tiers.yaml.
In-cycle escalation: most recent attempt ran at the Tier 1 slot (`tier-1`). Slot's model defined in .opencode/models/tiers.yaml.
In-cycle escalation: most recent attempt ran at the Tier 2 slot (`tier-2`). Slot's model defined in .opencode/models/tiers.yaml. Gated behind IMPLEMENTER_ESCALATION_TIER2_ENABLED.
In-cycle escalation: most recent attempt ran at the Tier -1 slot (`tier-min`). Slot's model defined in .opencode/models/tiers.yaml. Suffix is ``-min`` (not ``--1``) so the Forgejo UI reads naturally.
Tracking issues used by the AI Automation system for agents to communicate and report.
Rebase conflict needs LLM conflict-resolver.
Failing CI needs implementer attention.
Documenting a driver incident or rollback.
Reviewer has APPROVED this PR and no later REQUEST_CHANGES is outstanding. The merge driver requires this label to even consider a PR for merging. Set by the reviewer worker on APPROVE; cleared on REQUEST_CHANGES.
Train repeatedly lost master-tempo races. Driver excludes via merge_cycle until cooldown elapses; label persists as visible history.
Revert PR backing out an invariant violation. Fast-tracked through the merge driver.
Sentinel PR duplicated from upstream into a personal fork by tools/duplicate_prs_to_fork.py for pipeline testing. Lives only in the fork; the canonical pipeline never sees it.
No implementer activity for N days. Flagged for human review. Auto-cleared on next push to head branch.
Repeatedly fails on current master (>= 3 ci-fail-on-rebased-sha releases in 12 h). Excluded from driver until human triage.
A ticket in a blocked state and unable to complete until some other task is completed first.
Bounty
$100
A bounty of $100 for any open-source contributor who provides a MR that solves this issue
Bounty
$1000
A bounty of $1000 for any open-source contributor who provides a MR that solves this issue
Bounty
$10000
A bounty of $10000 for any open-source contributor who provides a MR that solves this issue
Bounty
$20
A bounty of $20 for any open-source contributor who provides a MR that solves this issue
Bounty
$2000
A bounty of $2000 for any open-source contributor who provides a MR that solves this issue
Bounty
$250
A bounty of $250 for any open-source contributor who provides a MR that solves this issue
Bounty
$50
A bounty of $50 for any open-source contributor who provides a MR that solves this issue
Bounty
$500
A bounty of $500 for any open-source contributor who provides a MR that solves this issue
Bounty
$5000
A bounty of $5000 for any open-source contributor who provides a MR that solves this issue
Bounty
$750
A bounty of $750 for any open-source contributor who provides a MR that solves this issue
MoSCoW
Could have
Could have feature in order to satisfy the epic/legendary.
MoSCoW
Must have
Must have feature in order to satisfy the epic/legendary.
MoSCoW
Should have
Should have feature in order to satisfy the epic/legendary.
There are questions in the ticket that can not be completed until the project owner provides clarity.
Points
1
1 man-hours worth of work for an expert with no learning curve.
Points
13
13 man-hours worth of work for an expert with no learning curve.
Points
2
2 man-hours worth of work for an expert with no learning curve.
Points
21
21 man-hours worth of work for an expert with no learning curve.
Points
3
3 man-hours worth of work for an expert with no learning curve.
Points
34
34 man-hours worth of work for an expert with no learning curve.
Points
5
5 man-hours worth of work for an expert with no learning curve.
Points
55
55 man-hours worth of work for an expert with no learning curve.
Points
8
8 man-hours worth of work for an expert with no learning curve.
Points
88
88 man-hours worth of work for an expert with no learning curve.
Priority
Backlog
This ticket has backlogged priority and is not to be worked on yet
Priority
CI Blocker
Critical priority issue that blocks CI/CD pipeline and prevents PR merges
Priority
Critical
The priority is critical
Priority
High
The priority is high
Priority
Low
The priority is low
Priority
Medium
The priority is medium
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
A ticket for learning a tool or technology that is needed to be able to do future planning and design.
State
Completed
The ticket has been fully implemented, completed, and merged with the source code. This label should only be applied once a ticket is closed.
State
Duplicate
A ticket that represents the same content as an existing ticket.
State
In Progress
A ticket that is actively being developed.
State
In Review
A ticket that has had some code completed to implement but is waiting to pass peer review and is not yet merged in.
State
Paused
This ticket's work started but wasn't finished. It's on hold (likely in a feature branch) and will be resumed later, either due to a blocker or a delay.
State
Unverified
All new tickets start in this state. A developer may set it to show the ticket is unverified. This means we haven't agreed to work on it. It will either move to a verified state or be closed as wontdo.
State
Verified
The issue has been verified by a developer as legitimate. It will be worked on and verified tickets are now considered part of the backlog.
State
Wont Do
This ticket has been decided it wont be done. This may mean the bug has been determined to not be real (cant verify) or the feature is one we have decided we dont want to adopt.
Type
Automation
Any edits or discussion about the AI automated coding system.
Type
Bug
Something that doesnt work as intended.
Type
Discussion
Anytime a ticket represents a discussion about a subject and doesnt fall into one of the other categories.
Type
Documentation
An error or improvement needed in the documentation.
Type
Epic
Any first tier epic. That is, an epic which contains only issues as children and will not have sub-epics.
Type
Feature
Some new functionality not present.
Type
Legendary
A type of Epic which will contain other Epics.
Type
Refactor
A code change that restructures existing code without changing its external behavior.
Type
Support
Someone needs help using the project.
Type
Task
A generic task that doesnt fit into the other type categories.
Type
Testing
Work exclusively focusing on fixing or expanding testing.
Projects
Clear projects
No project
Assignees
aditya (Aditya Chhabra)
aleenaumair (Aleena Umair)
brent.edwards (Brent Edwards)
CoreRasurae (Luis Mendes)
drew (Drew Morris)
eugen.thaci (Eugen Thaci)
freemo (Jeffrey Phillips Freeman)
HAL9000 (HAL 9000)
HAL9001 (HAL9001)
hamza.khyari (Hamza Khyari)
hurui200320 (Rui Hu)
justin.morris
khird (Kyle Hird)
org.cleveragents
Clear assignees
No Assignees
hamza.khyari
Notifications
Due Date
No due date set.
Blocks
#575 feat(acms): implement UKO Layer 2 Paradigm Vocabularies (uko-oo, uko-func, uko-proc)
cleveragents/cleveragents-core
Reference: cleveragents/cleveragents-core#657
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feature/m6-uko-layer2-paradigm-vocabularies"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements Forgejo issue #575 -- UKO Layer 2 Paradigm Vocabularies (
uko-oo,uko-func,uko-proc) for the ACMS subsystem.Motivation
Layer 2 paradigm vocabularies specialize the Layer 1
uko-code:domain ontology with paradigm-specific semantic classes. Object-oriented code needs class/interface/method/attribute hierarchy concepts, functional code needs pure functions/type classes/monads, and procedural code needs function declarations/global variables/headers/structs/macros. Each paradigm also extends the DetailLevelMap with paradigm-specific named levels (e.g., CLASS_HIERARCHY for OO). Without these, the ACMS context pipeline cannot produce paradigm-aware code summaries.Changes
Ontology (
docs/ontology/uko.ttl)uko-func:anduko-proc:namespace prefixesPython Models (
src/cleveragents/acms/uko/)vocabularies.py(494 lines) -- VocabularyClass, VocabularyProperty, ParadigmVocabulary, VocabularyRegistry (frozen Pydantic models with prefix/IRI lookup and duplicate protection)detail_level_maps.py(277 lines) -- DetailLevelMapBuilder with insertion/reassignment logic; pre-built maps: CODE_DETAIL_LEVEL_MAP, OO_DETAIL_LEVEL_MAP, FUNC_DETAIL_LEVEL_MAP, PROC_DETAIL_LEVEL_MAP__init__.py/acms/__init__.py-- Package re-exports with sorted__all__DetailLevelMap Inheritance
Tests
features/acms/uko_layer2_paradigm_vocabularies.feature-- 81 scenarios, 286 steps, 0 failuresrobot/helper_uko_layer2_paradigm.py-- 5 subcommands, all passDocumentation
docs/reference/uko_layer2_paradigm_vocabularies.md-- Reference documentationAutomated Check Results
Diff Coverage
vocabularies.pydetail_level_maps.pyacms/uko/__init__.pyacms/__init__.pydomain/models/acms/crp.py(delta)Spec Reference
docs/specification.mdlines ~42333-42422 (Layer 2: Paradigm / Format Specializations)Closes #575
eee1c01fd0tob0a7c1b8a6db04d3a114to995ad1daf3995ad1daf3to91efb508e0Exhaustive Code Review — PR #657: UKO Layer 2 Paradigm Vocabularies
Reviewer: Brent Edwards
PR Size: XL (~3,118 lines across 18 files)
Review method: 10 parallel review passes (architecture, security, test quality, ontology, code quality, backward compatibility, CRP deep-dive, Semgrep scan, Pyright analysis, Ruff lint)
Overall Assessment
This is a well-structured PR with thorough test coverage (81 Behave scenarios, 286 steps), clean Semgrep results, and correct ontology modeling. The Python models are properly frozen, docstrings are thorough, and the
DetailLevelMapBuilderpattern is sound. However, there are 1 P0 blocker, 4 P1 must-fix, 13 P2 should-fix, and 10 P3 nit findings that need attention before merge.Per playbook escalation rules: The P0 requires a fix before merge. The multiple P1 findings in the CRP domain subsystem warrant escalation to the domain model owner (Luis).
P0:blocker (1) — Must fix before merge
H1. Robot helper imports
VocabularyRegistryfrom wrong modulerobot/helper_uko_layer2_paradigm.py:28—VocabularyRegistryis imported fromcleveragents.acms.uko.vocabularies, but it is defined incleveragents.acms.uko.vocabulary_registryand is NOT exported fromvocabularies.py. Every robot subcommand will crash at runtime withImportError.Fix:
The same wrong import path appears in
docs/reference/uko_layer2_paradigm_vocabularies.md:124-127— users following the documentation will also getImportError.P1:must-fix (4) — Must fix before merge
H2.
_freeze_levelsmodel_validator does not re-run on field assignment, breaking the immutability invariantcrp.py:108-112—DetailLevelMapusesvalidate_assignment=True(notfrozen=True). The_freeze_levelslogic is amodel_validator(mode="after"), which runs at construction but does NOT re-run on field assignment in Pydantic v2. This meansmap.levels = {"FOO": 1}would bypass the freeze and set a plaindict, silently breaking the immutability contract.Fix: Either (a) make
DetailLevelMapfrozen=Trueand keepregister()usingobject.__setattr__, or (b) convert the freeze to a@field_validator("levels", mode="after")so it runs on every assignment trigger.H3.
MappingProxyTypeserialization is untested —model_dump_json()may failcrp.py:86,111— Thelevelsfield is annotated asdict[str, int]but holdsMappingProxyTypeat runtime. Pydantic v2's Rust-based JSON serializer (pydantic-core) may not handleMappingProxyTypecorrectly. No test in this PR callsmodel_dump()ormodel_dump_json()on aDetailLevelMap.Fix: Add a test that roundtrips
DetailLevelMap(...).model_dump_json()to confirm compatibility. If it fails, add a@field_serializer("levels")that converts todict.H4.
levelsfield type annotation lies to the type checkercrp.py:86— Field isdict[str, int]but runtime isMappingProxyType[str, int]. Pyright/mypy will believe.levelssupports.update(),.pop(),[key]=val— all of which raiseTypeErrorat runtime. Downstream code passingmap.levelsto functions expectingdictgets false confidence.Fix: Annotate as
Mapping[str, int](fromtyping) which is truthful for both construction input and runtime type. Pydantic acceptsdictinput during construction either way.H5. Unbounded list fields in
ContextRequestallow memory exhaustioncrp.py:330-385— Fieldsentities,uko_types,focus,preferred_strategies, andrequired_backendsare alllist[str]with nomax_length. SinceContextRequestis the primary user-facing input model, a malformed request with millions of items could exhaust memory. Also applies toquery: str(nomax_length).Fix: Add
max_lengthconstraints tuned to expected workloads (e.g.,max_length=1000for lists,max_length=10_000for query).P2:should-fix (13) — Fix in follow-up PR within 3 days
M1. Duplicated
_validate_uriacrossVocabularyClassandVocabularyPropertyvocabularies.py:94-100andvocabularies.py:144-150— Character-for-character identical validators. Extract to a shared module-level helper_validate_http_uri(v: str) -> str.M2. Inconsistent URI scheme validation —
parent_uris,domain_uri,range_urinot validatedvocabularies.py:89,129-141— Only the primaryurifield enforceshttp(s)://scheme. Secondary URI fields (parent_uris,domain_uri,range_uri,sub_property_of) have no scheme check. If these reach an RDF serializer or HTTP client, malicious values likejavascript:orfile:///could be injected.M3. Near-identical
_build_func_mapand_build_proc_map+ hardcodedmax_depth=9detail_level_maps.py:261-292— These differ only in the domain string. Extract to_build_passthrough_map(domain: str). Also,max_depth=9is hardcoded in 3 places instead of deriving fromCODE_DETAIL_LEVEL_MAP.max_depth.M4. No domain-specific exception types
crp.py:136,detail_level_maps.py:142-148,vocabulary_registry.py:67-72— All error conditions raise bareValueError. Define domain exceptions (UnknownDetailLevelError,DuplicateVocabularyError, etc.) as subclasses ofValueErrorfor backward compatibility.M5.
resolve()has no cycle guard for circular parent chainscrp.py:129-136— If a circular parent reference is introduced (e.g.,A.parent=B, B.parent=A),resolve()infinite-recurses toRecursionError. Add a visited-set guard or max-depth parameter.M6.
register()is racy under concurrent accesscrp.py:138-158— Two threads callingregister()concurrently both readdict(self.levels), add their entry, and write back — last-writer-wins race. Consider returning a new instance or adding a note that the method is not thread-safe.M7.
after_levelnot stripped inDetailLevelMapBuilder.insert_afterdetail_level_maps.py:120-150—new_levelis stripped butafter_levelis not. If whitespace is present, the lookup fails with a confusing error.M8. Missing test: VocabularyProperty with empty label/domain/range
Feature file has no scenario testing the
min_length=1validators onVocabularyProperty.label,domain_uri, andrange_uri(only tests emptyuri).M9. Missing test: invalid URI scheme (non-HTTP)
No scenario tests that
ftp://orurn:URIs are rejected by_validate_uri. The validator code atvocabularies.py:94-100would go undetected if removed.M10. Missing test:
insert_afterat the tail of the level listAll insertion tests insert after middle levels. No test inserts after
FULL_SOURCE(the last level), which exercises the boundary ofordered_names.insert(idx + 1, ...)at the end of the list.M11.
scoped_sessionchange alters session-sharing semantics for R2 testsfeatures/steps/repositories_coverage_r2_steps.py:237-241— Changing fromsessionmakertoscoped_session(sessionmaker(...))means repeated calls return the same session within a thread. Add.remove()in teardown and verify no existing R2 steps rely on independent sessions.M12. Ontology:
uko-oo:Classinherits contradictory archetypes (Atom + Container)uko.ttl:150-153,556-559—uko-code:TypeDefinitionsubclassesuko:Atom. Thenuko-oo:Classsubclasses bothTypeDefinition(→Atom) andContainer. If disjointness axioms are ever added to Layer 0, everyuko-oo:Classindividual becomes unsatisfiable. Add a comment documenting this design decision, or changeTypeDefinitionto subclassInformationUnitdirectly.M13. CHANGELOG references issue
#575but not PR#657CHANGELOG.md:17— Clarify:(issue #575, PR #657)or just(#657)per project convention.P3:nit (10) — Optional, author discretion
L1.
vocabularies.py:139-142—VocabularyProperty.sub_property_ofuses""default instead ofNone. Makes truthiness checks ambiguous.L2.
vocabularies.py:346,351— Unnecessary parentheses around string literals incomment=("...").L3.
vocabularies.py:22-29—__all__omits public namespace constants (UKO_OO_PREFIX,UKO_OO_IRI, etc.). Either add them or prefix with_.L4.
vocabularies.py:270-271,333-334,372-373—layer=2andparent_domain="uko-code:"explicitly passed but are already model defaults. Add a comment# explicit for spec traceabilityor remove.L5.
detail_level_maps.py:64,251+vocabularies.py:188,271,334,373— String literal"uko-code:"repeated 6 times. Consider a named constant.L6.
crp.py:349-356—ContextRequest.depth: int | strunion makes every consumer do isinstance dispatch. Consider adding aresolve_depth(map) -> intconvenience method.L7.
uko.ttl:9— Unuseduko-py:prefix declared but never used. Flagged as warning by TTL validators.L8. Feature file — Inconsistent
@frozenvs@vocab_frozentagging (lines 40,67 vs 555). Running--tags=@frozenmisses the ParadigmVocabulary test.L9.
acms/__init__.py:28-42—__all__is a manual copy ofuko/__init__.py:38-52. Consider re-exporting programmatically or adding a sync comment.L10. Step definitions — The try/except error-capture pattern is repeated 18 times across 4 step files. Consider extracting a
capture_error(ctx, *exc_types)context manager.Static Analysis Results
Checklist Verification
_freeze_levelshas bypass risk (H2)levelsannotation lies (H4)effective_levels()return type changed (H4),levelsruntime type changedSummary
Verdict: REQUEST_CHANGES — The P0 (wrong import) and P1 items (freeze invariant, serialization, type annotation, unbounded inputs) must be resolved before merge. The P2/P3 items can be addressed in a follow-up.
@@ -0,0 +25,4 @@PROC_DETAIL_LEVEL_MAP,)from cleveragents.acms.uko.vocabularies import ( # noqa: E402VocabularyRegistry,P0:blocker —
VocabularyRegistryis imported fromcleveragents.acms.uko.vocabularies, but it is defined incleveragents.acms.uko.vocabulary_registryand is NOT exported fromvocabularies.py. Every robot subcommand will crash at runtime withImportError.Fix:
@@ -0,0 +258,4 @@return builder.build()def _build_func_map() -> DetailLevelMap:P2:should-fix —
_build_func_map(line 261) and_build_proc_map(line 278) are near-identical — they differ only in the domain string. Also,max_depth=9is hardcoded instead of derived fromCODE_DETAIL_LEVEL_MAP.max_depth. If the parent map ever changes, child maps silently drift.Fix:
@@ -0,0 +86,4 @@default="",description="rdfs:comment describing this class",)parent_uris: tuple[str, ...] = Field(P2:should-fix — Only the primary
urifield validates the HTTP(S) scheme. Theparent_uris,domain_uri,range_uri, andsub_property_offields have no scheme validation. If these reach an RDF serializer or HTTP client downstream, non-HTTP URIs (e.g.,javascript:,file:///) could be injected. Apply the shared validator to all URI-typed fields.@@ -0,0 +91,4 @@description="rdfs:subClassOf parent IRIs",)@field_validator("uri")P2:should-fix — This
_validate_urimethod is character-for-character identical to the one inVocabularyProperty(line 144-150). Extract to a shared module-level helper:P1:must-fix — The
levelsfield is annotated asdict[str, int]but holdsMappingProxyType[str, int]at runtime after_freeze_levelsruns. This means:isinstance(map.levels, dict)→Falseat runtime.levelssupports.update(),.pop(),[key]=val— all raiseTypeErrormodel_dump_json()with Pydantic's Rust serializer is untested and may failFix: Annotate as
Mapping[str, int](fromtyping). Add a test formodel_dump()andmodel_dump_json()roundtrip.P1:must-fix —
_freeze_levelsis amodel_validator(mode="after")which runs at construction but does NOT re-run on field assignment in Pydantic v2. Since this model usesvalidate_assignment=True(notfrozen=True), doingmap.levels = {"FOO": 1}bypasses the freeze and sets a plaindict, silently breaking the immutability contract.Fix: Either (a) make
DetailLevelMapfrozen=Trueand keepregister()usingobject.__setattr__, or (b) convert to@field_validator("levels", mode="after")so it runs on every assignment.P2:should-fix —
resolve()recurses throughself.parent.resolve(depth)with no cycle guard. If a circular parent reference is introduced (e.g., viaDetailLevelMapBuildermis-wiring), this causesRecursionError. Add a visited-set guard or max-recursion parameter.PM Status (Day 31):
Merge conflict detected. The 17 PR merges from Days 30-31 (including your own 5 merges) significantly updated
develop.Action required: @hamza.khyari — please rebase this PR against current
developand push.Priority: M6 work — continue at pace. Your Days 30-31 velocity was excellent (5 merges).
69fed8a925tob7aff82d6fResponse to Review #2126 (Brent Edwards)
All findings have been validated against the current source (
e6304300) and addressed in commite6304300.P0 (1 finding)
robot/helper_uko_layer2_paradigm.pyanddocs/reference/uko_layer2_paradigm_vocabularies.mdto import fromvocabulary_registryP1 (4 findings)
_freeze_levelsmodel_validator bypass on assignment__setattr__override that re-freezeslevelsasMappingProxyTypeafter Pydantic stores the validated value. Also changedvalidate_levelstomode="before"to handleMappingProxyTypeinput on round-trip. BDD scenario added.MappingProxyTypeserialization untested / fails@field_serializer("levels")that convertsMappingProxyTypeback to plaindictfor JSON serialization. Added 2 BDD scenarios formodel_dump_json()andmodel_dump().levelsannotated asdict[str, int]but runtime isMappingProxyTypedict[str, int]annotation for Pydantic deserialization compatibility.ContextRequestContextRequestis pre-existing code not modified in this PR. Filed as separate concern.P2 (13 findings)
_validate_uri_validate_http_uri()shared helper, both classes now delegate to it.field_validatorforparent_uris,domain_uri,range_uri,sub_property_of-- all now check HTTP(S) scheme._build_passthrough_map(domain). Extracted_CODE_MAX_DEPTHand_CODE_DOMAINconstants.DetailLevelError(ValueError)andDetailLevelCycleError(DetailLevelError).resolve()id()-based visited set. BDD scenario added.register()race under concurrent accessdetail_level_maps.pymodule docstring (lines 14-19). Module constants are read-only after init;register()is not called at runtime.after_levelnot stripped ininsert_afterFULL_SOURCE.scoped_sessionsemantics changeStaticPool. Documented.uko-oo:Classcontradictory archetypesuko-oo:Classis both aTypeDefinition(Atom) andContainer. This is intentional OWL multiple inheritance.PR #657.P3 (selected fixes)
sub_property_ofdefault""->Nonecomment=()__all__missing namespace constants"uko-code:"repeated 6 times_CODE_DOMAINconstantQuality Gates
Review Response -- Second Fix Pass (commit 339f71db)
All remaining valid-but-unfixed findings from Brent Edwards' review (ID 2126) have been addressed in this commit. Combined with the first fix pass (e6304300), every valid finding is now resolved.
Findings Addressed in Second Pass
max_length=500toentities,uko_types,focus,preferred_strategies,required_backendsvia module-level_MAX_LIST_ITEMSconstantregister()race conditionPrivateAttr(default_factory=threading.Lock)field withwith self._register_lock:guard around read-modify-write inregister()layer=2andparent_domaindefaultsField(...)(required). Updated all 4 test callsites inuko_l2_coverage_ttl_steps.pydepth: int | strunion dispatchDetailDepth = int | strtype alias at module level; used inContextRequest.depthfield,DetailLevelMap.resolve()signature, and exported fromacms.__init__uko-py:prefix in uko.ttl@prefix uko-py:line@frozen/@vocab_frozentags@vocab_frozenthroughoutacms/__init__.py__all__duplication__all__: list[str] = list(_uko.__all__)capture_error()context-manager helper in_uko_l2_test_helpers.py; applied to all 29 occurrences across 4 step filesFindings Confirmed Not Bugs (unchanged)
Quality Gates
nox -s lintnox -s typecheckAll findings from the original review are now addressed. Ready for re-review.
PM Review — Day 31 (Specification Update)
This PR is mergeable — one of only 5 clean PRs in the repository.
Spec Alignment Check
UKO Layer 2 paradigm vocabularies (OO, functional, procedural) are NOT impacted by the ACP→A2A or TUI changes. The ACMS knowledge layer is orthogonal to the protocol layer.
Action Required
@hamza.khyari — This is ready for merge review. Excellent velocity (5 PRs merged recently). Please ensure CHANGELOG is updated if not already done.
H4 Fix (commit 6363106d)
Missed one: H4 (P1) --
levelsfield type annotation lies to the type checker.Changed
DetailLevelMap.levelsannotation fromdict[str, int]toMapping[str, int](fromcollections.abc). This truthfully reflects theMappingProxyTypestored at runtime -- type checkers now see read-only methods only (__getitem__,keys(),values(),items()) and will correctly flag mutation attempts.All quality gates still pass (lint, typecheck, 98 scenarios / 333 steps).
All 28 findings from the review are now addressed:
Second-Round Review — Export chains, backward compatibility,
__all__sortingI verified the export chains, searched for existing callers of changed APIs, and checked
__all__sorting across all new/modified files. Four issues found; one P1, three P2.P1 —
DetailLevelError/DetailLevelCycleErrornot exported fromdomain/models/acms/__init__.pyFile:
src/cleveragents/domain/models/acms/__init__.pyThe PR adds two new public exception classes to
crp.py:Neither is imported nor listed in
__all__ofdomain/models/acms/__init__.py. The only current consumer (features/steps/uko_l2_detail_level_steps.py:310) works around this by importing directly from the internal module:This breaks the established encapsulation pattern in this codebase — every other public symbol in
crp.pyis re-exported through the package__init__.py. Downstream consumers who want to catch these specific exceptions (rather than the genericValueError) would need to reach into the internalcrpmodule.Fix: Add both to the import block and to
__all__indomain/models/acms/__init__.py.P2 —
__all__sorting violations in 3 filesCONTRIBUTING.md requires sorted
__all__. Three files have incorrect ordering:1.
src/cleveragents/acms/uko/vocabularies.py—UKO_*constants are placed beforeParadigmVocabulary, but in ASCII/lexicographic sort,P(0x50) <U(0x55), soParadigmVocabularymust come first. Correct order:2.
src/cleveragents/acms/uko/detail_level_maps.py—DetailLevelMapBuilder(D) sorts beforeFUNC_DETAIL_LEVEL_MAP(F), but currently appears afterPROC_DETAIL_LEVEL_MAP. Correct order:3.
src/cleveragents/acms/uko/__init__.py— Same issue inherited fromdetail_level_maps.py.DetailLevelMapBuildermust come afterCODE_DETAIL_LEVEL_MAPand beforeFUNC_DETAIL_LEVEL_MAP.4.
src/cleveragents/acms/__init__.py— Useslist(_uko.__all__)so it inherits whatever orderuko/__init__.pyhas. Once (3) is fixed this auto-fixes, but worth noting that the explicit imports at the top of the file are also in the unsorted order and should match the corrected__all__.P2 —
effective_levels()return type change is a breaking API changeFile:
src/cleveragents/domain/models/acms/crp.py:246The return type of
effective_levels()changed fromdict[str, int]toMappingProxyType[str, int]. This is a behavioral breaking change: any caller that mutates the returned mapping (e.g.,levels["FOO"] = 5) will now get aTypeErrorat runtime.There is one existing caller in
features/steps/crp_models_steps.py:148that annotates the return asdict[str, int]:This is technically a type error now (the annotation lies), though it works at runtime since the caller only reads. However, the asymmetry should be cleaned up — the test annotation should use
Mapping[str, int]orMappingProxyType[str, int].More importantly: since
effective_levels()previously returned a mutabledict, any caller who mutated the result (even unintentionally viamerged.update()patterns in their own code) will now break. I searched the codebase and found no current callers that mutate the return value, so the practical risk is low. But this should be documented in the changelog entry as a breaking change.Informational — Items verified as correct
DetailDepthexport: Correctly added todomain/models/acms/__init__.pyimports and__all__. ✓_MAX_LIST_ITEMSprivacy: Underscore-prefixed, not exported. ✓acms/__init__.pyre-exports:list(_uko.__all__)correctly picks upVocabularyRegistryand all 13 symbols. ✓_build_passthrough_mapcorrectness:levels={}withparent=CODE_DETAIL_LEVEL_MAPis correct.resolve("SIGNATURES")walks the parent chain and finds it.effective_levels()merges parent levels (all 10 code levels) with the empty child dict, returning the full parent set. Themax_depth=9matches the parent. ✓resolve()exception subclassing:DetailLevelError(ValueError)andDetailLevelCycleError(DetailLevelError)are both subclasses ofValueError, so existingexcept ValueErrorhandlers (e.g., incrp_models_steps.py,depth_breadth_projection.py) continue to catch them. ✓ Backward compatible.ContextRequestmax_length=500: All existing construction sites pass small lists (typically 0-5 items). No breakage risk. ✓domain/models/acms/__init__.py__all__: Sorted correctly. ✓vocabulary_registry.py__all__: Single entry, sorted. ✓@@ -0,0 +36,4 @@from cleveragents.acms.uko.vocabulary_registry import VocabularyRegistry__all__: list[str] = ["CODE_DETAIL_LEVEL_MAP",P2: Same
__all__sorting issue inherited from the submodules.DetailLevelMapBuildermust come afterCODE_DETAIL_LEVEL_MAPand beforeFUNC_DETAIL_LEVEL_MAP. The explicit imports at the top should also be reordered to match the corrected sort.@@ -0,0 +32,4 @@__all__: list[str] = ["CODE_DETAIL_LEVEL_MAP","FUNC_DETAIL_LEVEL_MAP","OO_DETAIL_LEVEL_MAP",P2:
__all__is not sorted.DetailLevelMapBuilder(D) sorts beforeFUNC_DETAIL_LEVEL_MAP(F). Correct order:@@ -0,0 +20,4 @@from pydantic import BaseModel, ConfigDict, Field, field_validator__all__: list[str] = ["UKO_ATOM",P2:
__all__is not sorted per CONTRIBUTING.md. In ASCII/lexicographic order,P<U<V<g, soParadigmVocabularymust come before theUKO_*constants. Correct order:P1:
DetailLevelErrorandDetailLevelCycleErrorare defined incrp.pybut not imported here and not listed in__all__. This breaks the encapsulation pattern — every other public CRP symbol is re-exported through this__init__.py.Add to the
crpimport block:And add both to
__all__(betweenDetailDepthandDetailLevelMap).@@ -139,2 +244,3 @@object.__setattr__(self, "levels", MappingProxyType(updated))def effective_levels(self) -> dict[str, int]:def effective_levels(self) -> MappingProxyType[str, int]:P2: Return type changed from
dict[str, int]→MappingProxyType[str, int]. This is a behavioral breaking change (callers who mutated the old return value will now getTypeError). No current callers are affected, but this should be noted in the CHANGELOG entry as a breaking change. Also,features/steps/crp_models_steps.py:148annotates the return asdict[str, int]which is now incorrect.Second-Round Code Review — PR #657: UKO Layer 2 Paradigm Vocabularies
Reviewer: Brent Edwards
Review method: 6 parallel review threads (fix verification, domain model deep-dive, test quality, ontology/TTL alignment, security/type safety, backward compatibility/API surface)
First-Round Fix Verification
16 of 17 original findings fully resolved. Excellent fix work by @hamza.khyari — the two fix-pass commits address the vast majority of issues thoroughly and correctly. The only partial fix is M4 (domain-specific exceptions):
DetailLevelErrorandDetailLevelCycleErrorare present butDuplicateVocabularyErrorforVocabularyRegistrywas not added. This is low-risk and acceptable as-is.New Findings — P1:must-fix (5)
N1.
DetailLevelError/DetailLevelCycleErrornot exported from package__init__.pysrc/cleveragents/domain/models/acms/__init__.py— Both exceptions are defined incrp.py:68-73and raised byresolve()at lines 207 and 215, but neither is imported into__init__.pynor listed in__all__. Consumers must use the internal pathfrom cleveragents.domain.models.acms.crp import DetailLevelError— breaking the package encapsulation pattern. The existing caller indepth_breadth_projection.py:309lets errors propagate asValueError, which still works since both subclassValueError, but the public API contract is incomplete.Fix: Add to the import block and
__all__:N2.
deepcopy/pickle/model_copy(deep=True)crash onDetailLevelMapsrc/cleveragents/domain/models/acms/crp.py— The combination ofMappingProxyTypeinlevelsandthreading.Lockin_register_lockmakes the model unpicklable and un-deepcopyable.copy.deepcopy(model)raisesTypeError: cannot pickle 'mappingproxy' object. This matters because LangGraph's state management (src/cleveragents/langgraph/nodes.py:100) usesdeepcopy— any state containing aDetailLevelMapwould crash at runtime.Fix: Add
__deepcopy__and__copy__methods:N3.
queryfield onContextRequeststill has nomax_lengthsrc/cleveragents/domain/models/acms/crp.py:416-419— The original H5 finding explicitly flaggedquery: stralongside the list fields. The list fields all receivedmax_length=500, butquerywas missed. A 100MB query string passes validation, which is the single largest memory-exhaustion vector on the input model.Fix:
N4. Inner-function imports in
uko_l2_detail_level_steps.pyfeatures/steps/uko_l2_detail_level_steps.py:310,318,331— Three imports are inside function bodies:from cleveragents.domain.models.acms.crp import DetailLevelCycleErrorfrom types import MappingProxyTypeCONTRIBUTING.md lines 1289-1294 is absolute: "Ensure all imports are at the top of the Python file. Never encapsulate imports inside an indented code block." The only exception is
if TYPE_CHECKING:.N5. Robot helper uses
except Exceptionwithout re-raising in all 5 commandsrobot/helper_uko_layer2_paradigm.py:58,77,102,159,200— Every command function catchesException, prints a message, and returns 1 without re-raising. CONTRIBUTING.md lines 496, 1382: "Do not suppress errors. Do not use bareexcept:orexcept Exception:without re-raising." The exception type and traceback are lost.Fix: Either narrow the caught types to specific expected exceptions, or add
traceback.print_exc()and re-raise.New Findings — P2:should-fix (7)
N6.
__setattr__re-freezes from original pre-validationvalue, not validatedself.levelscrp.py:170— Aftersuper().__setattr__(name, value), Pydantic has validated and stored the result onself.levels. But the re-freeze line usesMappingProxyType(dict(value))— the original pre-validation input — notMappingProxyType(dict(self.levels)). Currently safe becausevalidate_levelsdoesn't modify keys/values, but if the validator is ever extended to normalize keys (strip whitespace, case-fold), the__setattr__would silently revert that normalization.Fix:
object.__setattr__(self, "levels", MappingProxyType(dict(self.levels)))instead ofdict(value).N7. Factually incorrect comments about model_validator behavior
crp.py:148-155,161-165— The docstrings state "model_validator does not re-run on validate_assignment". In Pydantic 2.12.5 (the project's version),model_validator(mode='after')does re-run onvalidate_assignment. The__setattr__override is therefore redundant (but harmless as defensive code). The comments will mislead future maintainers.Fix: Update comments to say the
__setattr__is a defensive measure, not a fix for a current Pydantic limitation.N8.
capture_error()context manager suppresses exceptionsfeatures/steps/_uko_l2_test_helpers.py:42-49— The helper catchesexc_types, stores the exception onctx.error, but never re-raises. This is a hand-rolledcontextlib.suppress()equivalent. While the intent (negative-test capture) is sound, CONTRIBUTING.md prohibits suppression. Add a code comment citing the test-infrastructure exemption rationale.N9.
__all__lists not sorted in 3 filessrc/cleveragents/acms/uko/vocabularies.py,src/cleveragents/acms/uko/detail_level_maps.py,src/cleveragents/acms/uko/__init__.py— TheUKO_*namespace constants are placed before alphabetically earlier entries.acms/__init__.pyinherits the issue vialist(_uko.__all__). CONTRIBUTING.md requires sorted__all__.N10.
effective_levels()return type change not documented as breakingcrp.py— Return type changed fromdict[str, int]toMappingProxyType[str, int]. Any downstream code doinglevels = map.effective_levels(); levels["FOO"] = 1would now getTypeError. No current callers are affected, but this is a public API change. Should be noted in CHANGELOG.N11. Missing test coverage for diverse bad URI schemes on secondary fields
features/acms/uko_layer2_paradigm_vocabularies.feature— Tests only coverftp://onVocabularyClass.uriandurn:onVocabularyProperty.uri. No tests verify scheme rejection onparent_uris,domain_uri,range_uri, orsub_property_of— all of which have validators.N12. Incomplete H5 fix — M4 domain exceptions partial
VocabularyRegistry.register()invocabulary_registry.py:67-72still raises bareValueErrorfor duplicate prefix/IRI. The M4 finding asked forDuplicateVocabularyError. Low priority since the detail-level exceptions (the critical ones) are present.New Findings — P3:nit (8)
N13.
crp.py:155—__setattr__parametervalue: objectvs Pydantic'svalue: Any. No functional impact but inconsistent with parent signature.N14.
crp.py:226-241—register()doesn't enforcevalue <= max_depth. A registered named level can map to a depth exceedingmax_depth, whileresolve(99)clamps integers. Inconsistent capping behavior.N15.
crp.py:405— List items inContextRequestlack per-stringmax_length. 500 items of 1MB strings each = 500MB.N16.
vocabularies.py:82—_validate_http_uriis scheme-only. No SSRF protection (low risk: identifiers not fetched, but worth a code comment).N17.
docs/reference/uko_layer2_paradigm_vocabularies.md— Description columns paraphraserdfs:commentrather than quoting verbatim.N18.
docs/ontology/uko.ttl:555-558— No inline comment documenting the intentional dual Atom+Container inheritance design decision (M12 follow-up).N19.
docs/reference/uko_layer2_paradigm_vocabularies.md— "Layer 1 Dependencies" section omits Layer 0 URIs that are directly referenced.N20.
features/steps/uko_l2_detail_level_steps.py:339-345— Manualtry/except TypeError: passinstead of usingcapture_error(), inconsistent with rest of test suite.Static Analysis
Ontology Consistency
All 12 Layer 2 OWL classes and 2 OWL properties verified field-by-field across TTL, Python models, and reference docs. No mismatches in URIs, labels, comments, or parent chains. Namespace IRIs consistent across all sources.
Summary
Verdict: REQUEST_CHANGES — The P1 items (missing exports, deepcopy crash, query max_length, CONTRIBUTING.md violations) must be addressed. All are straightforward fixes. The bulk of the first-round issues were resolved excellently — this is close to merge-ready.
Note: Per playbook escalation rules, N2 (deepcopy crash affecting LangGraph) may warrant a quick check with the LangGraph subsystem owner to confirm whether
DetailLevelMapobjects appear in graph state.Consolidated Code Review — PR #657: UKO Layer 2 Paradigm Vocabularies
Reviewer: Rui Hu (
hurui200320)PR Size: XL (~3,100+ lines across 19 files)
Review method: 5 parallel review agents (bug detection, security, test quality, type safety/performance, spec compliance + prior review verification)
Specification Compliance
All three paradigm vocabularies (uko-oo, uko-func, uko-proc) match the specification exactly:
rdfs:subClassOfhierarchies inuko.ttlalign with spec lines ~42333-42422The ontology modeling, vocabulary definitions, and builder logic are well-implemented overall. Credit to @hamza.khyari for addressing the bulk of the first-round review findings thoroughly.
Prior Review Status
Brent Edwards' first-round findings (review ID 2126): All resolved. The two fix-pass commits addressed all P0/P1 items correctly.
Brent Edwards' second-round findings (review ID 2141): 12 of 19 remain unresolved (5 P1, 5 P2, 4 P3 — details below with N-prefixed IDs from that review). One finding (N7 — comment about model_validator behavior) was evaluated and found to be a non-issue (the comment is factually correct for Pydantic v2).
P1: Must Fix Before Merge (5 unresolved + 1 new)
F1.
DetailLevelError/DetailLevelCycleErrornot exported fromdomain/models/acms/__init__.py(unresolved N1)src/cleveragents/domain/models/acms/__init__.py— Both exceptions are defined incrp.py:68-73and raised byresolve(), but neither is imported or listed in__all__. Consumers must reach into the privatecrpmodule path.Fix: Add both to the import block and
__all__indomain/models/acms/__init__.py.F2.
deepcopy/pickle/model_copy(deep=True)crash onDetailLevelMap(unresolved N2)src/cleveragents/domain/models/acms/crp.py:220— The_register_lock: threading.Lockprivate attribute cannot be pickled or deep-copied.copy.deepcopy(map)raisesTypeError: cannot pickle '_thread.lock' object. This affects any deep-copy use case including test fixtures and LangGraph state management.Fix: Add
__deepcopy__method that creates a new instance with a fresh lock:F3.
ContextRequest.queryhas nomax_length(unresolved N3)src/cleveragents/domain/models/acms/crp.py:416-419— The H5 fix addedmax_length=500to list fields, but thequerystring (primary user-facing free-text input) was missed. A multi-gigabyte string can exhaust memory. Same applies topurposefield (line ~489).Fix: Add
max_length=10_000(or appropriate limit) toqueryandmax_length=2_000topurpose.F4. Inner-function imports violate CONTRIBUTING.md (unresolved N4)
features/steps/uko_l2_detail_level_steps.py:310, 318, 331— Three imports inside function bodies. CONTRIBUTING.md (lines 1289-1294) absolutely forbids this (onlyif TYPE_CHECKING:exception). Lines 310 and 318 are also duplicates of each other.Fix: Move all three imports to the top of the file; deduplicate
DetailLevelCycleErrorimport.F5. Robot helper uses bare
except Exceptionwithout re-raising (unresolved N5)robot/helper_uko_layer2_paradigm.py:58, 77, 102, 159, 200— All 5 command functions catch broadException, print a terse message, and return 1 without traceback. CONTRIBUTING.md (lines 496, 1382) explicitly prohibits this pattern.Fix: Either let exceptions propagate (centralize error handling in
main()only), or at minimum addtraceback.print_exc()and narrow the caught exception types.F6.
__setattr__re-freezes from raw inputvalue, not validatedself.levels(unresolved N6, elevated from P2 due to correctness risk)src/cleveragents/domain/models/acms/crp.py:167-172— Aftersuper().__setattr__(), Pydantic'svalidate_assignmentmay transformvaluebefore storing it. The re-freeze usesMappingProxyType(dict(value))(the raw input) instead ofMappingProxyType(dict(self.levels))(the validated result). When a caller passes aMappingProxyType, theisinstancecheck fails to detect the need for re-freezing, leavingself.levelsas a mutabledictfrom the Pydantic validator.Fix: Check
self.levelsafter super call:P2: Should Fix (7)
F7.
effective_levels()has no cycle guard —RecursionErroron circular parentssrc/cleveragents/domain/models/acms/crp.py:246-257—resolve()has avisitedset for cycle detection, buteffective_levels()recurses throughself.parent.effective_levels()with no guard. A circular parent chain causesRecursionError.Fix: Add a visited-set guard mirroring
resolve(), raisingDetailLevelCycleError.F8.
__all__sorting violations in 3 files (unresolved N9)src/cleveragents/acms/uko/vocabularies.py:22-41—ParadigmVocabulary(P) should come beforeUKO_*(U) in ASCII ordersrc/cleveragents/acms/uko/detail_level_maps.py:32-39—DetailLevelMapBuilder(D) should come afterCODE_*(C) and beforeFUNC_*(F)src/cleveragents/acms/uko/__init__.py:38-52— Same cascaded issueFix: Sort all
__all__lists by ASCII order per CONTRIBUTING.md.F9. Per-item string lengths in list fields unbounded (unresolved N15, elevated to P2)
src/cleveragents/domain/models/acms/crp.py:420-479—entities,uko_types,focus,preferred_strategies,required_backendshavemax_length=500(list cap), but individual strings have no length limit. 500 items of 10 MB each = 5 GB allocation.Fix: Use
Annotated[str, StringConstraints(max_length=2_000)]for list items.F10.
effective_levels()return type change not documented as breaking (unresolved N10)CHANGELOG.md:17-26— The return type changed fromdict[str, int]toMappingProxyType[str, int]. Callers relying on mutation will getTypeError. Not mentioned in CHANGELOG.Fix: Add a note: "Breaking:
DetailLevelMap.effective_levels()now returnsMappingProxyType(read-only) instead ofdict."F11. Missing test coverage for bad URI schemes on secondary fields (unresolved N11)
features/acms/uko_layer2_paradigm_vocabularies.feature— Tests cover non-HTTP rejection onVocabularyClass.uriandVocabularyProperty.uri, but not onparent_uris,domain_uri,range_uri, orsub_property_of.Fix: Add 4 scenarios testing non-HTTP rejection on each secondary URI field.
F12.
VocabularyRegistry.register()raises bareValueError(unresolved N12)src/cleveragents/acms/uko/vocabulary_registry.py:67-72— No domain-specific exception. Per CONTRIBUTING.md's fail-fast principles, domain operations should raise specific error types.Fix: Define
DuplicateVocabularyError(ValueError)and raise it instead.F13. Missing
deepcopyand JSON roundtrip testsNo test verifies
copy.deepcopy(DetailLevelMap(...))succeeds, and no test roundtripsmodel_dump_json()throughmodel_validate_json(). Both are important for theMappingProxyType+ Lock combination.Fix: Add scenarios for both deep-copy and JSON roundtrip.
P3: Nits (6)
F14.
crp.py:199-200—resolve()doesn't clamp negative integer depths.resolve(-5)returns-5. Fix:return max(0, min(depth, self.max_depth)).F15.
crp.py:158—__setattr__usesvalue: objectinstead of Pydantic'svalue: Any. Minor type inconsistency.F16.
crp.py:222-244—register()acceptsvalue > max_depthwithout warning. A level registered at depth 100 withmax_depth=9would never be resolved.F17.
vocabularies.py:241-244—ParadigmVocabulary.irihas no URI scheme validation, unlike all other URI fields. Inconsistent.F18.
detail_level_maps.py:44,73—_CODE_MAX_DEPTH = 9is hardcoded separately from_CODE_LEVELS. Should derive:max(_CODE_LEVELS.values()).F19.
vocabularies.py:336,399,442—"uko-code:"magic string repeated 3 times without referencing the_CODE_DOMAINconstant fromdetail_level_maps.py.Static Analysis
Summary
Verdict: REQUEST_CHANGES — The 6 P1 items (missing exports, deepcopy crash, unbounded query, CONTRIBUTING.md violations,
__setattr__correctness) must be resolved. Most are straightforward fixes. The spec compliance and overall code quality are strong — this is close to merge-ready.Third-Round Review Response (Reviews #2140 + #2141)
All 20 findings from Brent Edwards' third-round review have been addressed in commit
2f34170e.P1 Fixes
DetailLevelError/DetailLevelCycleErrornot exported from__init__.py__all__, and docstringdeepcopy/pickle/model_copy(deep=True)crash onDetailLevelMap__copy__and__deepcopy__overridesqueryfield has nomax_lengthmax_length=10_000constantuko_l2_detail_level_steps.pyexcept Exceptionwithout re-raisingtraceback.print_exc()for diagnostic outputP2 Fixes
__setattr__re-freezes fromvaluenotself.levelsself.levelscapture_error()suppresses exceptions__all__not sorted in 3 fileseffective_levels()return type change not documentedVocabularyRegistryraises bareValueErrorDuplicateVocabularyError(ValueError)subclassP3 Fixes
__setattr__value: objectvsvalue: AnyAnyregister()doesn't enforcevalue <= max_depthmax_length_BoundedStr = Annotated[str, StringConstraints(max_length=2000)]on all 5 list fields_validate_http_urilacks SSRF noterdfs:commentuko.ttlfor dual inheritancetry/exceptinconsistent withcapture_error()Additional Improvement
DetailLevelMap,DetailDepth,DetailLevelError, andDetailLevelCycleErrorfromcrp.py(601 lines) into newdetail_level.py(267 lines), bringingcrp.pydown to 364 lines. All existing import paths preserved via re-exports. This addresses the CONTRIBUTING.md 500-line file limit.Quality Gates
nox -s lint-- PASSnox -s typecheck-- PASSbehave features/acms/uko_layer2_paradigm_vocabularies.feature-- PASSbehave features/uko_ontology.feature-- PASSbehave features/crp_models.feature-- PASSbehave features/unified_context_models.feature-- PASSbehave features/depth_breadth_projection.feature-- PASSbehave features/context_strategy_registry.feature-- PASSbehave features/uko_ontology_registry.feature-- PASSResponse to Rui Hu Review #2152 (commit
49f24c9d)Thanks for the thorough review, @hurui200320. 12 of the 19 findings overlap with Brent Edwards' reviews #2140/#2141 and were already addressed in commit
2f34170e. The remaining findings have been evaluated and resolved below.Findings Already Fixed (12 -- overlap with Brent Edwards N1-N20)
These were resolved in commit
2f34170e(pushed before review #2152):__init__.pydeepcopy/picklecrash__copy__,__deepcopy__)except Exceptiontraceback.print_exc())__setattr__re-freezes from raw valueself.levels)__all__sorting violations_BoundedStr)effective_levels()return type not documentedValueErrorin registryDuplicateVocabularyError)value: objectvsvalue: Anyregister()acceptsvalue > max_depthNew Findings Fixed in
49f24c9d(5)purposefield missingmax_lengthmax_length=_MAX_ITEM_LENGTH(2,000).querywas already fixed to 10,000 in the prior commit.effective_levels()has no cycle guard_visited: set[int]parameter withDetailLevelCycleErroron cycle detection, mirroringresolve().deepcopytest__copy__/__deepcopy__:model_copy(deep=False)internally calls__copy__(), so we now construct viaDetailLevelMap(...)directly.resolve()doesn't clamp negative intsmax(0, min(depth, self.max_depth)).ParadigmVocabulary.irino URI validation_validate_http_urifield validator oniri.Findings Kept As-Is With Rationale (2)
F18 (P3):
_CODE_MAX_DEPTH = 9hardcoded separately from_CODE_LEVELSKept as-is. The
max_depth=9value comes directly from the specification (spec lines 24970-24985) and is an independent semantic property of the domain -- it means "the maximum meaningful detail depth for the uko-code domain is 9." While it happens to equalmax(_CODE_LEVELS.values())today, these are conceptually distinct:max_depthis a domain constraint from the spec, not a derived property of the current level set. Deriving it would invert that relationship and silently change semantics if a level were added or removed. Hardcoding the spec value makes the spec dependency explicit.F19 (P3):
"uko-code:"string repeated 3 times invocabularies.pyKept as-is.
_CODE_DOMAINexists indetail_level_maps.py, but importing it intovocabularies.pywould create a cross-module coupling between two sibling modules that are currently independent (vocabularies.pydefines vocabulary data models;detail_level_maps.pydefines builder/map logic). The string"uko-code:"is a stable specification constant (the Layer 1 domain prefix), not a value that drifts. Introducing a shared constants module for a single 10-character string adds indirection without meaningful safety gain.Quality Gates
nox -s lint-- PASSnox -s typecheck-- PASSbehave features/acms/uko_layer2_paradigm_vocabularies.feature-- PASS (105 scenarios)behave features/crp_models.feature-- PASSbehave features/uko_ontology.feature-- PASSbehave features/unified_context_models.feature-- PASSPM Status — Day 32
Review Progress
This PR has been through 3 review rounds with thorough findings from @brent.edwards (2 rounds) and @hurui200320 (1 round):
Current Blocking Items (consolidated from Rui's review)
6 P1 findings remain unresolved:
DetailLevelError/DetailLevelCycleErrornot exported from__init__.pydeepcopy/picklecrash onDetailLevelMap(threading.Lock)ContextRequest.queryhas nomax_lengthexcept Exceptionwithout re-raising__setattr__re-freezes from raw input, not validated valueLabels Added
Action Required
@hamza.khyari: Please address the 6 P1 findings from Rui's review (#2152). Most are straightforward fixes (import moves, max_length addition, exception export). This PR is in an overdue milestone (M6, due Mar 10) and blocks ACMS pipeline completeness. The sooner these are resolved, the sooner we can approve and merge.
Blockers Status -- All 6 P1 Items Already Resolved
@freemo -- all 6 P1 findings listed in your Day 32 status are already fixed. They were addressed in commits
2f34170e(pushed 13:08 UTC) and49f24c9d(pushed 13:34 UTC), both before your comment.Details in response comments #59807 (Brent's N1-N20) and #59861 (Rui's F1-F19).
2f34170e__all__, docstring inacms/__init__.py2f34170e+49f24c9d__copy__/__deepcopy__; fixed model_copy recursion2f34170e+49f24c9dmax_length=10_000; purpose:max_length=2_0002f34170e2f34170etraceback.print_exc()to all 5 handlers2f34170eself.levels(validated) not rawvalueAll quality gates pass (lint, typecheck, 105 behave scenarios). Ready for re-review or merge approval.
49f24c9d9ctoad76dcdc8dNew commits pushed, approval review dismissed automatically according to repository settings
ad76dcdc8dto3c014a9565