@tenkara/afm-linux-arm64 0.0.0-stage → 4.0.0-alpha.7
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.
- package/bin/afm +4 -0
- package/content/.coupling-baseline.tsv +1 -0
- package/content/.pending-commands.txt +2 -0
- package/content/CHANGELOG-archive.md +806 -0
- package/content/CHANGELOG.md +4256 -0
- package/content/PRINCIPLES.md +121 -0
- package/content/README-light.md +160 -0
- package/content/README.md +152 -0
- package/content/code-style/_any/file-size.md +62 -0
- package/content/code-style/_any/imports.md +68 -0
- package/content/code-style/_any/naming.md +72 -0
- package/content/code-style/_any/test-placement.md +57 -0
- package/content/code-style/nextjs-app-router/imports.md +50 -0
- package/content/code-style/nextjs-app-router/naming.md +50 -0
- package/content/code-style/prisma-postgres/error-boundary.md +55 -0
- package/content/code-style/prisma-postgres/imports.md +61 -0
- package/content/code-style/shadcn-ui/naming.md +48 -0
- package/content/code-style/stripe-billing/naming.md +76 -0
- package/content/code-style/trigger-dev-v4/imports.md +58 -0
- package/content/code-style/trigger-dev-v4/naming.md +49 -0
- package/content/code-style/trigger-dev-v4/test-placement.md +61 -0
- package/content/code-style/trpc-v11/error-boundary.md +51 -0
- package/content/code-style/trpc-v11/file-size.md +44 -0
- package/content/code-style/trpc-v11/naming.md +60 -0
- package/content/code-style/trpc-v11/test-placement.md +52 -0
- package/content/core/ach.md +265 -0
- package/content/core/afm.md +496 -0
- package/content/core/gotchas.md +18 -0
- package/content/core/prd.md +143 -0
- package/content/core/protocol.md +160 -0
- package/content/core/ust.md +65 -0
- package/content/guardrails/README.md +55 -0
- package/content/guardrails/dsl-com-ordem-obrigatoria.md +47 -0
- package/content/guardrails/exaustividade-de-union.md +48 -0
- package/content/guardrails/fronteira-de-import.md +57 -0
- package/content/hooks/README.md +72 -0
- package/content/interview/bootstrap.md +415 -0
- package/content/interview/promotion.md +117 -0
- package/content/interview/refactor.md +381 -0
- package/content/interview/triggers.md +109 -0
- package/content/modules/nextjs-app-router/ach.patch.md +44 -0
- package/content/modules/nextjs-app-router/gotchas.seed.md +78 -0
- package/content/modules/nextjs-app-router/rules.patch.md +35 -0
- package/content/modules/prisma-postgres/ach.patch.md +65 -0
- package/content/modules/prisma-postgres/rules.patch.md +28 -0
- package/content/modules/shadcn-ui/ach.patch.md +42 -0
- package/content/modules/stripe-billing/ach.patch.md +46 -0
- package/content/modules/stripe-billing/gotchas.seed.md +73 -0
- package/content/modules/stripe-billing/rules.patch.md +30 -0
- package/content/modules/trigger-dev-v4/ach.patch.md +64 -0
- package/content/modules/trigger-dev-v4/gotchas.seed.md +53 -0
- package/content/modules/trigger-dev-v4/rules.patch.md +35 -0
- package/content/modules/trpc-v11/ach.patch.md +56 -0
- package/content/modules/trpc-v11/rules.patch.md +34 -0
- package/content/modules/vireya-ui/ach.patch.md +85 -0
- package/content/modules/vireya-ui/gotchas.seed.md +98 -0
- package/content/modules/vireya-ui/rules.patch.md +36 -0
- package/content/ops/adr.md +54 -0
- package/content/ops/analyze.md +129 -0
- package/content/ops/clarify.md +86 -0
- package/content/ops/deliver.md +211 -0
- package/content/ops/diagnose.md +146 -0
- package/content/ops/evolve.md +317 -0
- package/content/ops/export-template.md +97 -0
- package/content/ops/generalize.md +120 -0
- package/content/ops/gotcha.md +46 -0
- package/content/ops/plan.md +61 -0
- package/content/ops/policy.md +63 -0
- package/content/ops/promote.md +72 -0
- package/content/ops/protocol.md +51 -0
- package/content/ops/reconcile.md +44 -0
- package/content/ops/reflect.md +180 -0
- package/content/ops/remediate.md +146 -0
- package/content/ops/restructure.md +145 -0
- package/content/ops/rule.md +165 -0
- package/content/ops/specify.md +62 -0
- package/content/ops/tasks.md +67 -0
- package/content/ops/update.md +223 -0
- package/content/ops/verify.md +69 -0
- package/content/patterns/adapter.md +46 -0
- package/content/patterns/facade.md +47 -0
- package/content/patterns/factory.md +46 -0
- package/content/patterns/null-object.md +55 -0
- package/content/patterns/result-vs-exception.md +52 -0
- package/content/patterns/strategy.md +45 -0
- package/content/patterns/template-method-vs-composition.md +50 -0
- package/content/questions/adr.questions.yaml +14 -0
- package/content/questions/analyze.questions.yaml +12 -0
- package/content/questions/bootstrap-mapping.questions.yaml +14 -0
- package/content/questions/bootstrap-rules.questions.yaml +10 -0
- package/content/questions/bootstrap-stack.questions.yaml +23 -0
- package/content/questions/clarify.questions.yaml +10 -0
- package/content/questions/code-style.questions.yaml +12 -0
- package/content/questions/confirm.questions.yaml +12 -0
- package/content/questions/deliver.questions.yaml +23 -0
- package/content/questions/evolve.questions.yaml +15 -0
- package/content/questions/export-template-apply.questions.yaml +11 -0
- package/content/questions/export-template.questions.yaml +23 -0
- package/content/questions/gates.questions.yaml +27 -0
- package/content/questions/generalize.questions.yaml +13 -0
- package/content/questions/gotcha.questions.yaml +11 -0
- package/content/questions/init-template.questions.yaml +10 -0
- package/content/questions/init.questions.yaml +28 -0
- package/content/questions/plan.questions.yaml +14 -0
- package/content/questions/refactor.questions.yaml +23 -0
- package/content/questions/reflect.questions.yaml +13 -0
- package/content/questions/remediate.questions.yaml +27 -0
- package/content/questions/restructure.questions.yaml +15 -0
- package/content/questions/rf-mapping.questions.yaml +12 -0
- package/content/questions/rule-scope.questions.yaml +12 -0
- package/content/questions/rule.questions.yaml +12 -0
- package/content/questions/specify.questions.yaml +23 -0
- package/content/questions/update-artifacts.questions.yaml +10 -0
- package/content/questions/update-strings.questions.yaml +14 -0
- package/content/questions/update.questions.yaml +10 -0
- package/content/questions/verify.questions.yaml +9 -0
- package/content/roles/executor.md +18 -0
- package/content/roles/explorer.md +22 -0
- package/content/roles/reviewer.md +23 -0
- package/content/rubrics/enum-vs-union-vs-branded.md +40 -0
- package/content/rubrics/episodic-vs-semantic-boundary.md +37 -0
- package/content/rubrics/error-classification.md +98 -0
- package/content/rubrics/failure-classification.md +113 -0
- package/content/rubrics/negative-filters.md +38 -0
- package/content/rubrics/solid-triggers.md +121 -0
- package/content/rubrics/template-vs-streaming-precedence.md +34 -0
- package/content/rubrics/validation-boundary.md +94 -0
- package/content/rubrics/when-to-create-dsl.md +65 -0
- package/content/rubrics/when-to-create-lib.md +49 -0
- package/content/rubrics/when-to-create-module.md +39 -0
- package/content/rubrics/when-to-evolve-methodology.md +62 -0
- package/content/skills/adr.md +42 -0
- package/content/skills/analyze.md +34 -0
- package/content/skills/clarify.md +34 -0
- package/content/skills/deliver.md +42 -0
- package/content/skills/diagnose.md +50 -0
- package/content/skills/evolve.md +67 -0
- package/content/skills/export-template.md +40 -0
- package/content/skills/generalize.md +47 -0
- package/content/skills/gotcha.md +40 -0
- package/content/skills/init.md +82 -0
- package/content/skills/plan.md +34 -0
- package/content/skills/policy.md +31 -0
- package/content/skills/promote.md +41 -0
- package/content/skills/protocol.md +42 -0
- package/content/skills/reconcile.md +49 -0
- package/content/skills/refactor.md +84 -0
- package/content/skills/reflect.md +53 -0
- package/content/skills/remediate.md +39 -0
- package/content/skills/restructure.md +52 -0
- package/content/skills/rule.md +44 -0
- package/content/skills/specify.md +34 -0
- package/content/skills/tasks.md +34 -0
- package/content/skills/update.md +56 -0
- package/content/skills/verify.md +31 -0
- package/content/templates/adr.template.md +51 -0
- package/content/templates/evolution-report.template.md +129 -0
- package/content/templates/feature-plan.template.md +86 -0
- package/content/templates/feature-research.template.md +57 -0
- package/content/templates/feature-spec.template.md +86 -0
- package/content/templates/feature-tasks.induced.template.md +67 -0
- package/content/templates/feature-tasks.template.md +60 -0
- package/content/templates/focus.template.md +30 -0
- package/content/templates/gotcha.template.md +31 -0
- package/content/templates/guardrail-runner.template.md +81 -0
- package/content/templates/guardrail.template.md +63 -0
- package/content/templates/learning.template.md +40 -0
- package/content/templates/procedure.template.md +47 -0
- package/content/templates/protocols/p1.md +29 -0
- package/content/templates/protocols/p2.md +28 -0
- package/content/templates/protocols/p3.md +47 -0
- package/content/templates/research.template.md +50 -0
- package/content/templates/session-handoff.template.md +58 -0
- package/content/templates/us.template.md +39 -0
- package/content/tools/gate/core-rules/PLUGIN-13-secrets.sh +36 -0
- package/content/tools/gate/core-rules/PLUGIN-21-code-language.sh +27 -0
- package/content/tools/gate/core-rules/PLUGIN-35-gate-complete.sh +19 -0
- package/content/tools/gate/core-rules/PLUGIN-36-absolute-path.sh +38 -0
- package/content/tools/gate/core-rules/PLUGIN-37-prose-language.sh +56 -0
- package/content/tools/gate/core-rules/PLUGIN-38-parser-marker.sh +82 -0
- package/content/tools/gate/core-rules/PLUGIN-39-frontmatter-ops.sh +325 -0
- package/content/tools/gate/core-rules/PLUGIN-40-dead-reference.sh +74 -0
- package/content/tools/gate/core-rules/README.md +55 -0
- package/content/tools/gate/guardrails.sh +740 -0
- package/content/tools/gate/lib/ratchet.sh +119 -0
- package/content/tools/gate/lib/scope.sh +85 -0
- package/content/tools/gate/ratchet.seed.tsv +1 -0
- package/content/tools/gate/rules/README.md +50 -0
- package/package.json +19 -5
- package/plugin/agy/hooks.json +29 -0
- package/plugin/agy/mcp_config.json +7 -0
- package/plugin/agy/plugin.json +6 -0
- package/plugin/agy/skills/afm-adr/SKILL.md +44 -0
- package/plugin/agy/skills/afm-analyze/SKILL.md +36 -0
- package/plugin/agy/skills/afm-clarify/SKILL.md +36 -0
- package/plugin/agy/skills/afm-deliver/SKILL.md +44 -0
- package/plugin/agy/skills/afm-diagnose/SKILL.md +50 -0
- package/plugin/agy/skills/afm-evolve/SKILL.md +69 -0
- package/plugin/agy/skills/afm-export-template/SKILL.md +42 -0
- package/plugin/agy/skills/afm-generalize/SKILL.md +49 -0
- package/plugin/agy/skills/afm-gotcha/SKILL.md +42 -0
- package/plugin/agy/skills/afm-init/SKILL.md +84 -0
- package/plugin/agy/skills/afm-plan/SKILL.md +36 -0
- package/plugin/agy/skills/afm-policy/SKILL.md +31 -0
- package/plugin/agy/skills/afm-promote/SKILL.md +41 -0
- package/plugin/agy/skills/afm-protocol/SKILL.md +42 -0
- package/plugin/agy/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/agy/skills/afm-refactor/SKILL.md +86 -0
- package/plugin/agy/skills/afm-reflect/SKILL.md +55 -0
- package/plugin/agy/skills/afm-remediate/SKILL.md +41 -0
- package/plugin/agy/skills/afm-restructure/SKILL.md +54 -0
- package/plugin/agy/skills/afm-rule/SKILL.md +46 -0
- package/plugin/agy/skills/afm-specify/SKILL.md +36 -0
- package/plugin/agy/skills/afm-tasks/SKILL.md +34 -0
- package/plugin/agy/skills/afm-update/SKILL.md +58 -0
- package/plugin/agy/skills/afm-verify/SKILL.md +33 -0
- package/plugin/claude-code/.claude-plugin/marketplace.json +15 -0
- package/plugin/claude-code/.claude-plugin/plugin.json +9 -0
- package/plugin/claude-code/.mcp.json +7 -0
- package/plugin/claude-code/agents/afm-executor.md +18 -0
- package/plugin/claude-code/agents/afm-explorer.md +20 -0
- package/plugin/claude-code/agents/afm-reviewer.md +21 -0
- package/plugin/claude-code/hooks/hooks.json +85 -0
- package/plugin/claude-code/skills/adr/SKILL.md +44 -0
- package/plugin/claude-code/skills/analyze/SKILL.md +36 -0
- package/plugin/claude-code/skills/clarify/SKILL.md +36 -0
- package/plugin/claude-code/skills/deliver/SKILL.md +44 -0
- package/plugin/claude-code/skills/diagnose/SKILL.md +50 -0
- package/plugin/claude-code/skills/evolve/SKILL.md +69 -0
- package/plugin/claude-code/skills/export-template/SKILL.md +42 -0
- package/plugin/claude-code/skills/generalize/SKILL.md +49 -0
- package/plugin/claude-code/skills/gotcha/SKILL.md +42 -0
- package/plugin/claude-code/skills/init/SKILL.md +84 -0
- package/plugin/claude-code/skills/plan/SKILL.md +36 -0
- package/plugin/claude-code/skills/policy/SKILL.md +31 -0
- package/plugin/claude-code/skills/promote/SKILL.md +41 -0
- package/plugin/claude-code/skills/protocol/SKILL.md +42 -0
- package/plugin/claude-code/skills/reconcile/SKILL.md +49 -0
- package/plugin/claude-code/skills/refactor/SKILL.md +86 -0
- package/plugin/claude-code/skills/reflect/SKILL.md +55 -0
- package/plugin/claude-code/skills/remediate/SKILL.md +41 -0
- package/plugin/claude-code/skills/restructure/SKILL.md +54 -0
- package/plugin/claude-code/skills/rule/SKILL.md +46 -0
- package/plugin/claude-code/skills/specify/SKILL.md +36 -0
- package/plugin/claude-code/skills/tasks/SKILL.md +34 -0
- package/plugin/claude-code/skills/update/SKILL.md +58 -0
- package/plugin/claude-code/skills/verify/SKILL.md +33 -0
- package/plugin/opencode/afm.js +196 -0
- package/plugin/opencode/agents/afm-executor.md +31 -0
- package/plugin/opencode/agents/afm-explorer.md +47 -0
- package/plugin/opencode/agents/afm-reviewer.md +48 -0
- package/plugin/opencode/skills/afm-adr/SKILL.md +44 -0
- package/plugin/opencode/skills/afm-analyze/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-clarify/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-deliver/SKILL.md +44 -0
- package/plugin/opencode/skills/afm-diagnose/SKILL.md +50 -0
- package/plugin/opencode/skills/afm-evolve/SKILL.md +69 -0
- package/plugin/opencode/skills/afm-export-template/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-generalize/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-gotcha/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-init/SKILL.md +84 -0
- package/plugin/opencode/skills/afm-plan/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-policy/SKILL.md +31 -0
- package/plugin/opencode/skills/afm-promote/SKILL.md +41 -0
- package/plugin/opencode/skills/afm-protocol/SKILL.md +42 -0
- package/plugin/opencode/skills/afm-reconcile/SKILL.md +49 -0
- package/plugin/opencode/skills/afm-refactor/SKILL.md +86 -0
- package/plugin/opencode/skills/afm-reflect/SKILL.md +55 -0
- package/plugin/opencode/skills/afm-remediate/SKILL.md +41 -0
- package/plugin/opencode/skills/afm-restructure/SKILL.md +54 -0
- package/plugin/opencode/skills/afm-rule/SKILL.md +46 -0
- package/plugin/opencode/skills/afm-specify/SKILL.md +36 -0
- package/plugin/opencode/skills/afm-tasks/SKILL.md +34 -0
- package/plugin/opencode/skills/afm-update/SKILL.md +58 -0
- package/plugin/opencode/skills/afm-verify/SKILL.md +33 -0
- package/README.md +0 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: code-style
|
|
3
|
+
description: 'Proposes a path-bound grep that verifies TRPCError never appears in the domain layer, for a project that keeps domain code under a fixed path.'
|
|
4
|
+
load: cold
|
|
5
|
+
stack: trpc-v11
|
|
6
|
+
concern: error-boundary
|
|
7
|
+
detect: |
|
|
8
|
+
if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|has("@trpc/server")' package.json >/dev/null 2>&1; else grep -q '"@trpc/server"' package.json 2>/dev/null; fi
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Code style — tRPC v11 error-boundary check
|
|
12
|
+
|
|
13
|
+
> The principle behind this — a transport error type must not reach the domain layer — is a
|
|
14
|
+
> genuine tRPC layering fact, kept in `modules/trpc-v11/rules.patch.md` as a §1.3 principle. What
|
|
15
|
+
> is a **proposal** here, not a fact, is the concrete mechanical check below: it is bound to one
|
|
16
|
+
> house layout (`{{src-path}}/server/modules/*/domain/`), and a project that lays out its domain
|
|
17
|
+
> code differently needs a different glob, or none at all.
|
|
18
|
+
|
|
19
|
+
## The convention
|
|
20
|
+
|
|
21
|
+
Add a hard rule to `docs/afm.md` §3 that mechanically enforces the principle, verified by:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
grep -rn "TRPCError" {{src-path}}/server/modules/*/domain/
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Zero results required. `TRPCError` appearing anywhere under a project's domain path means a
|
|
28
|
+
transport type leaked past the procedure boundary.
|
|
29
|
+
|
|
30
|
+
## Why this works
|
|
31
|
+
|
|
32
|
+
Review alone misses this reliably — `TRPCError` is a normal, typed import, and nothing about
|
|
33
|
+
using it inside a domain function raises a compiler error or a lint warning on its own; the
|
|
34
|
+
violation is architectural, not syntactic. A path-bound grep turns "domain must not import
|
|
35
|
+
TRPCError" from a principle a reviewer has to remember into a check a hook runs on every commit.
|
|
36
|
+
|
|
37
|
+
## The trade-off
|
|
38
|
+
|
|
39
|
+
The check is only as good as the glob. A monorepo with more than one domain root, a project mid
|
|
40
|
+
-migration to a new folder layout, or one that does not separate "domain" into its own directory
|
|
41
|
+
at all gets a check that is silently vacuous (matches nothing, so it always passes) rather than
|
|
42
|
+
one that fails loudly. Confirm the glob actually matches existing domain files before trusting a
|
|
43
|
+
green result — an empty match set means either the boundary holds, or the path is wrong.
|
|
44
|
+
|
|
45
|
+
## If the operator accepts this
|
|
46
|
+
|
|
47
|
+
Materialize the hard rule into `docs/afm.md` §3 with `{{src-path}}` resolved to the project's
|
|
48
|
+
actual domain-layer root (fill the placeholder at bootstrap, the way `docs/afm.md` fills every
|
|
49
|
+
other `{{src-path}}` site). Do not paste the grep with the placeholder left in — a rule with an
|
|
50
|
+
unresolved `{{src-path}}` runs against a literal, nonexistent directory and passes vacuously on
|
|
51
|
+
every project.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: code-style
|
|
3
|
+
description: 'Proposes exactly one domain function per file, with shared constants and schemas factored to a sibling file.'
|
|
4
|
+
load: cold
|
|
5
|
+
stack: trpc-v11
|
|
6
|
+
concern: file-size
|
|
7
|
+
detect: |
|
|
8
|
+
if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|has("@trpc/server")' package.json >/dev/null 2>&1; else grep -q '"@trpc/server"' package.json 2>/dev/null; fi
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Code style — tRPC v11 domain file granularity
|
|
12
|
+
|
|
13
|
+
> This is a **proposal**, not a fact about tRPC. Materialize it into `docs/ach.md` only if the
|
|
14
|
+
> operator accepts it — item by item, at bootstrap. Nothing here is `(mandatory)`.
|
|
15
|
+
|
|
16
|
+
## The convention
|
|
17
|
+
|
|
18
|
+
One domain function per file. Shared constants, Zod schemas, or types that more than one domain
|
|
19
|
+
function needs move to `<name>.ts` in the module — never added as a second export in a domain
|
|
20
|
+
file.
|
|
21
|
+
|
|
22
|
+
## Why this works
|
|
23
|
+
|
|
24
|
+
A domain file's name (`<action>-<module>.ts`) then names exactly one thing, so `git blame` and
|
|
25
|
+
`git log --follow` on that file tell the history of one business rule, not several interleaved
|
|
26
|
+
ones. It also keeps a domain file's diff small and reviewable — a change to one rule cannot
|
|
27
|
+
accidentally touch the body of an unrelated one two exports down.
|
|
28
|
+
|
|
29
|
+
## The trade-off
|
|
30
|
+
|
|
31
|
+
Two domain functions that are always read and changed together (a `create` and its matching
|
|
32
|
+
`validate`) end up in two files a reviewer has to open side by side anyway, and a module with
|
|
33
|
+
many small, closely related domain functions accumulates many small files, which has its own
|
|
34
|
+
navigation cost. A project that already caps files by line count rather than by function count
|
|
35
|
+
gains nothing extra from this — it addresses a different axis.
|
|
36
|
+
|
|
37
|
+
## If the operator accepts this
|
|
38
|
+
|
|
39
|
+
Materialize it into `docs/ach.md` under the Domain-like component type. This convention has no
|
|
40
|
+
practical mechanical check of its own — "one function per file" is check-able only by parsing
|
|
41
|
+
exports per file, which the existing naming check (`code-style/trpc-v11/naming.md`) already
|
|
42
|
+
covers as a side effect: if every domain file matches `^export const domain_` for exactly one
|
|
43
|
+
export, a second export in that file (a hand-added constant, say) would itself be a naming-rule
|
|
44
|
+
violation with a different shape. Do not add a redundant hard rule for this alone.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: code-style
|
|
3
|
+
description: 'Proposes a fixed export/file naming pattern for tRPC procedures and domain functions, plus a fixed location for module subrouters.'
|
|
4
|
+
load: cold
|
|
5
|
+
stack: trpc-v11
|
|
6
|
+
concern: naming
|
|
7
|
+
detect: |
|
|
8
|
+
if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|has("@trpc/server")' package.json >/dev/null 2>&1; else grep -q '"@trpc/server"' package.json 2>/dev/null; fi
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Code style — tRPC v11 naming
|
|
12
|
+
|
|
13
|
+
> This is a **proposal**, not a fact about tRPC. Materialize it into `docs/ach.md` and
|
|
14
|
+
> `docs/afm.md` §3 only if the operator accepts it — item by item, at bootstrap. Nothing here is
|
|
15
|
+
> `(mandatory)`.
|
|
16
|
+
|
|
17
|
+
## The convention
|
|
18
|
+
|
|
19
|
+
- **Procedure export:** `procedure_<action><Module>` — camelCase, action first, plural module
|
|
20
|
+
after. Example: `procedure_getApps`, `procedure_createRegistries`.
|
|
21
|
+
- **Procedure file:** `<action>-<module>.ts` — kebab-case, same stem as the export.
|
|
22
|
+
- **Domain export:** `domain_<action><Module>` — same shape as the procedure, so the two read as
|
|
23
|
+
a matched pair.
|
|
24
|
+
- **Domain file:** `<action>-<module>.ts` — kebab-case, same pattern as the procedure.
|
|
25
|
+
- **Module subrouter:** lives at `modules/<f>/router.ts`. It imports the module's procedures and
|
|
26
|
+
exports a tRPC subrouter — aggregation plus namespacing, never a business rule.
|
|
27
|
+
|
|
28
|
+
Anti-examples for the procedure prefix:
|
|
29
|
+
- ❌ `procedure_signOut` — missing the module.
|
|
30
|
+
- ❌ `signOutProcedure` — suffix instead of prefix.
|
|
31
|
+
- ❌ `procedure_AuthSignOut` — module before the action.
|
|
32
|
+
|
|
33
|
+
## Why this works
|
|
34
|
+
|
|
35
|
+
A fixed prefix makes `grep -rn "^export const procedure_"` a complete inventory of every
|
|
36
|
+
tRPC entry point, and the matching `procedure_`/`domain_` pair makes the transport-to-business
|
|
37
|
+
mapping readable by name alone, without opening either file. The `modules/<f>/router.ts` location
|
|
38
|
+
gives every module the same subrouter address, so a new contributor finds the aggregation point
|
|
39
|
+
without asking.
|
|
40
|
+
|
|
41
|
+
## The trade-off
|
|
42
|
+
|
|
43
|
+
The prefix is redundant with the file's own location (`server/modules/x/procedures/get-apps.ts`
|
|
44
|
+
already says "this is a procedure in module x") and with the tool tip / import statement a caller
|
|
45
|
+
sees. A project that already has a naming scheme — feature-first folders, a different subrouter
|
|
46
|
+
layout, no `modules/` tier at all — gains nothing from importing this one; the value is
|
|
47
|
+
consistency **within** a project that adopts it, not a property of tRPC itself.
|
|
48
|
+
|
|
49
|
+
## If the operator accepts this
|
|
50
|
+
|
|
51
|
+
- Materialize the naming rule and anti-examples into `docs/ach.md` (Procedure-like /
|
|
52
|
+
Domain-like sections).
|
|
53
|
+
- Add a hard rule to `docs/afm.md` §3, verified by:
|
|
54
|
+
```sh
|
|
55
|
+
grep -rn "^export const procedure_" {{src-path}}/server/modules/*/procedures/*.ts
|
|
56
|
+
grep -rn "^export const domain_" {{src-path}}/server/modules/*/domain/*.ts
|
|
57
|
+
```
|
|
58
|
+
Every export returned must match the pattern — an empty result on a project with procedures
|
|
59
|
+
means the convention was not followed, not that the check passed vacuously; confirm at least
|
|
60
|
+
one procedure file exists first.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: code-style
|
|
3
|
+
description: 'Proposes a neighbor-test layout for tRPC procedures and domains, and a single shared test-context factory.'
|
|
4
|
+
load: cold
|
|
5
|
+
stack: trpc-v11
|
|
6
|
+
concern: test-placement
|
|
7
|
+
detect: |
|
|
8
|
+
if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|has("@trpc/server")' package.json >/dev/null 2>&1; else grep -q '"@trpc/server"' package.json 2>/dev/null; fi
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Code style — tRPC v11 test placement
|
|
12
|
+
|
|
13
|
+
> This is a **proposal**, not a fact about tRPC. Materialize it into `docs/ach.md` and
|
|
14
|
+
> `docs/afm.md` §3 only if the operator accepts it — item by item, at bootstrap. Nothing here is
|
|
15
|
+
> `(mandatory)`.
|
|
16
|
+
|
|
17
|
+
## The convention
|
|
18
|
+
|
|
19
|
+
- **Neighbor test.** `<action>-<module>.test.ts` lives in the SAME directory as
|
|
20
|
+
`<action>-<module>.ts` — no separate `__tests__/` folder.
|
|
21
|
+
- **One shared context factory.** Every test that needs a `TRPCContext` (procedures) or a
|
|
22
|
+
`DomainContext` (domains) builds it through one helper — for example
|
|
23
|
+
`makeTestCtx(override?)`, returning a fresh, deep-copied ctx — instead of constructing the
|
|
24
|
+
context object by hand in each test file.
|
|
25
|
+
|
|
26
|
+
## Why this works
|
|
27
|
+
|
|
28
|
+
A neighbor test is found by the same file-explorer sort that finds the source file, and a
|
|
29
|
+
directory listing shows source and test side by side, which makes an untested file visible at a
|
|
30
|
+
glance. A single context factory means a `TRPCContext` field added once is available to every
|
|
31
|
+
test through one function, instead of a hand-rolled object per test file quietly drifting from
|
|
32
|
+
the real shape.
|
|
33
|
+
|
|
34
|
+
## The trade-off
|
|
35
|
+
|
|
36
|
+
`__tests__/` (or a top-level `test/` mirror) is itself a legitimate, widely used layout — it
|
|
37
|
+
keeps a directory listing free of test files for someone scanning source only, and some test
|
|
38
|
+
runners default to it. A hand-built context per test can also be the right call for a test that
|
|
39
|
+
deliberately exercises a malformed or partial context — forcing every test through one factory
|
|
40
|
+
can hide that case behind an `override` parameter nobody reads closely. Pick the layout that
|
|
41
|
+
matches how the team already scans the codebase; do not adopt this because it is here.
|
|
42
|
+
|
|
43
|
+
## If the operator accepts this
|
|
44
|
+
|
|
45
|
+
- Materialize the neighbor-test convention into `docs/ach.md` (Procedure-like / Domain-like).
|
|
46
|
+
- If a shared context factory is adopted, name and locate it explicitly in `docs/ach.md`
|
|
47
|
+
(project-specific — do not copy a path from another repo).
|
|
48
|
+
- Add a hard rule to `docs/afm.md` §3, verified by:
|
|
49
|
+
```sh
|
|
50
|
+
find {{src-path}}/server -name "__tests__" -type d
|
|
51
|
+
```
|
|
52
|
+
Zero results required.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: core
|
|
3
|
+
description: 'The architecture guide: the component types and where each one lives.'
|
|
4
|
+
load: warm
|
|
5
|
+
materializes_to: 'docs/ach.md'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# ACH — Architecture Guide
|
|
9
|
+
|
|
10
|
+
> Live architecture guide for {{nome do projeto}}.
|
|
11
|
+
> **Author:** owner of the architecture. Changes go through review before merge.
|
|
12
|
+
>
|
|
13
|
+
> This document answers: "Where do I put this logic?", "How do I structure this new module?", "How much testing does this change need?".
|
|
14
|
+
>
|
|
15
|
+
> **Related docs:** [`/docs/afm.md`](./afm.md) (process + hard rules), [`/docs/gotchas/`](./gotchas/) (counterintuitive surprises), [`/docs/adr/`](./adr/) (versioned decisions).
|
|
16
|
+
|
|
17
|
+
> **In this file:** 1. Macro Architecture · 2. Folder Architecture · 3. Components · 4. Test Strategy · 5. Cross-cutting Principles · 6. Code Conventions
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Macro Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
{{Diagrama ASCII das camadas. Fluxo principal. Dataflow de artefatos entre serviços externos.
|
|
26
|
+
|
|
27
|
+
Convenção: setas unidirecionais (→ camada chama camada). Boxes pra serviços externos. Texto curto identificando o tech (ex: "Postgres", "Redis", "S3-compatible").}}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Canonical entities:**
|
|
31
|
+
- **{{Entidade A}}** — {{descrição em 1 linha}}.
|
|
32
|
+
- **{{Entidade B}}** — {{descrição em 1 linha}}.
|
|
33
|
+
|
|
34
|
+
**Dataflow:**
|
|
35
|
+
- **{{Storage primário}}** — source of truth for {{X}}.
|
|
36
|
+
- **{{Storage secundário}}** — source of truth for {{Y}}.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 2. Folder Architecture
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
{{árvore de pastas comentada — uma linha por pasta importante explicando o que vive ali}}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Import rules
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
{{layer X}} → can import: {{lista}}
|
|
50
|
+
NEVER imports: {{lista}}
|
|
51
|
+
|
|
52
|
+
{{layer Y}} → can import: {{lista}}
|
|
53
|
+
does NOT import directly, receives via parameter: {{lista}}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Promotion to `domain/shared/`:** a function/value object in `modules/<X>/domain/` moves to `{{src-path}}/domain/shared/` when used by **3+ modules** (Rule of Three).
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Boundary exit
|
|
61
|
+
|
|
62
|
+
A boundary holds from the first need: a primitive needed on the forbidden side moves to the lowest layer both sides may import, never copied and never injected. The Rule of Three decides when a domain value becomes shared; it never decides whether a boundary may be crossed.
|
|
63
|
+
|
|
64
|
+
## 3. Components
|
|
65
|
+
|
|
66
|
+
### 3.1 First-class components
|
|
67
|
+
|
|
68
|
+
This section defines the **project vocabulary**. It maps universal component types to concrete tools in the chosen stack. The interview (`afm path interview/bootstrap.md`) fills this in.
|
|
69
|
+
|
|
70
|
+
#### Procedure-like — handler sync request/response
|
|
71
|
+
|
|
72
|
+
- **Universal concept:** handler for a short synchronous operation (< ~5s). Input is validated, auth is checked, and the return is typed for the frontend.
|
|
73
|
+
- **Stack implementation:** {{ex: tRPC procedure / Express route handler / Nest Controller / FastAPI endpoint}}.
|
|
74
|
+
- **Single responsibility:** orchestrate — validate → authorize → call domain/lib → persist → respond.
|
|
75
|
+
- **When to use:** every synchronous UI ↔ server interaction.
|
|
76
|
+
- **When NOT to use:**
|
|
77
|
+
- Heavy logic → delegate to Domain-like.
|
|
78
|
+
- Long-running, retryable, or scheduled work → delegate to Task-like.
|
|
79
|
+
- **Naming convention:** {{ex: `procedure_<action><Module>` + arquivo `<action>-<module>.ts`}}.
|
|
80
|
+
- **Canonical example:** {{path real do projeto}}.
|
|
81
|
+
- **Anti-examples (do not do this):**
|
|
82
|
+
- ❌ {{exemplo de naming errado com porquê}}.
|
|
83
|
+
- ❌ {{exemplo de pasta errada com porquê}}.
|
|
84
|
+
|
|
85
|
+
#### Domain-like — pure business rule function
|
|
86
|
+
|
|
87
|
+
- **Universal concept:** a pure function that applies a business rule. No un-abstracted I/O. No undeclared side effects. Testable without infra.
|
|
88
|
+
- **Stack implementation:** {{ex: função TS exportada com prefixo `domain_` / Use Case do DDD / função Python pura}}.
|
|
89
|
+
- **Canonical contract:** {{ex: `({ ctx, input }: DomainInput<T>) => Result<T, DomainErrorCode>`}}.
|
|
90
|
+
- **ONE domain function per file. No exceptions.** Shared constants and types go into `<nome>.{{ext}}` in the module. Never add them as a second export in the domain file.
|
|
91
|
+
- **When to use:**
|
|
92
|
+
- Logic that survives a transport change (HTTP today, CLI tomorrow).
|
|
93
|
+
- A rule you can test without a real DB.
|
|
94
|
+
- **When NOT to use — Domain is NOT:**
|
|
95
|
+
- ❌ **A data-access helper.** Building a query, mapping to a DTO, or forming a JOIN is infra or procedure work.
|
|
96
|
+
- ❌ **Transport glue.** HTTP headers, webhook parsers — those live in lib or procedure.
|
|
97
|
+
- ❌ **Orchestration between modules.** That is procedure or task responsibility.
|
|
98
|
+
- ❌ **Un-abstracted I/O** (fetch, spawn, direct S3 calls).
|
|
99
|
+
- ❌ **A file with only types or constants.** Move it out of `domain/` into `*.types.{{ext}}`.
|
|
100
|
+
- ❌ **Importing a transport error type** (hard rule 15).
|
|
101
|
+
- **Anti-examples (do not do this):**
|
|
102
|
+
- ❌ {{exemplo `domain_xWhereClause` retornando query parcial}}.
|
|
103
|
+
- ❌ {{exemplo arquivo com 2 `domain_*` exports}}.
|
|
104
|
+
|
|
105
|
+
#### Shared Domain — rule used by 3+ modules
|
|
106
|
+
|
|
107
|
+
- **Universal concept:** value objects, rules, and types shared across multiple modules.
|
|
108
|
+
- **When to use:** on the third confirmed duplicate across modules — promote it (Rule of Three).
|
|
109
|
+
- **When NOT to use:** on the first or second occurrence — keep it in `modules/<X>/domain/`.
|
|
110
|
+
|
|
111
|
+
#### Task-like — retry-safe async unit of work
|
|
112
|
+
|
|
113
|
+
- **Universal concept:** async work that can retry without corrupting state. It reads canonical state from the DB, early-returns on terminal states, updates atomically, and triggers the next task when needed.
|
|
114
|
+
- **Stack implementation:** {{ex: Trigger.dev v4 task / BullMQ Job / Celery task / AWS Step Function}}.
|
|
115
|
+
- **When to use:**
|
|
116
|
+
- Cron or scheduled jobs.
|
|
117
|
+
- Long workflows with retry (build, publish).
|
|
118
|
+
- External integrations with variable latency.
|
|
119
|
+
- **When NOT to use:**
|
|
120
|
+
- It fits in < 5s with no retry → use procedure.
|
|
121
|
+
- It is pure logic with no I/O → use domain.
|
|
122
|
+
|
|
123
|
+
##### Orchestration pattern: thin parent calls subtasks
|
|
124
|
+
|
|
125
|
+
A multi-stage workflow = a thin parent that coordinates, plus subtasks that do the work. Each subtask has its own retry, its own log, and its own sizing. The parent only calls `triggerAndWait`.
|
|
126
|
+
|
|
127
|
+
#### Lib-like — isolated, publishable package
|
|
128
|
+
|
|
129
|
+
- **Universal concept:** a self-contained package with no dependency on the app runtime (no ORM, no web framework, no orchestrator). It must be safe to `publish`.
|
|
130
|
+
- **Stack implementation:** {{ex: a folder under `{{src-path}}/lib/` with an `index.ts` and zero framework imports}}.
|
|
131
|
+
- **Responsibility:** a self-contained feature.
|
|
132
|
+
- **When to use:** any of these:
|
|
133
|
+
- The same helper already has 3 callers.
|
|
134
|
+
- It wraps a nameable external integration (Stripe, S3, etc.).
|
|
135
|
+
- It holds > ~150 lines of coupled pure logic.
|
|
136
|
+
- **When NOT to use — a Lib is NOT:**
|
|
137
|
+
- ❌ **A lib that imports an ORM type.** Accept a minimal structural shape instead.
|
|
138
|
+
- ❌ **A lib with an implicit singleton** (a module-level variable caching a client). Export a factory instead.
|
|
139
|
+
- ❌ **A lib with a God object** (a class or object with 8+ methods). Use named functions instead.
|
|
140
|
+
- ❌ **A lib that logs on its own.** Receive `log` by DI, or return a `Result`.
|
|
141
|
+
- ❌ **A lib that defines errors with no literal discriminant** (`code: "..." as const`).
|
|
142
|
+
- ❌ **A lib with 1 caller.** YAGNI.
|
|
143
|
+
- ❌ **A lib with a huge options bag** (≥ 6 optional fields).
|
|
144
|
+
- ❌ **A lib that imports from a layer above it.** Layer order follows this project's Import rules in § 2. It is not a hardcoded example.
|
|
145
|
+
|
|
146
|
+
#### Adapter-like — implementation of a typed port
|
|
147
|
+
|
|
148
|
+
- **Universal concept:** a concrete implementation of a port (a typed interface). Examples: a registry adapter (NPM/GitHub/Custom), a storage adapter (S3/R2/MinIO), an email adapter (Resend/SES).
|
|
149
|
+
- **LSP in action:** every implementation of the same port returns the same classified result shape (e.g., `PUBLISHED|CONFLICT|FAILED`). Adapter A cannot return `null` on conflict while adapter B throws an exception.
|
|
150
|
+
- **OCP in action:** adding a new provider means a new file that implements the port, **with no** `switch (provider)` scattered around.
|
|
151
|
+
|
|
152
|
+
### 3.2 Supporting components (second class)
|
|
153
|
+
|
|
154
|
+
#### Module router — aggregation inside the module namespace
|
|
155
|
+
|
|
156
|
+
{{Implementação no stack — ex: `modules/<f>/router.ts` que junta procedures num subrouter tRPC}}.
|
|
157
|
+
|
|
158
|
+
#### Infra — cross-cutting utilities
|
|
159
|
+
|
|
160
|
+
Singleton clients, rate-limit wrappers, email senders, and test context factories. **Contains no business rules.**
|
|
161
|
+
|
|
162
|
+
#### UI primitives
|
|
163
|
+
|
|
164
|
+
Presentation components. No direct fetch — data comes via {{cliente do stack — ex: tRPC + React Query}}.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 4. Test Strategy
|
|
169
|
+
|
|
170
|
+
### 4.1 Levels (classic pyramid + strong XP)
|
|
171
|
+
|
|
172
|
+
| Level | What it tests | Where it lives | Target ratio |
|
|
173
|
+
| ----- | ----------- | --------- | -------------- |
|
|
174
|
+
| **Unit** | Pure logic, domain, pure libs | {{paths}} | ~70% |
|
|
175
|
+
| **Integration** | Contracts between layers with real I/O | {{paths}} | ~25% |
|
|
176
|
+
| **E2E** | End-to-end user flow | {{paths}} | ~5% |
|
|
177
|
+
|
|
178
|
+
### 4.2 Strict TDD + types-as-test
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
1. RED — write a test (or a type signature) that fails for the right reason
|
|
182
|
+
2. GREEN — minimal implementation that passes
|
|
183
|
+
3. REFACTOR — remove duplication, improve names, type-check + tests
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`tsc --noEmit` is part of the red/green loop, just like the tests.
|
|
187
|
+
|
|
188
|
+
### 4.3 Regression
|
|
189
|
+
|
|
190
|
+
**Bug found → write a reproducing test BEFORE the fix.** No exceptions. Production hotfix: add the test in the same PR.
|
|
191
|
+
|
|
192
|
+
### 4.4 Types as tests
|
|
193
|
+
|
|
194
|
+
`unknown` or `any` in a helper you own is a missing type test. Fix the inference.
|
|
195
|
+
|
|
196
|
+
### 4.5 Target coverage by layer
|
|
197
|
+
|
|
198
|
+
{{Tabela: por camada/pasta, qual cobertura mínima e se é policiada por CI ou só guideline.}}
|
|
199
|
+
|
|
200
|
+
**No global threshold in CI** — the metric is easy to game. Confidence comes from the reviewer plus AFM, not from a number.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 5. Cross-cutting Principles
|
|
205
|
+
|
|
206
|
+
- **XP + Pragmatic** — DRY, YAGNI, KISS, Broken Windows, Design by Contract, Rubber Duck. Daily practices in [`/docs/afm.md`](./afm.md).
|
|
207
|
+
- **Task idempotency** — every task is retry-safe. Canonical state lives in the DB. Early return on terminal states is the rule.
|
|
208
|
+
- **{{Storage primário}} = source of truth for {{X}}. {{Storage secundário}} = source of truth for {{Y}}.** Resolve any divergence by always reading from the authoritative source per type.
|
|
209
|
+
- **Types instead of comments.** The name and type carry the *what*. Use a comment only to explain a surprising *why*.
|
|
210
|
+
- **Observability by design.** Every async operation leaves a traceable trail (run id, correlation id, etc.).
|
|
211
|
+
- **Auditable schema — state with a lifecycle gets its own model.**
|
|
212
|
+
- State with a cycle (start → update → end) is NOT a scalar field on the owner.
|
|
213
|
+
- Use a separate model with one row per instance instead.
|
|
214
|
+
- Rule of thumb: if X is recreated, do you want its history?
|
|
215
|
+
- If yes, add a model with an FK to the owner.
|
|
216
|
+
- Lifelong 1:1 external identifiers can stay as a plain field.
|
|
217
|
+
|
|
218
|
+
{{Adicione princípios transversais específicos do projeto.}}
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 6. Code Conventions (cheat sheet)
|
|
223
|
+
|
|
224
|
+
### Decision rubrics
|
|
225
|
+
|
|
226
|
+
Check the rubrics in [`rubrics/`](rubrics/) **before** you choose:
|
|
227
|
+
|
|
228
|
+
- [`when-to-create-lib.md`](rubrics/when-to-create-lib.md) — triggers for creating `{{src-path}}/lib/<x>/`.
|
|
229
|
+
- [`when-to-create-module.md`](rubrics/when-to-create-module.md) — triggers for creating a top-level module.
|
|
230
|
+
- [`when-to-create-dsl.md`](rubrics/when-to-create-dsl.md) — DSL-first: when primitive boilerplate scales (≥3 repeated sequences, wiring dominates, and a grammar exists), suggest a DSL. Rule 11: do not build it yourself.
|
|
231
|
+
- [`enum-vs-union-vs-branded.md`](rubrics/enum-vs-union-vs-branded.md) — which type to use for an enumerable value.
|
|
232
|
+
- [`error-classification.md`](rubrics/error-classification.md) — Domain vs Procedure vs Infra.
|
|
233
|
+
- [`failure-classification.md`](rubrics/failure-classification.md) — a failure recognized by an external signal (CRITIC) → procedure (mechanical) | learning (conceptual) | nothing (transient). Used by the CRITIC loop (`remediate`).
|
|
234
|
+
- [`episodic-vs-semantic-boundary.md`](rubrics/episodic-vs-semantic-boundary.md) — what decays (episodic: session handoffs, `_focus.md`) vs. what is permanent (semantic: rules/decisions/gotchas). Defines what belongs in the diagnose axes.
|
|
235
|
+
- [`negative-filters.md`](rubrics/negative-filters.md) — what NOT to promote to durable docs (a negative tool claim, transient failure, one-off narrative, or status update). The rejection checklist for the `gotcha`/`reconcile`/`remediate` gate. A false constraint is poison (#5).
|
|
236
|
+
- [`solid-triggers.md`](rubrics/solid-triggers.md) — OCP/LSP/ISP/DIP with a concrete trigger.
|
|
237
|
+
- [`validation-boundary.md`](rubrics/validation-boundary.md) — where the Zod parser (or equivalent) fits in.
|
|
238
|
+
- [`when-to-evolve-methodology.md`](rubrics/when-to-evolve-methodology.md) — when to run an `afm evolve` cycle (health of this project's whole local doc set) vs. a one-off fix (`afm gotcha`/`afm rule`/`afm adr` via reconcile).
|
|
239
|
+
- [`template-vs-streaming-precedence.md`](rubrics/template-vs-streaming-precedence.md) — when a frozen template (`export-template`) and streaming learning (`reconcile`) collide: precedence plus tombstone, never additive (AWM non-additivity).
|
|
240
|
+
|
|
241
|
+
### Naming (fill in during the interview)
|
|
242
|
+
|
|
243
|
+
| Layer | Export pattern | File pattern |
|
|
244
|
+
| ----- | ---- | ---- |
|
|
245
|
+
| Procedure-like | {{ex: `procedure_<action><Module>`}} | {{ex: `<action>-<module>.ts`}} |
|
|
246
|
+
| Domain-like | {{ex: `domain_<action><Module>`}} | {{ex: `<action>-<module>.ts`}} |
|
|
247
|
+
| External lib | {{ex: `<libname>_<action>`}} | {{ex: `<action>.ts`}} |
|
|
248
|
+
| Test file | {{ex: same name + `.test.{{ext}}`}} | {{ex: same directory, no `__tests__/`}} |
|
|
249
|
+
|
|
250
|
+
### Size and responsibility
|
|
251
|
+
|
|
252
|
+
- ≤ 300 lines per file.
|
|
253
|
+
- One responsibility per file.
|
|
254
|
+
- Shared types → `*.types.{{ext}}` next to the file.
|
|
255
|
+
- Constants → `*.constants.{{ext}}` next to the file.
|
|
256
|
+
|
|
257
|
+
### Types: explicit at boundaries, inferred elsewhere
|
|
258
|
+
|
|
259
|
+
- **Explicit:** return types of exported functions, public parameters, ctx/input of procedures and domain functions, props of exported components.
|
|
260
|
+
- **Inferred:** local variables, closure return values, `.map` output, chained calls.
|
|
261
|
+
- **Never `any` / `unknown` in a helper you own.**
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
*Changes here follow hard rule 11: an architectural change stops and asks. The surface is `afm approve` for a plan, or `afm ask <op>` for a question, whichever the situation calls for.*
|