atdd 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- atdd/__init__.py +0 -0
- atdd/cli.py +404 -0
- atdd/coach/__init__.py +0 -0
- atdd/coach/commands/__init__.py +0 -0
- atdd/coach/commands/add_persistence_metadata.py +215 -0
- atdd/coach/commands/analyze_migrations.py +188 -0
- atdd/coach/commands/consumers.py +720 -0
- atdd/coach/commands/infer_governance_status.py +149 -0
- atdd/coach/commands/initializer.py +177 -0
- atdd/coach/commands/interface.py +1078 -0
- atdd/coach/commands/inventory.py +565 -0
- atdd/coach/commands/migration.py +240 -0
- atdd/coach/commands/registry.py +1560 -0
- atdd/coach/commands/session.py +430 -0
- atdd/coach/commands/sync.py +405 -0
- atdd/coach/commands/test_interface.py +399 -0
- atdd/coach/commands/test_runner.py +141 -0
- atdd/coach/commands/tests/__init__.py +1 -0
- atdd/coach/commands/tests/test_telemetry_array_validation.py +235 -0
- atdd/coach/commands/traceability.py +4264 -0
- atdd/coach/conventions/session.convention.yaml +754 -0
- atdd/coach/overlays/__init__.py +2 -0
- atdd/coach/overlays/claude.md +2 -0
- atdd/coach/schemas/config.schema.json +34 -0
- atdd/coach/schemas/manifest.schema.json +101 -0
- atdd/coach/templates/ATDD.md +282 -0
- atdd/coach/templates/SESSION-TEMPLATE.md +327 -0
- atdd/coach/utils/__init__.py +0 -0
- atdd/coach/utils/graph/__init__.py +0 -0
- atdd/coach/utils/graph/urn.py +875 -0
- atdd/coach/validators/__init__.py +0 -0
- atdd/coach/validators/shared_fixtures.py +365 -0
- atdd/coach/validators/test_enrich_wagon_registry.py +167 -0
- atdd/coach/validators/test_registry.py +575 -0
- atdd/coach/validators/test_session_validation.py +1183 -0
- atdd/coach/validators/test_traceability.py +448 -0
- atdd/coach/validators/test_update_feature_paths.py +108 -0
- atdd/coach/validators/test_validate_contract_consumers.py +297 -0
- atdd/coder/__init__.py +1 -0
- atdd/coder/conventions/adapter.recipe.yaml +88 -0
- atdd/coder/conventions/backend.convention.yaml +460 -0
- atdd/coder/conventions/boundaries.convention.yaml +666 -0
- atdd/coder/conventions/commons.convention.yaml +460 -0
- atdd/coder/conventions/complexity.recipe.yaml +109 -0
- atdd/coder/conventions/component-naming.convention.yaml +178 -0
- atdd/coder/conventions/design.convention.yaml +327 -0
- atdd/coder/conventions/design.recipe.yaml +273 -0
- atdd/coder/conventions/dto.convention.yaml +660 -0
- atdd/coder/conventions/frontend.convention.yaml +542 -0
- atdd/coder/conventions/green.convention.yaml +1012 -0
- atdd/coder/conventions/presentation.convention.yaml +587 -0
- atdd/coder/conventions/refactor.convention.yaml +535 -0
- atdd/coder/conventions/technology.convention.yaml +206 -0
- atdd/coder/conventions/tests/__init__.py +0 -0
- atdd/coder/conventions/tests/test_adapter_recipe.py +302 -0
- atdd/coder/conventions/tests/test_complexity_recipe.py +289 -0
- atdd/coder/conventions/tests/test_component_taxonomy.py +278 -0
- atdd/coder/conventions/tests/test_component_urn_naming.py +165 -0
- atdd/coder/conventions/tests/test_thinness_recipe.py +286 -0
- atdd/coder/conventions/thinness.recipe.yaml +82 -0
- atdd/coder/conventions/train.convention.yaml +325 -0
- atdd/coder/conventions/verification.protocol.yaml +53 -0
- atdd/coder/schemas/design_system.schema.json +361 -0
- atdd/coder/validators/__init__.py +0 -0
- atdd/coder/validators/test_commons_structure.py +485 -0
- atdd/coder/validators/test_complexity.py +416 -0
- atdd/coder/validators/test_cross_language_consistency.py +431 -0
- atdd/coder/validators/test_design_system_compliance.py +413 -0
- atdd/coder/validators/test_dto_testing_patterns.py +268 -0
- atdd/coder/validators/test_green_cross_stack_layers.py +168 -0
- atdd/coder/validators/test_green_layer_dependencies.py +148 -0
- atdd/coder/validators/test_green_python_layer_structure.py +103 -0
- atdd/coder/validators/test_green_supabase_layer_structure.py +103 -0
- atdd/coder/validators/test_import_boundaries.py +396 -0
- atdd/coder/validators/test_init_file_urns.py +593 -0
- atdd/coder/validators/test_preact_layer_boundaries.py +221 -0
- atdd/coder/validators/test_presentation_convention.py +260 -0
- atdd/coder/validators/test_python_architecture.py +674 -0
- atdd/coder/validators/test_quality_metrics.py +420 -0
- atdd/coder/validators/test_station_master_pattern.py +244 -0
- atdd/coder/validators/test_train_infrastructure.py +454 -0
- atdd/coder/validators/test_train_urns.py +293 -0
- atdd/coder/validators/test_typescript_architecture.py +616 -0
- atdd/coder/validators/test_usecase_structure.py +421 -0
- atdd/coder/validators/test_wagon_boundaries.py +586 -0
- atdd/conftest.py +126 -0
- atdd/planner/__init__.py +1 -0
- atdd/planner/conventions/acceptance.convention.yaml +538 -0
- atdd/planner/conventions/appendix.convention.yaml +187 -0
- atdd/planner/conventions/artifact-naming.convention.yaml +852 -0
- atdd/planner/conventions/component.convention.yaml +670 -0
- atdd/planner/conventions/criteria.convention.yaml +141 -0
- atdd/planner/conventions/feature.convention.yaml +371 -0
- atdd/planner/conventions/interface.convention.yaml +382 -0
- atdd/planner/conventions/steps.convention.yaml +141 -0
- atdd/planner/conventions/train.convention.yaml +552 -0
- atdd/planner/conventions/wagon.convention.yaml +275 -0
- atdd/planner/conventions/wmbt.convention.yaml +258 -0
- atdd/planner/schemas/acceptance.schema.json +336 -0
- atdd/planner/schemas/appendix.schema.json +78 -0
- atdd/planner/schemas/component.schema.json +114 -0
- atdd/planner/schemas/feature.schema.json +197 -0
- atdd/planner/schemas/train.schema.json +192 -0
- atdd/planner/schemas/wagon.schema.json +281 -0
- atdd/planner/schemas/wmbt.schema.json +59 -0
- atdd/planner/validators/__init__.py +0 -0
- atdd/planner/validators/conftest.py +5 -0
- atdd/planner/validators/test_draft_wagon_registry.py +374 -0
- atdd/planner/validators/test_plan_cross_refs.py +240 -0
- atdd/planner/validators/test_plan_uniqueness.py +224 -0
- atdd/planner/validators/test_plan_urn_resolution.py +268 -0
- atdd/planner/validators/test_plan_wagons.py +174 -0
- atdd/planner/validators/test_train_validation.py +514 -0
- atdd/planner/validators/test_wagon_urn_chain.py +648 -0
- atdd/planner/validators/test_wmbt_consistency.py +327 -0
- atdd/planner/validators/test_wmbt_vocabulary.py +632 -0
- atdd/tester/__init__.py +1 -0
- atdd/tester/conventions/artifact.convention.yaml +257 -0
- atdd/tester/conventions/contract.convention.yaml +1009 -0
- atdd/tester/conventions/filename.convention.yaml +555 -0
- atdd/tester/conventions/migration.convention.yaml +509 -0
- atdd/tester/conventions/red.convention.yaml +797 -0
- atdd/tester/conventions/routing.convention.yaml +51 -0
- atdd/tester/conventions/telemetry.convention.yaml +458 -0
- atdd/tester/schemas/a11y.tmpl.json +17 -0
- atdd/tester/schemas/artifact.schema.json +189 -0
- atdd/tester/schemas/contract.schema.json +591 -0
- atdd/tester/schemas/contract.tmpl.json +95 -0
- atdd/tester/schemas/db.tmpl.json +20 -0
- atdd/tester/schemas/e2e.tmpl.json +17 -0
- atdd/tester/schemas/edge_function.tmpl.json +17 -0
- atdd/tester/schemas/event.tmpl.json +17 -0
- atdd/tester/schemas/http.tmpl.json +19 -0
- atdd/tester/schemas/job.tmpl.json +18 -0
- atdd/tester/schemas/load.tmpl.json +21 -0
- atdd/tester/schemas/metric.tmpl.json +19 -0
- atdd/tester/schemas/pack.schema.json +139 -0
- atdd/tester/schemas/realtime.tmpl.json +20 -0
- atdd/tester/schemas/rls.tmpl.json +18 -0
- atdd/tester/schemas/script.tmpl.json +16 -0
- atdd/tester/schemas/sec.tmpl.json +18 -0
- atdd/tester/schemas/storage.tmpl.json +18 -0
- atdd/tester/schemas/telemetry.schema.json +128 -0
- atdd/tester/schemas/telemetry_tracking_manifest.schema.json +143 -0
- atdd/tester/schemas/test_filename.schema.json +194 -0
- atdd/tester/schemas/test_intent.schema.json +179 -0
- atdd/tester/schemas/unit.tmpl.json +18 -0
- atdd/tester/schemas/visual.tmpl.json +18 -0
- atdd/tester/schemas/ws.tmpl.json +17 -0
- atdd/tester/utils/__init__.py +0 -0
- atdd/tester/utils/filename.py +300 -0
- atdd/tester/validators/__init__.py +0 -0
- atdd/tester/validators/cleanup_duplicate_headers.py +116 -0
- atdd/tester/validators/cleanup_duplicate_headers_v2.py +135 -0
- atdd/tester/validators/conftest.py +5 -0
- atdd/tester/validators/coverage_gap_report.py +321 -0
- atdd/tester/validators/fix_dual_ac_references.py +179 -0
- atdd/tester/validators/remove_duplicate_lines.py +93 -0
- atdd/tester/validators/test_acceptance_urn_filename_mapping.py +359 -0
- atdd/tester/validators/test_acceptance_urn_separator.py +166 -0
- atdd/tester/validators/test_artifact_naming_category.py +307 -0
- atdd/tester/validators/test_contract_schema_compliance.py +706 -0
- atdd/tester/validators/test_contracts_structure.py +200 -0
- atdd/tester/validators/test_coverage_adequacy.py +797 -0
- atdd/tester/validators/test_dual_ac_reference.py +225 -0
- atdd/tester/validators/test_fixture_validity.py +372 -0
- atdd/tester/validators/test_isolation.py +487 -0
- atdd/tester/validators/test_migration_coverage.py +204 -0
- atdd/tester/validators/test_migration_criteria.py +276 -0
- atdd/tester/validators/test_migration_generation.py +116 -0
- atdd/tester/validators/test_python_test_naming.py +410 -0
- atdd/tester/validators/test_red_layer_validation.py +95 -0
- atdd/tester/validators/test_red_python_layer_structure.py +87 -0
- atdd/tester/validators/test_red_supabase_layer_structure.py +90 -0
- atdd/tester/validators/test_telemetry_structure.py +634 -0
- atdd/tester/validators/test_typescript_test_naming.py +301 -0
- atdd/tester/validators/test_typescript_test_structure.py +84 -0
- atdd-0.1.0.dist-info/METADATA +191 -0
- atdd-0.1.0.dist-info/RECORD +183 -0
- atdd-0.1.0.dist-info/WHEEL +5 -0
- atdd-0.1.0.dist-info/entry_points.txt +2 -0
- atdd-0.1.0.dist-info/licenses/LICENSE +674 -0
- atdd-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
name: "Acceptance Criteria Blocks"
|
|
3
|
+
description: "Reusable acceptance scaffolding primitives (planes, harness defaults, metrics)."
|
|
4
|
+
|
|
5
|
+
defaults:
|
|
6
|
+
given:
|
|
7
|
+
auth:
|
|
8
|
+
scopes: []
|
|
9
|
+
builders: []
|
|
10
|
+
time: {}
|
|
11
|
+
stubbing:
|
|
12
|
+
policy: strict
|
|
13
|
+
overrides: []
|
|
14
|
+
knobs: {}
|
|
15
|
+
|
|
16
|
+
planes:
|
|
17
|
+
keywords:
|
|
18
|
+
presentation: ["display", "visible", "screen", "render", "animation", "button", "form", "modal"]
|
|
19
|
+
application: ["workflow", "orchestrate", "use case", "policy", "state", "saga"]
|
|
20
|
+
domain: ["rule", "validate", "aggregate", "entity", "invariant", "business"]
|
|
21
|
+
integration: ["database", "persist", "external", "queue", "api", "webhook", "repository"]
|
|
22
|
+
sequence:
|
|
23
|
+
presentation: command
|
|
24
|
+
application: use_case
|
|
25
|
+
domain: validate
|
|
26
|
+
integration: persist
|
|
27
|
+
|
|
28
|
+
harnesses:
|
|
29
|
+
http:
|
|
30
|
+
layers: ["presentation", "application", "domain", "integration"]
|
|
31
|
+
given:
|
|
32
|
+
auth:
|
|
33
|
+
scopes: ["purchase:create"]
|
|
34
|
+
when:
|
|
35
|
+
method: POST
|
|
36
|
+
path: "/api/example"
|
|
37
|
+
headers: {"Content-Type": "application/json"}
|
|
38
|
+
body: {sample: true}
|
|
39
|
+
then:
|
|
40
|
+
- kind: status
|
|
41
|
+
expect: 200
|
|
42
|
+
- kind: body
|
|
43
|
+
expect: {ok: true}
|
|
44
|
+
unit:
|
|
45
|
+
layers: ["application", "domain"]
|
|
46
|
+
when:
|
|
47
|
+
target: "Service.method"
|
|
48
|
+
args: {payload: {sample: true}}
|
|
49
|
+
then:
|
|
50
|
+
- kind: result
|
|
51
|
+
expect: {ok: true}
|
|
52
|
+
event:
|
|
53
|
+
layers: ["application", "integration"]
|
|
54
|
+
when:
|
|
55
|
+
topic: "sample.event"
|
|
56
|
+
payload: {sample: true}
|
|
57
|
+
then:
|
|
58
|
+
- kind: event
|
|
59
|
+
expect: "sample.event"
|
|
60
|
+
ws:
|
|
61
|
+
layers: ["integration"]
|
|
62
|
+
when:
|
|
63
|
+
url: "ws://example/events"
|
|
64
|
+
subscribe_msg: {action: "subscribe", channel: "updates"}
|
|
65
|
+
then:
|
|
66
|
+
- kind: message
|
|
67
|
+
expect: {frame: "connected"}
|
|
68
|
+
e2e:
|
|
69
|
+
layers: ["presentation", "application", "domain", "integration"]
|
|
70
|
+
when:
|
|
71
|
+
url: "http://example/ui"
|
|
72
|
+
actions: ["fill #field", "click #submit"]
|
|
73
|
+
then:
|
|
74
|
+
- kind: visual
|
|
75
|
+
expect: "success-banner"
|
|
76
|
+
a11y:
|
|
77
|
+
layers: ["presentation"]
|
|
78
|
+
when: {}
|
|
79
|
+
then:
|
|
80
|
+
- kind: a11y
|
|
81
|
+
expect: "passes"
|
|
82
|
+
visual:
|
|
83
|
+
layers: ["presentation"]
|
|
84
|
+
when: {}
|
|
85
|
+
then:
|
|
86
|
+
- kind: snapshot
|
|
87
|
+
expect: "unchanged"
|
|
88
|
+
metric:
|
|
89
|
+
layers: ["application", "integration"]
|
|
90
|
+
when: {}
|
|
91
|
+
then:
|
|
92
|
+
- kind: metric
|
|
93
|
+
expect: "metric:placeholder"
|
|
94
|
+
job:
|
|
95
|
+
layers: ["application", "integration"]
|
|
96
|
+
when: {}
|
|
97
|
+
then:
|
|
98
|
+
- kind: status
|
|
99
|
+
expect: "completed"
|
|
100
|
+
db:
|
|
101
|
+
layers: ["integration", "domain"]
|
|
102
|
+
when: {}
|
|
103
|
+
then:
|
|
104
|
+
- kind: rows
|
|
105
|
+
expect: "updated"
|
|
106
|
+
sec:
|
|
107
|
+
layers: ["application", "integration"]
|
|
108
|
+
when: {}
|
|
109
|
+
then:
|
|
110
|
+
- kind: security
|
|
111
|
+
expect: "granted"
|
|
112
|
+
load:
|
|
113
|
+
layers: ["integration", "application"]
|
|
114
|
+
when: {}
|
|
115
|
+
then:
|
|
116
|
+
- kind: metrics
|
|
117
|
+
expect: "within_limits"
|
|
118
|
+
script:
|
|
119
|
+
layers: ["application"]
|
|
120
|
+
when: {}
|
|
121
|
+
then:
|
|
122
|
+
- kind: status
|
|
123
|
+
expect: 0
|
|
124
|
+
|
|
125
|
+
metrics:
|
|
126
|
+
time:
|
|
127
|
+
minimize: metric:latency_p50
|
|
128
|
+
maximize: metric:latency_increase
|
|
129
|
+
likelihood:
|
|
130
|
+
maximize: metric:success_ratio
|
|
131
|
+
minimize: metric:error_ratio
|
|
132
|
+
effort:
|
|
133
|
+
decrease: metric:user_steps
|
|
134
|
+
"frequency":
|
|
135
|
+
decrease: metric:occurrence_rate
|
|
136
|
+
"quantity / amount":
|
|
137
|
+
decrease: metric:scrap_rate
|
|
138
|
+
maximize: metric:throughput
|
|
139
|
+
"financial value":
|
|
140
|
+
minimize: metric:cost_per_unit
|
|
141
|
+
maximize: metric:net_margin
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
name: "Feature Convention"
|
|
3
|
+
description: "Convention for feature assembly from WMBTs"
|
|
4
|
+
|
|
5
|
+
# Feature structure defined in schema
|
|
6
|
+
structure:
|
|
7
|
+
$ref: "schemas:planner:feature"
|
|
8
|
+
|
|
9
|
+
# URN naming pattern
|
|
10
|
+
urn_naming:
|
|
11
|
+
pattern: "feature:{wagon}:{feature}"
|
|
12
|
+
description: "Unique identifier for feature within wagon hierarchy"
|
|
13
|
+
utility: "utils.graph.URNBuilder.feature(wagon_id, feature_id)"
|
|
14
|
+
|
|
15
|
+
parts:
|
|
16
|
+
wagon: "Parent wagon identifier (kebab-case)"
|
|
17
|
+
feature: "Feature identifier (kebab-case, verb-object pattern)"
|
|
18
|
+
|
|
19
|
+
examples:
|
|
20
|
+
- urn: "feature:resolve-dilemmas:choose-option"
|
|
21
|
+
wagon: "resolve-dilemmas"
|
|
22
|
+
feature: "choose-option"
|
|
23
|
+
|
|
24
|
+
- urn: "feature:manage-inventory:track-stock"
|
|
25
|
+
wagon: "manage-inventory"
|
|
26
|
+
feature: "track-stock"
|
|
27
|
+
|
|
28
|
+
- urn: "feature:manage-users:authenticate-user"
|
|
29
|
+
wagon: "manage-users"
|
|
30
|
+
feature: "authenticate-user"
|
|
31
|
+
|
|
32
|
+
validation:
|
|
33
|
+
pattern: "^feature:[a-z][a-z0-9-]*:[a-z][a-z0-9-]*$"
|
|
34
|
+
format: "kebab-case for both wagon and feature"
|
|
35
|
+
|
|
36
|
+
# Artifact seeds for feature naming
|
|
37
|
+
artifact_seeds:
|
|
38
|
+
description: "Artifacts are the primary seeds for feature names"
|
|
39
|
+
overview: |
|
|
40
|
+
Feature names are derived from wagon produce/consume artifacts.
|
|
41
|
+
The artifact type determines which verbs are appropriate.
|
|
42
|
+
Features follow verb-object pattern where object comes from artifact domain or resource.
|
|
43
|
+
|
|
44
|
+
verb_selection:
|
|
45
|
+
by_artifact_type:
|
|
46
|
+
events:
|
|
47
|
+
description: "Past tense artifacts indicate completed actions or state transitions"
|
|
48
|
+
verbs: ["publish", "emit", "start", "close", "trigger", "notify"]
|
|
49
|
+
examples:
|
|
50
|
+
- artifact: "match:started"
|
|
51
|
+
feature: "start-match"
|
|
52
|
+
rationale: "Event 'started' suggests action 'start'"
|
|
53
|
+
|
|
54
|
+
- artifact: "wallet:credited"
|
|
55
|
+
feature: "credit-wallet"
|
|
56
|
+
rationale: "Event 'credited' suggests action 'credit'"
|
|
57
|
+
|
|
58
|
+
states:
|
|
59
|
+
description: "Adjectives or present participles indicating ongoing conditions"
|
|
60
|
+
verbs: ["track", "monitor", "maintain", "update", "manage"]
|
|
61
|
+
examples:
|
|
62
|
+
- artifact: "mechanic:timebank.remaining"
|
|
63
|
+
feature: "track-timebank"
|
|
64
|
+
rationale: "State 'remaining' requires tracking"
|
|
65
|
+
|
|
66
|
+
- artifact: "session:active"
|
|
67
|
+
feature: "maintain-session"
|
|
68
|
+
rationale: "State 'active' requires maintenance"
|
|
69
|
+
|
|
70
|
+
data:
|
|
71
|
+
description: "Nouns representing entities or information"
|
|
72
|
+
verbs: ["create", "manage", "process", "handle", "make", "generate"]
|
|
73
|
+
examples:
|
|
74
|
+
- artifact: "mechanic:decision.choice"
|
|
75
|
+
feature: "make-choice"
|
|
76
|
+
rationale: "Data 'choice' is made/created"
|
|
77
|
+
|
|
78
|
+
- artifact: "player:profile"
|
|
79
|
+
feature: "manage-profile"
|
|
80
|
+
rationale: "Data 'profile' is managed"
|
|
81
|
+
|
|
82
|
+
configs:
|
|
83
|
+
description: "Configuration or settings nouns"
|
|
84
|
+
verbs: ["configure", "setup", "initialize", "define", "establish"]
|
|
85
|
+
examples:
|
|
86
|
+
- artifact: "match:config"
|
|
87
|
+
feature: "configure-match"
|
|
88
|
+
rationale: "Config is configured/setup"
|
|
89
|
+
|
|
90
|
+
- artifact: "league:config"
|
|
91
|
+
feature: "define-league"
|
|
92
|
+
rationale: "Config defines league parameters"
|
|
93
|
+
|
|
94
|
+
transformation_guidance:
|
|
95
|
+
step_1: "Identify artifact from wagon produce/consume"
|
|
96
|
+
step_2: "Determine artifact type: event, state, data, or config"
|
|
97
|
+
step_3: "Select appropriate verb from type-specific verb list"
|
|
98
|
+
step_4: "Choose object: use domain OR resource depending on focus"
|
|
99
|
+
step_5: "Combine as: {verb}-{object} in kebab-case"
|
|
100
|
+
|
|
101
|
+
examples:
|
|
102
|
+
- wagon: "resolve-dilemmas"
|
|
103
|
+
artifact: "mechanic:decision.choice"
|
|
104
|
+
type: "data"
|
|
105
|
+
verb: "make"
|
|
106
|
+
object: "choice"
|
|
107
|
+
feature: "make-choice"
|
|
108
|
+
|
|
109
|
+
- wagon: "burn-timebank"
|
|
110
|
+
artifact: "mechanic:timebank.remaining"
|
|
111
|
+
type: "state"
|
|
112
|
+
verb: "track"
|
|
113
|
+
object: "timebank"
|
|
114
|
+
feature: "track-timebank"
|
|
115
|
+
|
|
116
|
+
- wagon: "play-match"
|
|
117
|
+
artifact: "match:started"
|
|
118
|
+
type: "event"
|
|
119
|
+
verb: "start"
|
|
120
|
+
object: "match"
|
|
121
|
+
feature: "start-match"
|
|
122
|
+
|
|
123
|
+
# Footprint limits defined in schema
|
|
124
|
+
footprint:
|
|
125
|
+
$ref: "schemas:planner:footprint"
|
|
126
|
+
|
|
127
|
+
# Component-centric footprint scoring with universal complexity rubric
|
|
128
|
+
footprint_scoring:
|
|
129
|
+
description: "Component-based architectural footprint using granular types from coder conventions"
|
|
130
|
+
|
|
131
|
+
complexity_rubric:
|
|
132
|
+
0: "Pure configuration/declaration (routes, dtos, events, ports, styles)"
|
|
133
|
+
0.5: "Simple transformation/validation (serializers, mappers, validators, hooks, filters)"
|
|
134
|
+
1: "Single-responsibility with business logic (controllers, services, clients, views)"
|
|
135
|
+
2: "Complex orchestration/state/persistence (use_cases, repositories, queues, workflows)"
|
|
136
|
+
3: "Very complex algorithms/integrations (engines with ML/graph/optimization)"
|
|
137
|
+
|
|
138
|
+
component_type_weights:
|
|
139
|
+
backend:
|
|
140
|
+
presentation:
|
|
141
|
+
controllers: 1
|
|
142
|
+
routes: 0
|
|
143
|
+
serializers: 0.5
|
|
144
|
+
validators: 0.5
|
|
145
|
+
middleware: 1
|
|
146
|
+
guards: 1
|
|
147
|
+
views: 1
|
|
148
|
+
|
|
149
|
+
application:
|
|
150
|
+
use_cases: 2
|
|
151
|
+
handlers: 1
|
|
152
|
+
ports: 0
|
|
153
|
+
dtos: 0
|
|
154
|
+
policies: 1
|
|
155
|
+
workflows: 2
|
|
156
|
+
|
|
157
|
+
domain:
|
|
158
|
+
entities: 1
|
|
159
|
+
value_objects: 0.5
|
|
160
|
+
aggregates: 2
|
|
161
|
+
services: 1
|
|
162
|
+
specifications: 0.5
|
|
163
|
+
events: 0
|
|
164
|
+
exceptions: 0
|
|
165
|
+
|
|
166
|
+
integration:
|
|
167
|
+
repositories: 2
|
|
168
|
+
clients: 1
|
|
169
|
+
caches: 0.5
|
|
170
|
+
engines: 3
|
|
171
|
+
formatters: 1
|
|
172
|
+
notifiers: 1
|
|
173
|
+
queues: 2
|
|
174
|
+
stores: 1
|
|
175
|
+
mappers: 0.5
|
|
176
|
+
schedulers: 2
|
|
177
|
+
monitors: 1
|
|
178
|
+
|
|
179
|
+
frontend:
|
|
180
|
+
presentation:
|
|
181
|
+
views: 1
|
|
182
|
+
components: 0.5
|
|
183
|
+
containers: 1
|
|
184
|
+
controllers: 2
|
|
185
|
+
routes: 0
|
|
186
|
+
layouts: 1
|
|
187
|
+
styles: 0
|
|
188
|
+
animations: 0.5
|
|
189
|
+
forms: 1
|
|
190
|
+
hooks: 0.5
|
|
191
|
+
directives: 0.5
|
|
192
|
+
filters: 0.5
|
|
193
|
+
|
|
194
|
+
application:
|
|
195
|
+
use_cases: 2
|
|
196
|
+
ports: 0
|
|
197
|
+
policies: 1
|
|
198
|
+
dtos: 0
|
|
199
|
+
|
|
200
|
+
domain:
|
|
201
|
+
entities: 1
|
|
202
|
+
value_objects: 0.5
|
|
203
|
+
services: 1
|
|
204
|
+
specifications: 0.5
|
|
205
|
+
exceptions: 0
|
|
206
|
+
|
|
207
|
+
integration:
|
|
208
|
+
repositories: 2
|
|
209
|
+
clients: 1
|
|
210
|
+
stores: 1
|
|
211
|
+
serializers: 0.5
|
|
212
|
+
mappers: 0.5
|
|
213
|
+
interceptors: 1
|
|
214
|
+
caches: 0.5
|
|
215
|
+
synchronizers: 2
|
|
216
|
+
monitors: 1
|
|
217
|
+
validators: 0.5
|
|
218
|
+
workers: 2
|
|
219
|
+
connectors: 1
|
|
220
|
+
|
|
221
|
+
calculation:
|
|
222
|
+
formula: "sum(component.count × weight[component.urn])"
|
|
223
|
+
rounding: "Round UP to nearest integer (ceiling function)"
|
|
224
|
+
examples:
|
|
225
|
+
integer: "2 controllers (2×1) + 1 repository (1×2) + 1 view (1×1) = 5 points → S bracket"
|
|
226
|
+
fractional: "3 serializers (3×0.5=1.5) + 2 controllers (2×1=2) = 3.5 → ceiling(3.5) = 4 points → S bracket"
|
|
227
|
+
|
|
228
|
+
brackets:
|
|
229
|
+
XS:
|
|
230
|
+
max: 5
|
|
231
|
+
description: "≤5 points"
|
|
232
|
+
S:
|
|
233
|
+
max: 10
|
|
234
|
+
description: "6-10 points"
|
|
235
|
+
M:
|
|
236
|
+
max: 15
|
|
237
|
+
description: "11-15 points — decompose if necessary"
|
|
238
|
+
L:
|
|
239
|
+
max: 25
|
|
240
|
+
description: "16-25 points — split"
|
|
241
|
+
XL:
|
|
242
|
+
min: 26
|
|
243
|
+
description: "≥26 points — split"
|
|
244
|
+
|
|
245
|
+
migration:
|
|
246
|
+
from_abstract_metrics: "Replaced screens/endpoints/tables with granular component types"
|
|
247
|
+
alignment:
|
|
248
|
+
old_endpoints: "controllers: 1"
|
|
249
|
+
old_new_tables: "repositories: 2"
|
|
250
|
+
old_screens: "views: 1"
|
|
251
|
+
old_async_jobs: "schedulers/queues/workers: 2"
|
|
252
|
+
|
|
253
|
+
# Sizing rules for features (agent-optimized)
|
|
254
|
+
sizing:
|
|
255
|
+
description: "Strict sizing rubric for AI agent work. Features MUST be S or smaller."
|
|
256
|
+
strategy: "blended"
|
|
257
|
+
rule: "Final feature size = max(WMBT size, Footprint size)"
|
|
258
|
+
final_size_rule: "max(wmbt_count_size, footprint_size)"
|
|
259
|
+
|
|
260
|
+
enforcement:
|
|
261
|
+
max_size: "S"
|
|
262
|
+
overflow_action: "Split or stage the feature before execution"
|
|
263
|
+
|
|
264
|
+
wmbt_brackets:
|
|
265
|
+
XS:
|
|
266
|
+
max: 5
|
|
267
|
+
description: "≤5 WMBTs"
|
|
268
|
+
S:
|
|
269
|
+
min: 6
|
|
270
|
+
max: 10
|
|
271
|
+
description: "6-10 WMBTs"
|
|
272
|
+
M:
|
|
273
|
+
min: 11
|
|
274
|
+
max: 20
|
|
275
|
+
description: "11-20 WMBTs — must be decomposed or staged"
|
|
276
|
+
L:
|
|
277
|
+
min: 21
|
|
278
|
+
description: ">20 WMBTs — split immediately"
|
|
279
|
+
|
|
280
|
+
approach:
|
|
281
|
+
pass1:
|
|
282
|
+
name: "Planning Pass"
|
|
283
|
+
description: "Size by WMBT-count to unblock decomposition"
|
|
284
|
+
pass2:
|
|
285
|
+
name: "Post-decomposition Pass"
|
|
286
|
+
description: "Compute footprint, reclassify size with max rule, gate M/L features"
|
|
287
|
+
|
|
288
|
+
constraints:
|
|
289
|
+
max_components: 8
|
|
290
|
+
max_events: 3
|
|
291
|
+
max_new_events: 3
|
|
292
|
+
description: "Each feature should have ≤8 components and emit/consume ≤3 new events"
|
|
293
|
+
|
|
294
|
+
hard_limits:
|
|
295
|
+
new_tables:
|
|
296
|
+
maximum: 2
|
|
297
|
+
rationale: "Carry high cost for maintenance, schema evolution, and performance impact"
|
|
298
|
+
async_jobs:
|
|
299
|
+
maximum: 2
|
|
300
|
+
rationale: "Add significant operational complexity (monitoring, retry logic, data inconsistency)"
|
|
301
|
+
integrations:
|
|
302
|
+
maximum: 2
|
|
303
|
+
rationale: "Introduce external dependencies, security vulnerabilities, and uncontrolled failure points"
|
|
304
|
+
|
|
305
|
+
# Grouping strategies
|
|
306
|
+
grouping_strategies:
|
|
307
|
+
by_step:
|
|
308
|
+
description: "Group WMBTs that share the same JTBD step"
|
|
309
|
+
max_per_group: 10
|
|
310
|
+
|
|
311
|
+
by_dimension:
|
|
312
|
+
description: "Group WMBTs that measure the same dimension"
|
|
313
|
+
max_per_group: 10
|
|
314
|
+
|
|
315
|
+
by_object:
|
|
316
|
+
description: "Group WMBTs that control the same object"
|
|
317
|
+
max_per_group: 10
|
|
318
|
+
|
|
319
|
+
by_coherence:
|
|
320
|
+
description: "Group WMBTs that form a coherent user story"
|
|
321
|
+
max_per_group: 10
|
|
322
|
+
|
|
323
|
+
# Naming patterns
|
|
324
|
+
naming:
|
|
325
|
+
pattern: "{verb}-{object}"
|
|
326
|
+
examples:
|
|
327
|
+
- "manage-inventory"
|
|
328
|
+
- "track-performance"
|
|
329
|
+
- "optimize-workflow"
|
|
330
|
+
|
|
331
|
+
grouping_heuristics:
|
|
332
|
+
heuristics:
|
|
333
|
+
- "Shared object of control (e.g., timebank, ability, score)"
|
|
334
|
+
- "Shared metric kind (latency, likelihood, effort)"
|
|
335
|
+
- "Shared plane/domain (ui, be, nw, etc.)"
|
|
336
|
+
- "Same user story or flow"
|
|
337
|
+
avoid: "Miscellaneous buckets — every feature must be user-facing and cohesive"
|
|
338
|
+
|
|
339
|
+
estimation:
|
|
340
|
+
from_wmbts:
|
|
341
|
+
display_animation: "likely screen/view"
|
|
342
|
+
apply_validate: "endpoint"
|
|
343
|
+
reconcile_persist: "table/migration"
|
|
344
|
+
notify_retry_queue: "async"
|
|
345
|
+
from_interfaces:
|
|
346
|
+
new_events: "event count"
|
|
347
|
+
external_consumes_produces: "integration points"
|
|
348
|
+
from_component_layers:
|
|
349
|
+
be_repository: "table/migration"
|
|
350
|
+
fe_presentation: "number of screens"
|
|
351
|
+
|
|
352
|
+
rationale:
|
|
353
|
+
wmbt_count:
|
|
354
|
+
always_present: "Every wagon enumerates WMBTs; early-stage features can be sized immediately"
|
|
355
|
+
scope_safety: "Prevents feature bloat by tying size to explicit outcomes"
|
|
356
|
+
decomposition_driver: "Maps cleanly to test coverage and acceptance criteria"
|
|
357
|
+
architectural_footprint:
|
|
358
|
+
effort_proxy: "Screens, endpoints, tables, migrations, async jobs correlate with build/test/deploy time"
|
|
359
|
+
risk_surface: "Storage schemas, migrations, background workers carry failure modes not visible in WMBTs"
|
|
360
|
+
coordination_cost: "Cross-cutting infra (authZ, observability, caching) scales with endpoints/tables"
|
|
361
|
+
|
|
362
|
+
schema_references:
|
|
363
|
+
feature: "schemas/planner/feature.schema.json"
|
|
364
|
+
note: "sizing field is defined inline in feature.schema.json (no separate sizing.schema.json)"
|
|
365
|
+
|
|
366
|
+
validation_rules:
|
|
367
|
+
- "size field must equal max(WMBT size, Footprint size)"
|
|
368
|
+
- "covers_wmbts determines WMBT size bracket"
|
|
369
|
+
- "footprint scores architectural complexity using point system"
|
|
370
|
+
- "Features exceeding component/event limits must be split"
|
|
371
|
+
- "Features exceeding hard limits (tables/jobs/integrations) MUST be split"
|