@polymorphism-tech/morph-spec 8.37.1 → 8.38.0
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/CLAUDE.md +19 -6
- package/README.md +2 -2
- package/bin/morph-spec.js +16 -7
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +3 -3
- package/framework/MORPH.md +25 -22
- package/framework/agents.json +76 -27
- package/framework/docs/CLI.md +54 -17
- package/framework/evals/rubrics/code-quality.md +5 -0
- package/framework/evals/rubrics/condensed.md +6 -2
- package/framework/evals/rubrics/contracts.md +20 -0
- package/framework/evals/rubrics/test-coverage.md +17 -6
- package/framework/hooks/README.md +9 -3
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +52 -0
- package/framework/hooks/claude-code/core/telemetry-log.js +172 -87
- package/framework/hooks/claude-code/core/validate-completion.js +16 -90
- package/framework/hooks/claude-code/core/worktree-context.js +10 -0
- package/framework/hooks/shared/command-tokens.js +96 -0
- package/framework/hooks/shared/git-exclude.js +44 -0
- package/framework/hooks/shared/git-paths.js +52 -0
- package/framework/hooks/shared/graph-freshness.js +380 -0
- package/framework/hooks/shared/graph-refresh.js +416 -0
- package/framework/hooks/shared/morph-cli.js +17 -5
- package/framework/hooks/shared/redact-secrets.js +55 -0
- package/framework/hooks/shared/telemetry-logger.js +25 -2
- package/framework/hooks/shared/transcript-usage.js +80 -0
- package/framework/rubrics/backend.json +2 -2
- package/framework/rubrics/default.json +2 -2
- package/framework/rubrics/frontend.json +2 -2
- package/framework/rules/csharp-standards.md +1 -0
- package/framework/rules/morph-workflow.md +1 -0
- package/framework/rules/nextjs-standards.md +1 -0
- package/framework/schemas/config.schema.json +41 -1
- package/framework/schemas/feature.schema.json +5 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +36 -11
- package/framework/skills/core/morph-brainstorming/SKILL.md +16 -7
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +39 -10
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +72 -15
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +51 -13
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +34 -9
- package/framework/standards/STANDARDS.json +187 -12
- package/framework/standards/ai-agents/testing-ai.md +2 -1
- package/framework/standards/architecture/code-comments.md +64 -0
- package/framework/standards/backend/dotnet/testing.md +22 -0
- package/framework/standards/frontend/admin-app/data-table.md +562 -0
- package/framework/standards/frontend/admin-app/feedback.md +236 -0
- package/framework/standards/frontend/admin-app/forms.md +232 -0
- package/framework/standards/frontend/admin-app/page-structure.md +203 -0
- package/framework/standards/frontend/nextjs/components.md +37 -58
- package/framework/standards/frontend/nextjs/data-fetching.md +1 -0
- package/framework/standards/frontend/nextjs/forms.md +31 -30
- package/framework/standards/frontend/nextjs/state-management.md +2 -1
- package/framework/standards/frontend/nextjs/testing.md +18 -0
- package/framework/templates/context/design-system.md +3 -3
- package/framework/templates/docs/proposal.md +11 -0
- package/framework/templates/docs/spec.md +15 -0
- package/framework/templates/docs/ui-mockups.md +115 -98
- package/framework/templates/feature/decisions.md +124 -122
- package/package.json +1 -1
- package/src/commands/graph/affected.js +4 -3
- package/src/commands/graph/build.js +109 -18
- package/src/commands/graph/explain.js +8 -5
- package/src/commands/graph/status.js +14 -8
- package/src/commands/observability/cost.js +148 -18
- package/src/commands/project/doctor.js +82 -10
- package/src/commands/project/update.js +25 -0
- package/src/commands/project/worktree.js +73 -90
- package/src/commands/state/advance.js +18 -0
- package/src/commands/state/approve.js +15 -0
- package/src/commands/state/archive.js +62 -9
- package/src/commands/state/finish.js +62 -14
- package/src/commands/state/gate-check.js +8 -1
- package/src/commands/state/gate-decision.js +8 -4
- package/src/commands/state/report-check.js +90 -9
- package/src/commands/state/usecase.js +66 -0
- package/src/commands/tasks/dag.js +17 -2
- package/src/commands/validation/validate-feature.js +6 -1
- package/src/commands/validation/verify.js +20 -1
- package/src/dashboard/scanner/agents-scanner.js +5 -1
- package/src/dashboard/scanner/hooks-scanner.js +8 -1
- package/src/dashboard/scanner/standards-scanner.js +2 -1
- package/src/lib/ai/comment-stripper.js +101 -4
- package/src/lib/evaluator-report.js +25 -0
- package/src/lib/generators/handoff-generator.js +4 -18
- package/src/lib/git/default-branch.js +52 -0
- package/src/lib/git/tree-fingerprint.js +58 -0
- package/src/lib/git/tree-state.js +167 -0
- package/src/lib/graph/god-nodes.js +12 -3
- package/src/lib/graph/graph-health.js +48 -2
- package/src/lib/graph/graph-loader.js +99 -25
- package/src/lib/graph/graphifyignore.js +145 -28
- package/src/lib/graph/sanitize.js +117 -11
- package/src/lib/risk-detector.js +90 -0
- package/src/lib/specs/acervo-format.js +70 -0
- package/src/lib/specs/acervo-lifecycle.js +264 -0
- package/src/lib/specs/adr-index.js +169 -0
- package/src/lib/specs/revocations.js +156 -0
- package/src/lib/specs/screen-checklist.js +357 -0
- package/src/lib/specs/usecase-check.js +20 -16
- package/src/lib/specs/usecase-promoter.js +103 -38
- package/src/lib/specs/usecase-registry.js +7 -7
- package/src/lib/tasks/tasks-json-parser.js +2 -3
- package/src/lib/telemetry/metrics.js +386 -0
- package/src/lib/telemetry/telemetry-reader.js +161 -51
- package/src/lib/telemetry/verify-event.js +79 -0
- package/src/lib/validators/code-budget/code-budget-validator.js +172 -0
- package/src/lib/validators/code-budget/comment-scanner.js +75 -0
- package/src/lib/validators/code-budget/index.js +9 -0
- package/src/lib/validators/reuse/reuse-validator.js +4 -2
- package/src/lib/validators/reuse/symbol-scanner.js +27 -22
- package/src/lib/validators/validation-runner.js +21 -5
- package/src/lib/validators/verify-runner.js +11 -0
- package/src/lib/worktree/finish-backup.js +739 -0
- package/src/lib/worktree/ignored-triage.js +15 -8
- package/src/lib/worktree/worktree-audit.js +5 -0
- package/src/scripts/setup-infra.js +29 -18
- package/src/utils/agents-installer.js +281 -12
- package/src/utils/hooks-installer.js +75 -15
|
@@ -1541,13 +1541,17 @@
|
|
|
1541
1541
|
"fake clock",
|
|
1542
1542
|
"integration test",
|
|
1543
1543
|
"ProblemDetails",
|
|
1544
|
-
"error body assertion"
|
|
1544
|
+
"error body assertion",
|
|
1545
|
+
"test budget",
|
|
1546
|
+
"orçamento de teste",
|
|
1547
|
+
"[Theory] table"
|
|
1545
1548
|
],
|
|
1546
1549
|
"anchors": {
|
|
1547
1550
|
"clock": "#rule-1--inject-timeprovider-fake-it-with-faketimeprovider-in-tests",
|
|
1548
|
-
"errorbody": "#rule-2--error-path-tests-assert-the-response-body-not-just-the-status-code"
|
|
1551
|
+
"errorbody": "#rule-2--error-path-tests-assert-the-response-body-not-just-the-status-code",
|
|
1552
|
+
"test-budget": "#test-budget"
|
|
1549
1553
|
},
|
|
1550
|
-
"digest": "Inject TimeProvider (never DateTime.UtcNow / DateOnly.FromDateTime(DateTime.UtcNow) directly in a handler or validator) and fake it with FakeTimeProvider (Microsoft.Extensions.TimeProvider.Testing) in integration tests — deterministic, no midnight-UTC flake, boundary dates (today vs. yesterday) become facts about the fake clock instead of when the suite happens to run. xUnit + WebApplicationFactory error-path tests (400/404/409) must assert the ProblemDetails response BODY (title/detail/violated field or error code), never just the HTTP status code — a status-only assertion lets the wrong validation rule or the wrong error branch pass silently as long as the status matches.",
|
|
1554
|
+
"digest": "Inject TimeProvider (never DateTime.UtcNow / DateOnly.FromDateTime(DateTime.UtcNow) directly in a handler or validator) and fake it with FakeTimeProvider (Microsoft.Extensions.TimeProvider.Testing) in integration tests — deterministic, no midnight-UTC flake, boundary dates (today vs. yesterday) become facts about the fake clock instead of when the suite happens to run. xUnit + WebApplicationFactory error-path tests (400/404/409) must assert the ProblemDetails response BODY (title/detail/violated field or error code), never just the HTTP status code — a status-only assertion lets the wrong validation rule or the wrong error branch pass silently as long as the status matches. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior (edge cases included) are rows of one [Theory], never copied [Fact]s; no test whose only assertion is a copy, config or prose string (that is an analyzer or a publish-time validation, outside the suite count); shared fixtures before new helpers; TDD for bugs (regression first) and pure logic; a surviving mutant is killed by tightening an assertion or adding a row, not by a new test.",
|
|
1551
1555
|
"verifiedAgainst": ".NET 10 + xUnit 2 + `Microsoft.Extensions.TimeProvider.Testing`.",
|
|
1552
1556
|
"provedBy": []
|
|
1553
1557
|
},
|
|
@@ -2136,8 +2140,8 @@
|
|
|
2136
2140
|
"patterns": "#three-tier-hierarchy",
|
|
2137
2141
|
"shadcn": "#tier-1--shadcnui-primitives"
|
|
2138
2142
|
},
|
|
2139
|
-
"digest": "
|
|
2140
|
-
"verifiedAgainst": "Next.js
|
|
2143
|
+
"digest": "Three tiers: components/ui is shadcn CLI output (never edit, wrap instead); components/ composes primitives with no domain knowledge; features/*/components knows the domain. 'use client' only for hooks, events or browser APIs; never pass raw API data as props — type and validate it first. The shared data table is specified once, in admin-app/data-table.md.",
|
|
2144
|
+
"verifiedAgainst": "Next.js 16 + shadcn 4 CLI (the code blocks typecheck under `tsc --strict`).",
|
|
2141
2145
|
"provedBy": []
|
|
2142
2146
|
},
|
|
2143
2147
|
{
|
|
@@ -2185,15 +2189,15 @@
|
|
|
2185
2189
|
"react-hook-form",
|
|
2186
2190
|
"Zod",
|
|
2187
2191
|
"form validation",
|
|
2188
|
-
"
|
|
2189
|
-
"
|
|
2192
|
+
"shadcn Field",
|
|
2193
|
+
"Controller"
|
|
2190
2194
|
],
|
|
2191
2195
|
"anchors": {
|
|
2192
2196
|
"validation": "#schema-composition",
|
|
2193
2197
|
"submission": "#complete-form-pattern"
|
|
2194
2198
|
},
|
|
2195
|
-
"digest": "react-hook-form
|
|
2196
|
-
"verifiedAgainst": "Next.js
|
|
2199
|
+
"digest": "react-hook-form + Zod + shadcn Field components wired through Controller. Define the Zod schema first and derive the type with z.infer (z.input/z.output when it coerces); zodResolver connects it; Field/FieldLabel/FieldError render each field and its error; never useState per field; submit through TanStack Query useMutation and put a failed submit on root. Edit forms reuse the create schema (.partial()). Zod 4: z.email(), a single `error` param. A legacy shadcn Form/FormField screen is migrated when touched, never extended. Admin CRUD forms add the deltas of admin-app/forms.md.",
|
|
2200
|
+
"verifiedAgainst": "Next.js 16 + react-hook-form 7 + Zod 4 + @hookform/resolvers 5 + shadcn 4 `Field` (the code blocks typecheck under `tsc --strict`).",
|
|
2197
2201
|
"provedBy": []
|
|
2198
2202
|
},
|
|
2199
2203
|
{
|
|
@@ -2357,13 +2361,17 @@
|
|
|
2357
2361
|
"testing-library",
|
|
2358
2362
|
"Playwright",
|
|
2359
2363
|
"Next.js testing",
|
|
2360
|
-
"component tests"
|
|
2364
|
+
"component tests",
|
|
2365
|
+
"test budget",
|
|
2366
|
+
"orçamento de teste",
|
|
2367
|
+
"it.each table"
|
|
2361
2368
|
],
|
|
2362
2369
|
"anchors": {
|
|
2363
2370
|
"unit": "#component-test-pattern",
|
|
2364
|
-
"e2e": "#test-file-co-location"
|
|
2371
|
+
"e2e": "#test-file-co-location",
|
|
2372
|
+
"test-budget": "#test-budget"
|
|
2365
2373
|
},
|
|
2366
|
-
"digest": "Vitest for unit tests, React Testing Library for component tests. Mock next/navigation with vi.mock. Test Server Actions with direct function calls. Use MSW for API mocking in component tests. Playwright for E2E tests against running app. Never test implementation details — test user behavior and output.",
|
|
2374
|
+
"digest": "Vitest for unit tests, React Testing Library for component tests. Mock next/navigation with vi.mock. Test Server Actions with direct function calls. Use MSW for API mocking in component tests. Playwright for E2E tests against running app. Never test implementation details — test user behavior and output. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior are rows of one it.each, never copied it() blocks; no test whose only assertion is a copy string (lint or publish-time validation instead); shared wrappers, MSW handlers and factories before new helpers; TDD for bugs and pure logic, component tests may come after the code.",
|
|
2367
2375
|
"verifiedAgainst": "Vitest 3 + React Testing Library 16 + MSW 2.",
|
|
2368
2376
|
"provedBy": []
|
|
2369
2377
|
},
|
|
@@ -2684,6 +2692,165 @@
|
|
|
2684
2692
|
"digest": "MCP tools extend Claude with external data and actions. Tools are synchronous request-response with typed inputSchema. Resources provide read-only data access. Prompts are reusable templates. Register MCP servers in .claude/settings.json. Prefer @context7 for live library docs. Test tools with MCP Inspector before integrating.",
|
|
2685
2693
|
"verifiedAgainst": "Claude Code MCP tooling — context7, Playwright; GitHub via `gh` CLI; Neon via `neonctl`.",
|
|
2686
2694
|
"provedBy": []
|
|
2695
|
+
},
|
|
2696
|
+
{
|
|
2697
|
+
"id": "frontend-admin-app-data-table",
|
|
2698
|
+
"name": "data table",
|
|
2699
|
+
"path": "frontend/admin-app/data-table.md",
|
|
2700
|
+
"category": "frontend",
|
|
2701
|
+
"subcategory": "admin-app",
|
|
2702
|
+
"tags": [
|
|
2703
|
+
"frontend",
|
|
2704
|
+
"admin-app"
|
|
2705
|
+
],
|
|
2706
|
+
"stacks": [
|
|
2707
|
+
"nextjs"
|
|
2708
|
+
],
|
|
2709
|
+
"aliases": [
|
|
2710
|
+
"data table",
|
|
2711
|
+
"admin list",
|
|
2712
|
+
"server-side pagination",
|
|
2713
|
+
"paginação",
|
|
2714
|
+
"tabela de dados",
|
|
2715
|
+
"ordenação no servidor",
|
|
2716
|
+
"empty state",
|
|
2717
|
+
"row selection",
|
|
2718
|
+
"bulk actions",
|
|
2719
|
+
"manualPagination"
|
|
2720
|
+
],
|
|
2721
|
+
"anchors": {
|
|
2722
|
+
"contract": "#the-list-contract-url-and-api",
|
|
2723
|
+
"table": "#the-shared-datatable-tier-2",
|
|
2724
|
+
"states": "#the-three-states",
|
|
2725
|
+
"mobile": "#mobile"
|
|
2726
|
+
},
|
|
2727
|
+
"digest": "Every admin list is paged, sorted and filtered on the server, with page/pageSize/sort/dir/filters in the URL (searchParams parsed by a Zod schema with .catch defaults) and the API answering { items, totalCount } over an OrderBy plus a unique id tiebreaker. The Server Component page reads searchParams and wraps the results in a Suspense keyed by the query; one shared components/data-table.tsx on TanStack Table 9 sets manualPagination + rowCount, manualSorting and selection by a stable getRowId, and only writes the URL (router.replace with scroll:false, page reset on any filter/sort change). Three non-happy states always: loading skeleton, empty (no records vs no match for the filters), error as a value with retry via router.refresh(). Compact density, right-aligned tabular numbers, one inline row action plus a menu, a bulk bar over the selected page, a card list below md. Never 'first N + see all' instead of paging.",
|
|
2728
|
+
"verifiedAgainst": "Next.js 16 App Router + @tanstack/react-table 9 + Zod 4 + shadcn 4 (the code blocks typecheck under `tsc --strict`).",
|
|
2729
|
+
"provedBy": []
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
"id": "frontend-admin-app-feedback",
|
|
2733
|
+
"name": "feedback",
|
|
2734
|
+
"path": "frontend/admin-app/feedback.md",
|
|
2735
|
+
"category": "frontend",
|
|
2736
|
+
"subcategory": "admin-app",
|
|
2737
|
+
"tags": [
|
|
2738
|
+
"frontend",
|
|
2739
|
+
"admin-app"
|
|
2740
|
+
],
|
|
2741
|
+
"stacks": [
|
|
2742
|
+
"nextjs"
|
|
2743
|
+
],
|
|
2744
|
+
"aliases": [
|
|
2745
|
+
"confirmation dialog",
|
|
2746
|
+
"confirm dialog",
|
|
2747
|
+
"delete confirmation",
|
|
2748
|
+
"toast",
|
|
2749
|
+
"sonner",
|
|
2750
|
+
"toast messages",
|
|
2751
|
+
"undo toast",
|
|
2752
|
+
"diálogo de confirmação"
|
|
2753
|
+
],
|
|
2754
|
+
"anchors": {
|
|
2755
|
+
"when": "#when-to-confirm",
|
|
2756
|
+
"dialog": "#the-confirmation-dialog-tier-2",
|
|
2757
|
+
"catalog": "#the-toast-catalog"
|
|
2758
|
+
},
|
|
2759
|
+
"digest": "One ConfirmDialog (controlled shadcn AlertDialog, a plain Button that awaits the action, stays open showing the error on failure, optional type-to-confirm) used only for destructive-irreversible, bulk or discard-changes actions; a reversible action gets a 'Desfazer' toast instead. The title names the object and the confirm label repeats the verb. Every toast string comes from a catalog (lib/toast-messages.ts for generic outcomes + per-entity EntityMessages, because Portuguese agrees in gender and number); sonner toast.success/toast.error with an id per action, a longer duration for errors, errors mapped by status (403, 409, network), never the server's raw text, and field validation never in a toast.",
|
|
2760
|
+
"verifiedAgainst": "shadcn 4 `AlertDialog` (Radix) + sonner 2 + TanStack Query 5 (the code blocks typecheck under `tsc --strict`).",
|
|
2761
|
+
"provedBy": []
|
|
2762
|
+
},
|
|
2763
|
+
{
|
|
2764
|
+
"id": "frontend-admin-app-forms",
|
|
2765
|
+
"name": "forms",
|
|
2766
|
+
"path": "frontend/admin-app/forms.md",
|
|
2767
|
+
"category": "frontend",
|
|
2768
|
+
"subcategory": "admin-app",
|
|
2769
|
+
"tags": [
|
|
2770
|
+
"frontend",
|
|
2771
|
+
"admin-app"
|
|
2772
|
+
],
|
|
2773
|
+
"stacks": [
|
|
2774
|
+
"nextjs"
|
|
2775
|
+
],
|
|
2776
|
+
"aliases": [
|
|
2777
|
+
"admin form",
|
|
2778
|
+
"crud form",
|
|
2779
|
+
"server validation errors",
|
|
2780
|
+
"ValidationProblemDetails",
|
|
2781
|
+
"unsaved changes",
|
|
2782
|
+
"formulário"
|
|
2783
|
+
],
|
|
2784
|
+
"anchors": {
|
|
2785
|
+
"server-errors": "#server-errors-on-the-field",
|
|
2786
|
+
"placement": "#where-the-form-lives",
|
|
2787
|
+
"dirty": "#unsaved-changes"
|
|
2788
|
+
},
|
|
2789
|
+
"digest": "Admin forms use the one pattern of nextjs/forms.md (Zod schema, zodResolver, react-hook-form Controller + shadcn Field/FieldError, useMutation) plus the CRUD deltas: map .NET ValidationProblemDetails errors onto their fields with setError (unmatched ones go to root.serverError), mode 'onTouched', submit disabled only while saving, form.reset(values) after a successful save, a guard for unsaved changes, the three useForm generics (z.input / unknown / z.output) when the schema coerces, and placement by size: dialog up to 4 fields, sheet or page up to 12, its own page beyond that, a wizard when steps depend on each other.",
|
|
2790
|
+
"verifiedAgainst": "react-hook-form 7 + @hookform/resolvers 5 + Zod 4 + TanStack Query 5 + shadcn 4 `Field` (the code blocks typecheck under `tsc --strict`).",
|
|
2791
|
+
"provedBy": []
|
|
2792
|
+
},
|
|
2793
|
+
{
|
|
2794
|
+
"id": "frontend-admin-app-page-structure",
|
|
2795
|
+
"name": "page structure",
|
|
2796
|
+
"path": "frontend/admin-app/page-structure.md",
|
|
2797
|
+
"category": "frontend",
|
|
2798
|
+
"subcategory": "admin-app",
|
|
2799
|
+
"tags": [
|
|
2800
|
+
"frontend",
|
|
2801
|
+
"admin-app"
|
|
2802
|
+
],
|
|
2803
|
+
"stacks": [
|
|
2804
|
+
"nextjs"
|
|
2805
|
+
],
|
|
2806
|
+
"aliases": [
|
|
2807
|
+
"tabs",
|
|
2808
|
+
"abas",
|
|
2809
|
+
"long page",
|
|
2810
|
+
"página longa",
|
|
2811
|
+
"wizard",
|
|
2812
|
+
"multi-step form",
|
|
2813
|
+
"stepper",
|
|
2814
|
+
"detail page"
|
|
2815
|
+
],
|
|
2816
|
+
"anchors": {
|
|
2817
|
+
"decision": "#tabs-long-page-or-wizard",
|
|
2818
|
+
"tabs": "#tabs-in-the-url",
|
|
2819
|
+
"wizard": "#wizard-for-long-flows"
|
|
2820
|
+
},
|
|
2821
|
+
"digest": "Decide per screen and write it in the mockup checklist: tabs for 3+ independent sections, a long page with sticky section nav when sections are read together or share one save, a plain page for 2 short blocks, a wizard when later fields depend on earlier answers. The active tab lives in ?tab= and only its content is rendered and fetched on the server; switching tab drops the list params of the tab being left. Unbounded related lists get their own paged tab, never a capped preview. A wizard keeps one react-hook-form across steps, validates each step with trigger(stepFields), never loses data going back, and commits on a final review step.",
|
|
2822
|
+
"verifiedAgainst": "Next.js 16 App Router + shadcn 4 `Tabs` (Radix) + react-hook-form 7 + Zod 4 (the code blocks typecheck under `tsc --strict`).",
|
|
2823
|
+
"provedBy": []
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
"id": "architecture-code-comments",
|
|
2827
|
+
"name": "code comments",
|
|
2828
|
+
"path": "architecture/code-comments.md",
|
|
2829
|
+
"category": "architecture",
|
|
2830
|
+
"subcategory": null,
|
|
2831
|
+
"tags": [
|
|
2832
|
+
"architecture",
|
|
2833
|
+
"comments"
|
|
2834
|
+
],
|
|
2835
|
+
"stacks": [
|
|
2836
|
+
"*"
|
|
2837
|
+
],
|
|
2838
|
+
"aliases": [
|
|
2839
|
+
"code comments",
|
|
2840
|
+
"comentário de código",
|
|
2841
|
+
"comment policy",
|
|
2842
|
+
"política de comentário",
|
|
2843
|
+
"comentário de processo",
|
|
2844
|
+
"self-documenting code"
|
|
2845
|
+
],
|
|
2846
|
+
"anchors": {
|
|
2847
|
+
"comment-policy": "#o-que-merece-comentário",
|
|
2848
|
+
"not-worth": "#o-que-não-merece",
|
|
2849
|
+
"size": "#tamanho"
|
|
2850
|
+
},
|
|
2851
|
+
"digest": "Comment only the WHY the code cannot show: an invariant the type does not express, an order that matters, an external quirk (third-party API, library bug with its link), a public API contract. Never process history: task, UC, ADR, FR, Gate, evaluator, spec.md and mockup belong in the commit message and decisions.md. Do not restate the code (a good name replaces the comment), do not describe the world outside the file (it goes stale), and turn claims about behavior into test assertions. Ceiling ~3 lines; longer needs a reason. The verify validators node (code-budget) warns with the count of added comment lines that cite process.",
|
|
2852
|
+
"verifiedAgainst": "C#, TypeScript e JavaScript (convenção de linguagem, sem pacote externo).",
|
|
2853
|
+
"provedBy": []
|
|
2687
2854
|
}
|
|
2688
2855
|
],
|
|
2689
2856
|
"sharedAliases": {
|
|
@@ -2767,6 +2934,14 @@
|
|
|
2767
2934
|
"seedance": [
|
|
2768
2935
|
"ai-agents-media-video",
|
|
2769
2936
|
"frontend-design-system-ai-video-generation"
|
|
2937
|
+
],
|
|
2938
|
+
"test budget": [
|
|
2939
|
+
"backend-dotnet-testing",
|
|
2940
|
+
"frontend-nextjs-testing"
|
|
2941
|
+
],
|
|
2942
|
+
"orçamento de teste": [
|
|
2943
|
+
"backend-dotnet-testing",
|
|
2944
|
+
"frontend-nextjs-testing"
|
|
2770
2945
|
]
|
|
2771
2946
|
}
|
|
2772
2947
|
}
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
## Fronteira com o testing genérico
|
|
13
13
|
|
|
14
14
|
`backend-dotnet-testing` continua dono do que é de teste em .NET: xUnit, `FakeTimeProvider`,
|
|
15
|
-
isolamento entre casos, nomes de teste, organização de fixtures
|
|
15
|
+
isolamento entre casos, nomes de teste, organização de fixtures e o orçamento de teste por task.
|
|
16
|
+
**Nada disso se repete aqui.**
|
|
16
17
|
|
|
17
18
|
Este standard cobre **só o que é de agente** — e o que é de agente cabe em uma frase: o único ponto
|
|
18
19
|
em que o seu código toca um provider é um `IChatClient`. Todo o resto deste arquivo é consequência
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Comentários no código
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 0 (always load)
|
|
5
|
+
> **Keywords:** comentário, comentario, comment, docstring, jsdoc, xml doc, história da task, código autoexplicativo
|
|
6
|
+
> **Load When:** escrevendo ou revisando código em qualquer stack
|
|
7
|
+
|
|
8
|
+
**Verified against:** C#, TypeScript e JavaScript (convenção de linguagem, sem pacote externo). Last-verified: 2026-09-24.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Comentário é relido a cada leitura do arquivo, por quem mantém e pelo agente que abre o arquivo na
|
|
13
|
+
próxima task. Ele só se paga quando diz o que o código **não consegue** dizer.
|
|
14
|
+
|
|
15
|
+
## O que merece comentário
|
|
16
|
+
|
|
17
|
+
Só o **porquê que o código não mostra**:
|
|
18
|
+
|
|
19
|
+
| Merece | Exemplo |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Invariante que o tipo não expressa | "a chave é a identidade e o hash é a versão" |
|
|
22
|
+
| Ordem que importa | "invalidar o cache ANTES de publicar: o consumidor relê na hora" |
|
|
23
|
+
| Peculiaridade externa | API de terceiro que devolve 200 com erro no corpo; bug de biblioteca, com o link |
|
|
24
|
+
| Contrato de API pública | `///` ou JSDoc no membro público: o que recebe, devolve e lança |
|
|
25
|
+
|
|
26
|
+
## O que não merece
|
|
27
|
+
|
|
28
|
+
- **História de processo.** Task, UC, ADR, FR, Gate, avaliador, `spec.md`, mockup, "confirmado ao
|
|
29
|
+
implementar a T11", "o Gate 3 pediu". Isso vai na mensagem de commit e no `decisions.md`, onde tem
|
|
30
|
+
data e autor e não envelhece dentro do arquivo.
|
|
31
|
+
- **Repetição do código.** `// incrementa o contador` sobre `count++`. Nome bom substitui
|
|
32
|
+
comentário: extraia `isEligibleForRefund()` em vez de comentar a condição.
|
|
33
|
+
- **Estado do mundo fora do arquivo.** "Public Sans é a fonte da interface" passa a mentir na
|
|
34
|
+
primeira troca de fonte, e nada avisa.
|
|
35
|
+
- **Afirmação sobre comportamento.** "nunca retorna vazio", "ordenado por sobrenome": isso é
|
|
36
|
+
asserção de teste. A prosa não falha quando deixa de ser verdade; o teste falha.
|
|
37
|
+
|
|
38
|
+
## Tamanho
|
|
39
|
+
|
|
40
|
+
Teto de ~3 linhas. Acima disso o comentário justifica o volume (algoritmo não óbvio, armadilha de
|
|
41
|
+
terceiro com a reprodução). Bloco longo narrando decisões é `decisions.md` com outro nome.
|
|
42
|
+
|
|
43
|
+
## Exemplo
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// Ruim: conta a task, repete o código e afirma comportamento que nenhum teste cobra.
|
|
47
|
+
// T8 + T11: mutação obrigatória do relatório, item c. Confirmado ao implementar a T11.
|
|
48
|
+
// Faz upsert do documento com chave e hash e nunca duplica.
|
|
49
|
+
await upsert({ key: doc.sourceId, hash: sha256(doc.body) });
|
|
50
|
+
|
|
51
|
+
// Bom: o porquê que o código não mostra.
|
|
52
|
+
// A chave é a identidade e o hash é a versão: hash novo na mesma chave substitui.
|
|
53
|
+
await upsert({ key: doc.sourceId, hash: sha256(doc.body) });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Na revisão
|
|
57
|
+
|
|
58
|
+
Comentário de processo é achado da rubrica `code-quality` no Gate 3. O nó `validators` do
|
|
59
|
+
`morph-spec verify` mede, nas linhas que a feature adicionou, quantas linhas de comentário citam
|
|
60
|
+
processo (validador `code-budget`) e avisa com o número.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -113,6 +113,28 @@ respectively and the test suite stays green.
|
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
116
|
+
## Test budget
|
|
117
|
+
|
|
118
|
+
The plan (`morph-plan`) gives each task a budget: **one test per postcondition, plus one
|
|
119
|
+
regression test per bug fixed**. Going above it takes a one-line justification in the task.
|
|
120
|
+
|
|
121
|
+
- **Table before copy.** Scenarios of the same behavior — including its edge cases (null, empty,
|
|
122
|
+
boundary) — are rows of one `[Theory]` (`[InlineData]`/`[MemberData]`), never N `[Fact]` methods
|
|
123
|
+
that differ by one value.
|
|
124
|
+
- **No test that only pins text.** An assertion that is only the presence or absence of a string in
|
|
125
|
+
UI copy, tenant config or prose proves the file's version, not behavior. Enforce it with an
|
|
126
|
+
analyzer, a lint rule or a validation at publish time, outside the suite count. The versioned
|
|
127
|
+
prompt case (at most one structural test) is `ai-agents-testing-ai`.
|
|
128
|
+
- **Shared fixture by default.** Reuse the project's `WebApplicationFactory` fixture, fakes and
|
|
129
|
+
builders. Before writing a new helper, look for the existing one (`morph-spec graph explain
|
|
130
|
+
<Name>`; fallback without a graph: `grep -rn`).
|
|
131
|
+
- **TDD where it pays:** a bug gets its regression test first (red, then the fix), and so does pure
|
|
132
|
+
logic. Integration and endpoint tests may come after the code.
|
|
133
|
+
- **A surviving mutant** of the Gate 3 mutation proof is killed by tightening an existing assertion
|
|
134
|
+
or adding a table row, not by one new test per mutant.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
116
138
|
## Anti-Patterns
|
|
117
139
|
|
|
118
140
|
| Do NOT | Do Instead |
|