vouchington-tooling 0.20.0 → 0.22.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/README.md +73 -10
- package/dist/agent-blackboard/snapshot-partition-format.mjs +2 -72
- package/dist/agent-blackboard/snapshot-partition-guards.d.mts +3 -0
- package/dist/agent-blackboard/snapshot-partition-guards.mjs +9 -0
- package/dist/agent-blackboard/snapshot-partition-predicates.d.mts +3 -0
- package/dist/agent-blackboard/snapshot-partition-predicates.mjs +65 -0
- package/dist/api-contract-discovery/header-contract-parser.d.mts +3 -0
- package/dist/api-contract-discovery/header-contract-parser.mjs +93 -0
- package/dist/api-contract-discovery/header-contract-registry.d.mts +3 -0
- package/dist/api-contract-discovery/header-contract-registry.mjs +38 -0
- package/dist/api-contract-discovery/header-contract-types.d.mts +19 -0
- package/dist/api-contract-discovery/header-contract-types.mjs +1 -0
- package/dist/api-contract-discovery/index.d.mts +31 -0
- package/dist/api-contract-discovery/index.mjs +26 -0
- package/dist/api-contract-discovery/query-contract-extraction.d.mts +3 -0
- package/dist/api-contract-discovery/query-contract-extraction.mjs +65 -0
- package/dist/api-contract-discovery/query-contract-literals.d.mts +8 -0
- package/dist/api-contract-discovery/query-contract-literals.mjs +54 -0
- package/dist/api-contract-discovery/query-contract-registry.d.mts +3 -0
- package/dist/api-contract-discovery/query-contract-registry.mjs +68 -0
- package/dist/api-contract-discovery/query-contract-types.d.mts +8 -0
- package/dist/api-contract-discovery/query-contract-types.mjs +1 -0
- package/dist/api-contract-discovery/registered-route-catalog.d.mts +10 -0
- package/dist/api-contract-discovery/registered-route-catalog.mjs +81 -0
- package/dist/api-contract-discovery/registered-route-handler-analysis.d.mts +2 -0
- package/dist/api-contract-discovery/registered-route-handler-analysis.mjs +74 -0
- package/dist/api-contract-discovery/request-contract-implicit.d.mts +17 -0
- package/dist/api-contract-discovery/request-contract-implicit.mjs +73 -0
- package/dist/api-contract-discovery/request-contract-lenient.d.mts +28 -0
- package/dist/api-contract-discovery/request-contract-lenient.mjs +59 -0
- package/dist/api-contract-discovery/request-contract-registry.d.mts +14 -0
- package/dist/api-contract-discovery/request-contract-registry.mjs +61 -0
- package/dist/api-contract-discovery/request-contract-route-analysis.d.mts +25 -0
- package/dist/api-contract-discovery/request-contract-route-analysis.mjs +68 -0
- package/dist/api-contract-discovery/request-contract-types.d.mts +12 -0
- package/dist/api-contract-discovery/request-contract-types.mjs +1 -0
- package/dist/api-contract-discovery/response-contract-ctx-analysis.d.mts +7 -0
- package/dist/api-contract-discovery/response-contract-ctx-analysis.mjs +28 -0
- package/dist/api-contract-discovery/response-contract-error-branch.d.mts +15 -0
- package/dist/api-contract-discovery/response-contract-error-branch.mjs +47 -0
- package/dist/api-contract-discovery/response-contract-implicit-sources.test-helpers.d.mts +145 -0
- package/dist/api-contract-discovery/response-contract-implicit-sources.test-helpers.mjs +145 -0
- package/dist/api-contract-discovery/response-contract-implicit.d.mts +5 -0
- package/dist/api-contract-discovery/response-contract-implicit.mjs +110 -0
- package/dist/api-contract-discovery/response-contract-lenient.d.mts +23 -0
- package/dist/api-contract-discovery/response-contract-lenient.mjs +52 -0
- package/dist/api-contract-discovery/response-contract-media.d.mts +3 -0
- package/dist/api-contract-discovery/response-contract-media.mjs +46 -0
- package/dist/api-contract-discovery/response-contract-registration.d.mts +11 -0
- package/dist/api-contract-discovery/response-contract-registration.mjs +61 -0
- package/dist/api-contract-discovery/response-contract-registry.d.mts +7 -0
- package/dist/api-contract-discovery/response-contract-registry.mjs +76 -0
- package/dist/api-contract-discovery/response-contract-route-analysis.d.mts +13 -0
- package/dist/api-contract-discovery/response-contract-route-analysis.mjs +144 -0
- package/dist/api-contract-discovery/response-contract-status.d.mts +27 -0
- package/dist/api-contract-discovery/response-contract-status.mjs +80 -0
- package/dist/api-contract-discovery/response-contract-types.d.mts +16 -0
- package/dist/api-contract-discovery/response-contract-types.mjs +1 -0
- package/dist/api-contract-discovery/test-setup.test-helpers.d.mts +3 -0
- package/dist/api-contract-discovery/test-setup.test-helpers.mjs +2 -0
- package/dist/ast-grep-examples/companion-parity-compare.d.mts +3 -0
- package/dist/ast-grep-examples/companion-parity-compare.mjs +58 -0
- package/dist/ast-grep-examples/companion-parity.d.mts +2 -1
- package/dist/ast-grep-examples/companion-parity.mjs +2 -58
- package/dist/browser-session-runner/attempt.mjs +29 -48
- package/dist/browser-session-runner/termination.d.mts +11 -0
- package/dist/browser-session-runner/termination.mjs +34 -0
- package/dist/cli/parse-direct-options.d.mts +26 -0
- package/dist/cli/parse-direct-options.mjs +72 -0
- package/dist/cli/parse-forwarded-commands.d.mts +42 -0
- package/dist/cli/parse-forwarded-commands.mjs +29 -0
- package/dist/cli/parse-options.d.mts +1 -2
- package/dist/cli/parse-options.mjs +2 -72
- package/dist/cli/parse.mjs +4 -26
- package/dist/compiler-build/freshness.d.mts +27 -0
- package/dist/compiler-build/freshness.mjs +116 -0
- package/dist/compiler-build/index.d.mts +2 -0
- package/dist/compiler-build/index.mjs +2 -0
- package/dist/compiler-build/settlement.d.mts +10 -0
- package/dist/compiler-build/settlement.mjs +14 -0
- package/dist/config-inventory/call-arguments.d.mts +1 -0
- package/dist/config-inventory/call-arguments.mjs +30 -0
- package/dist/config-inventory/collect.d.mts +3 -0
- package/dist/config-inventory/collect.mjs +43 -0
- package/dist/config-inventory/dynamic-configs.d.mts +2 -0
- package/dist/config-inventory/dynamic-configs.mjs +9 -0
- package/dist/config-inventory/env-expression-readers.d.mts +3 -0
- package/dist/config-inventory/env-expression-readers.mjs +117 -0
- package/dist/config-inventory/env-prefix-readers.d.mts +2 -0
- package/dist/config-inventory/env-prefix-readers.mjs +14 -0
- package/dist/config-inventory/env-reference-matchers.d.mts +3 -0
- package/dist/config-inventory/env-reference-matchers.mjs +9 -0
- package/dist/config-inventory/env-var-accumulator.d.mts +6 -0
- package/dist/config-inventory/env-var-accumulator.mjs +82 -0
- package/dist/config-inventory/env-vars.d.mts +4 -0
- package/dist/config-inventory/env-vars.mjs +108 -0
- package/dist/config-inventory/format.d.mts +2 -0
- package/dist/config-inventory/format.mjs +69 -0
- package/dist/config-inventory/index.d.mts +3 -0
- package/dist/config-inventory/index.mjs +2 -0
- package/dist/config-inventory/package-gates.d.mts +2 -0
- package/dist/config-inventory/package-gates.mjs +54 -0
- package/dist/config-inventory/shared.d.mts +3 -0
- package/dist/config-inventory/shared.mjs +7 -0
- package/dist/config-inventory/types.d.mts +96 -0
- package/dist/config-inventory/types.mjs +1 -0
- package/dist/contract-schema/contract-schema-bounded-array.d.mts +15 -0
- package/dist/contract-schema/contract-schema-bounded-array.mjs +32 -0
- package/dist/contract-schema/contract-schema-type-extractor.d.mts +2 -8
- package/dist/contract-schema/contract-schema-type-extractor.mjs +2 -31
- package/dist/coverage-transport/control-v2-parse-object.d.mts +12 -0
- package/dist/coverage-transport/control-v2-parse-object.mjs +28 -0
- package/dist/coverage-transport/control-v2.mjs +2 -27
- package/dist/dependency-license-policy/audit-directory.d.mts +28 -0
- package/dist/dependency-license-policy/audit-directory.mjs +115 -0
- package/dist/dependency-license-policy/audit-signals.d.mts +12 -0
- package/dist/dependency-license-policy/audit-signals.mjs +44 -0
- package/dist/dependency-license-policy/audit-store.d.mts +12 -0
- package/dist/dependency-license-policy/audit-store.mjs +32 -0
- package/dist/dependency-license-policy/collect.d.mts +3 -1
- package/dist/dependency-license-policy/collect.mjs +16 -21
- package/dist/dependency-license-policy/execute-pnpm.d.mts +10 -0
- package/dist/dependency-license-policy/execute-pnpm.mjs +83 -0
- package/dist/dependency-license-policy/types.d.mts +11 -9
- package/dist/dependency-license-policy/workspace.d.mts +3 -1
- package/dist/dependency-license-policy/workspace.mjs +12 -5
- package/dist/gh-api-shell-quoting/argument-scan.d.mts +7 -0
- package/dist/gh-api-shell-quoting/argument-scan.mjs +35 -0
- package/dist/gh-api-shell-quoting/logical-line.d.mts +3 -0
- package/dist/gh-api-shell-quoting/logical-line.mjs +90 -0
- package/dist/gh-api-shell-quoting/scan.d.mts +2 -4
- package/dist/gh-api-shell-quoting/scan.mjs +1 -119
- package/dist/gh-cli/diff.d.mts +24 -4
- package/dist/gh-cli/diff.mjs +111 -4
- package/dist/gh-cli/index.d.mts +2 -1
- package/dist/gh-cli/index.mjs +1 -1
- package/dist/gha-workspace-policy/docker-options.d.mts +4 -0
- package/dist/gha-workspace-policy/docker-options.mjs +93 -0
- package/dist/gha-workspace-policy/docker-workspace-user.mjs +1 -168
- package/dist/gha-workspace-policy/shell-token-modes.d.mts +10 -0
- package/dist/gha-workspace-policy/shell-token-modes.mjs +31 -0
- package/dist/gha-workspace-policy/shell-tokens.d.mts +1 -0
- package/dist/gha-workspace-policy/shell-tokens.mjs +65 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +1 -1
- package/dist/openapi-document/contract-schema-types.d.mts +1 -1
- package/dist/openapi-document/openapi-types.d.mts +1 -1
- package/dist/pnpm-install/native-family.d.mts +3 -0
- package/dist/pnpm-install/native-family.mjs +31 -0
- package/dist/pnpm-install/native-health.d.mts +1 -4
- package/dist/pnpm-install/native-health.mjs +2 -31
- package/dist/retrospective-facts/local-merge.d.mts +2 -0
- package/dist/retrospective-facts/local-merge.mjs +21 -0
- package/dist/retrospective-facts/local.mjs +1 -21
- package/dist/retrospective-transcript/claude-blocks.d.mts +3 -0
- package/dist/retrospective-transcript/claude-blocks.mjs +38 -0
- package/dist/retrospective-transcript/claude.mjs +4 -34
- package/dist/retrospective-transcript/codex-payload.d.mts +2 -0
- package/dist/retrospective-transcript/codex-payload.mjs +51 -0
- package/dist/retrospective-transcript/codex-records.d.mts +2 -0
- package/dist/retrospective-transcript/codex-records.mjs +95 -0
- package/dist/retrospective-transcript/codex.mjs +2 -144
- package/dist/retrospective-transcript/index.d.mts +3 -16
- package/dist/retrospective-transcript/index.mjs +4 -48
- package/dist/retrospective-transcript/resolve-transcript-file.d.mts +19 -0
- package/dist/retrospective-transcript/resolve-transcript-file.mjs +50 -0
- package/dist/session-friction/command-segments.d.mts +3 -0
- package/dist/session-friction/command-segments.mjs +94 -0
- package/dist/session-friction/log-file.d.mts +7 -0
- package/dist/session-friction/log-file.mjs +83 -0
- package/dist/session-friction/log.mjs +3 -83
- package/dist/session-friction/normalize.mjs +1 -94
- package/dist/sql-scanner/comments.d.mts +1 -0
- package/dist/sql-scanner/comments.mjs +101 -0
- package/dist/sql-scanner/index.d.mts +1 -1
- package/dist/sql-scanner/index.mjs +1 -100
- package/dist/sql-scanner/literals.mjs +1 -35
- package/dist/sql-scanner/quote-decode.d.mts +2 -0
- package/dist/sql-scanner/quote-decode.mjs +35 -0
- package/dist/vitest-diagnostics/index.d.mts +7 -0
- package/dist/vitest-diagnostics/index.mjs +4 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-error-detail.d.mts +7 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-error-detail.mjs +26 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-records.d.mts +26 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-records.mjs +161 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-sentinel.d.mts +14 -0
- package/dist/vitest-diagnostics/vitest-fork-exit-sentinel.mjs +131 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-detection.d.mts +26 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-detection.mjs +96 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-diagnostics.d.mts +3 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-diagnostics.mjs +14 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-episode.d.mts +37 -0
- package/dist/vitest-diagnostics/vitest-fork-leak-episode.mjs +118 -0
- package/dist/vitest-diagnostics/vitest-worker-exit-diagnostics-errors.d.mts +2 -0
- package/dist/vitest-diagnostics/vitest-worker-exit-diagnostics-errors.mjs +42 -0
- package/dist/vitest-diagnostics/vitest-worker-exit-diagnostics-reporter.d.mts +12 -0
- package/dist/vitest-diagnostics/vitest-worker-exit-diagnostics-reporter.mjs +142 -0
- package/dist/workflow-policy/concurrency-scope.d.mts +4 -0
- package/dist/workflow-policy/concurrency-scope.mjs +66 -0
- package/dist/workflow-policy/concurrency.d.mts +10 -0
- package/dist/workflow-policy/concurrency.mjs +77 -0
- package/dist/workflow-policy/condition-entailment.d.mts +20 -0
- package/dist/workflow-policy/condition-entailment.mjs +132 -0
- package/dist/workflow-policy/condition-split.d.mts +15 -0
- package/dist/workflow-policy/condition-split.mjs +71 -0
- package/dist/workflow-policy/graph.d.mts +2 -0
- package/dist/workflow-policy/graph.mjs +138 -0
- package/dist/workflow-policy/index.d.mts +7 -0
- package/dist/workflow-policy/index.mjs +6 -0
- package/dist/workflow-policy/permission-mismatches.d.mts +3 -0
- package/dist/workflow-policy/permission-mismatches.mjs +52 -0
- package/dist/workflow-policy/permissions.d.mts +16 -0
- package/dist/workflow-policy/permissions.mjs +83 -0
- package/dist/workflow-policy/secret-readiness.d.mts +18 -0
- package/dist/workflow-policy/secret-readiness.mjs +163 -0
- package/dist/workflow-policy/shell-comments.d.mts +7 -0
- package/dist/workflow-policy/shell-comments.mjs +28 -0
- package/dist/workflow-policy/types.d.mts +90 -0
- package/dist/workflow-policy/types.mjs +1 -0
- package/dist/workspace-gates/manifest-version-parser.mjs +1 -52
- package/dist/workspace-gates/manifest-version-skips.d.mts +1 -0
- package/dist/workspace-gates/manifest-version-skips.mjs +52 -0
- package/docs/workflow-and-compiler.md +74 -0
- package/package.json +26 -2
- package/skills/agent-workflow/SKILL.md +4 -4
- package/skills/agent-workflow/references/review-response.md +47 -44
- package/skills/backend-vitest-test-authoring/SKILL.md +9 -6
- package/skills/blackboard/SKILL.md +8 -8
- package/skills/dependabot/SKILL.md +68 -67
- package/skills/dotnet-test-authoring/SKILL.md +11 -12
- package/skills/git-commit-checklist/SKILL.md +3 -3
- package/skills/github-actions-authoring/SKILL.md +40 -38
- package/skills/github-actions-checklist/SKILL.md +93 -85
- package/skills/github-issue/SKILL.md +82 -78
- package/skills/nextjs-vitest-test-authoring/SKILL.md +8 -6
- package/skills/npm-publishing/SKILL.md +42 -38
- package/skills/organize-github-issues/SKILL.md +18 -22
- package/skills/package-json-checklist/SKILL.md +5 -5
- package/skills/planning/SKILL.md +3 -3
- package/skills/playwright-authoring/SKILL.md +10 -9
- package/skills/postgres-node-performance-tuning/SKILL.md +10 -6
- package/skills/postgres-partitioning-uuid-v7/SKILL.md +10 -7
- package/skills/pr-description/SKILL.md +4 -3
- package/skills/retrospective/SKILL.md +14 -15
- package/skills/retrospective-distill/SKILL.md +14 -14
- package/skills/review-ci-logs/SKILL.md +18 -19
- package/skills/review-github-issue-taxonomy/SKILL.md +21 -18
- package/skills/revisit-followups/SKILL.md +3 -3
- package/skills/stacked-prs/SKILL.md +30 -61
- package/skills/static-analysis-checklist/SKILL.md +6 -4
- package/skills/storybook-authoring/SKILL.md +9 -9
- package/skills/swift-test-authoring/SKILL.md +10 -9
- package/skills/test-authoring/SKILL.md +14 -14
- package/skills/test-authoring/references/core-practice.md +12 -11
- package/skills/test-authoring/references/dependency-boundaries.md +36 -35
- package/skills/test-authoring/references/tautological-tests.md +45 -44
- package/skills/vitest-test-authoring/SKILL.md +9 -6
|
@@ -5,17 +5,16 @@ description: Add maintainable .NET tests with appropriate unit, app, and integra
|
|
|
5
5
|
|
|
6
6
|
# .NET test authoring
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
where the project requires it, isolate process and filesystem state, and assert serialized contracts
|
|
10
|
-
instead of private implementation details. Keep test helpers typed and reusable only when they remove
|
|
11
|
-
repeated setup without hiding important expectations.
|
|
8
|
+
Apply [test-authoring](../test-authoring/SKILL.md).
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
- Place a test at the narrowest layer that proves the behavior.
|
|
11
|
+
- Batch native or external selection where the project requires it.
|
|
12
|
+
- Isolate process and filesystem state.
|
|
13
|
+
- Assert a serialized contract. Do not assert a private implementation detail.
|
|
14
|
+
- Keep a helper typed and reusable only when it removes repeated setup without hiding an
|
|
15
|
+
expectation.
|
|
16
|
+
- Keep portable library tests separate from rendered application tests.
|
|
17
|
+
- Batch compatible native targets in one selection pass so one shared build validates that source
|
|
18
|
+
set.
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
in one selection pass so a shared build validates the same source set.
|
|
17
|
-
|
|
18
|
-
Before finishing an assertion, name a concrete defect in the code under test that would make it fail;
|
|
19
|
-
an `Assert.True(true)` or a re-implemented computation compared against itself passes for every input
|
|
20
|
-
and proves nothing, so treat [tautological tests](../test-authoring/references/tautological-tests.md)
|
|
21
|
-
as a defect even when coverage looks satisfied.
|
|
20
|
+
Consumer wrapper owns: solution layout, test frameworks, native dependencies, and coverage policy.
|
|
@@ -5,7 +5,7 @@ description: Use before staging and committing changes to verify scope, validati
|
|
|
5
5
|
|
|
6
6
|
# Git commit checklist
|
|
7
7
|
|
|
8
|
-
Use before every commit. Read local `AGENTS.md`,
|
|
8
|
+
Use before every commit. Read local `AGENTS.md`, contribution guidance, and hook
|
|
9
9
|
output first; they own commit format, required trailers, file-size limits, and validation commands.
|
|
10
10
|
|
|
11
11
|
1. Inspect `git status` and the complete diff. Stage only files that implement the accepted task.
|
|
@@ -17,5 +17,5 @@ output first; they own commit format, required trailers, file-size limits, and v
|
|
|
17
17
|
5. Re-read the staged diff and commit message before committing. Do not amend another author's
|
|
18
18
|
work or rewrite history unless local policy and explicit authorization allow it.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Local instructions or the consumer wrapper own: branch names, file-size budgets, commit
|
|
21
|
+
conventions, pull-request templates, and push commands.
|
|
@@ -5,53 +5,55 @@ description: Author or redesign GitHub Actions workflows around event-driven orc
|
|
|
5
5
|
|
|
6
6
|
# GitHub Actions authoring
|
|
7
7
|
|
|
8
|
-
Never poll in CI. A workflow
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
Never poll in CI. A workflow reacts to a state transition. Read
|
|
9
|
+
[github-actions-checklist](../github-actions-checklist/SKILL.md) first, then every applicable
|
|
10
|
+
`AGENTS.md`. Repository-local policy and the consumer wrapper own runner labels,
|
|
11
|
+
permissions, action pins, concurrency, secrets, and required-check names.
|
|
12
12
|
|
|
13
13
|
## Design the event graph
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
- Name the producer, the durable transition it emits, and the consumer that owns the next action.
|
|
16
|
+
- Use `needs` for jobs in one workflow. Use `workflow_call` when the caller must await a reusable
|
|
17
|
+
workflow. When a consumer must run after failure or skip, give it an explicit status condition and
|
|
18
|
+
read `needs.<job>.result`. The implicit success condition skips it otherwise.
|
|
19
|
+
- Use `workflow_run` when a completed workflow is the trusted event boundary. Validate the source
|
|
20
|
+
workflow, repository, branch or pull-request head, conclusion, and artifacts before acting.
|
|
21
|
+
- The `workflow_run` receiver must already exist on the default branch. GitHub chains at most three
|
|
22
|
+
`workflow_run` levels. Plan that rollout, and collapse a deeper chain into one DAG.
|
|
23
|
+
- Use `repository_dispatch` for a cross-repository transition or an authenticated external callback.
|
|
24
|
+
Authenticate the sender, pass immutable correlation data, validate it against the source, and make
|
|
25
|
+
duplicate delivery safe. The receiver must already exist on the default branch before senders are
|
|
26
|
+
enabled.
|
|
27
|
+
- Prefer a provider-native completion event, callback, queue, or state-machine transition for a
|
|
28
|
+
deployment or service.
|
|
29
|
+
- A scheduled reconciliation workflow may repair a missed event. It inspects one snapshot and exits.
|
|
30
|
+
It does not wait for convergence.
|
|
30
31
|
|
|
31
32
|
## Persistent workspaces
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
bind mounts use a non-root identity whose ownership and write access are compatible with the runner.
|
|
36
|
-
Do not make each job traverse the whole workspace before checkout to repair permissions. Drain and
|
|
37
|
-
migrate an already contaminated runner once. At runtime, repair may cover bounded known generated
|
|
38
|
-
paths; a workspace-wide fallback must stay failure-gated, same-filesystem, directory-only, and batched,
|
|
39
|
-
with path-count and timing evidence in its diagnostics.
|
|
34
|
+
Apply the persistent-workspace rules in
|
|
35
|
+
[github-actions-checklist](../github-actions-checklist/SKILL.md).
|
|
40
36
|
|
|
41
37
|
## Reject polling designs
|
|
42
38
|
|
|
43
|
-
Do not add a sleep-and-read loop, repeated run
|
|
44
|
-
or recursive redispatch whose purpose is to
|
|
45
|
-
cost
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Bounded retries are allowed only for the same failed operation when failure is
|
|
49
|
-
operation is idempotent.
|
|
50
|
-
|
|
39
|
+
- Do not add a sleep-and-read loop, a repeated query of a run, check, deployment, lease, or
|
|
40
|
+
service, a CLI waiter, or a recursive redispatch whose purpose is to watch remote state change.
|
|
41
|
+
- A timeout caps cost. It does not make polling event-driven.
|
|
42
|
+
- If the producer cannot emit a usable event, add the bridge at the producer or provider boundary
|
|
43
|
+
and let that bridge dispatch the correlated completion event.
|
|
44
|
+
- Bounded retries are allowed only for the same failed operation, and only when the failure is
|
|
45
|
+
transient and the operation is idempotent.
|
|
46
|
+
- A local process readiness check is allowed when that process runs inside the job and cannot emit
|
|
47
|
+
a workflow event.
|
|
48
|
+
- Neither exception allows repeated observation of remote state.
|
|
51
49
|
|
|
52
50
|
## Validate the result
|
|
53
51
|
|
|
54
|
-
Test accepted, rejected, duplicate, stale, and out-of-order events.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
- Test accepted, rejected, duplicate, stale, and out-of-order events.
|
|
53
|
+
- Preserve required-check names. Prove that every terminal producer outcome causes one terminal
|
|
54
|
+
consumer outcome.
|
|
55
|
+
- Run the local workflow checker and affected tests. Inspect the event graph for credentials
|
|
56
|
+
crossing an untrusted boundary, a missing correlation field, and any remaining polling path.
|
|
57
|
+
|
|
58
|
+
Consumer wrapper owns: runner labels, permissions, action pins, concurrency, secrets, and
|
|
59
|
+
required-check names.
|
|
@@ -6,97 +6,105 @@ description: Use when editing GitHub Actions workflows or composite actions to k
|
|
|
6
6
|
# GitHub Actions checklist
|
|
7
7
|
|
|
8
8
|
Use before editing a workflow or composite action. Repository-local instructions own runners,
|
|
9
|
-
approved action
|
|
9
|
+
approved action pins, concurrency names, secrets, permissions, and workflow-only pull-request rules.
|
|
10
|
+
Apply this baseline unless a stricter local rule overrides it.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
## Triggers and required checks
|
|
12
13
|
|
|
13
|
-
- Use `pull_request` for pull-request workflows in private repositories.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
Do not poll remote workflow,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
14
|
+
- Use `pull_request` for pull-request workflows in private repositories.
|
|
15
|
+
- Reserve `pull_request_target` for base-owned orchestration in a public repository, or for a
|
|
16
|
+
narrowly scoped Dependabot or Renovate workflow.
|
|
17
|
+
- A privileged workflow must not check out or execute untrusted pull-request content.
|
|
18
|
+
- When changing orchestration, load
|
|
19
|
+
[github-actions-authoring](../github-actions-authoring/SKILL.md). Do not poll remote workflow,
|
|
20
|
+
deployment, lease, service, or health state.
|
|
21
|
+
- Required checks must be actual workflow jobs that run or aggregate the work they report.
|
|
22
|
+
- Workflow code must not create or publish check runs or commit statuses to synthesize a required
|
|
23
|
+
context, copy another workflow's conclusion, or bypass the event graph.
|
|
24
|
+
- An external CI or analysis integration may report its own result. Do not relay GitHub Actions
|
|
25
|
+
work through its API.
|
|
26
|
+
|
|
27
|
+
## Tests, concurrency, and timeouts
|
|
28
|
+
|
|
29
|
+
- On `main`, or the consumer's configured default branch, split test jobs by domain, such as web
|
|
30
|
+
and backend. Keep required-check job names stable. Add a bounded fan-in job only when the merge
|
|
31
|
+
contract needs one combined result.
|
|
32
|
+
- Serialize test runs for the same pull request or default branch with one stable concurrency group.
|
|
33
|
+
- For pull requests, set `cancel-in-progress: true`. On `main`, or the consumer's configured default
|
|
34
|
+
branch, set `cancel-in-progress: false` so the active run finishes before the newest pending
|
|
35
|
+
revision starts. GitHub may replace an older pending main run with the newest pending revision;
|
|
36
|
+
preserving every intermediate queued revision is not required.
|
|
37
|
+
- When one workflow handles both events, make `cancel-in-progress` conditional on the pull-request
|
|
38
|
+
event. Keep the pull-request number or branch ref in the group.
|
|
39
|
+
- Give every concrete job `timeout-minutes` of at most 30 minutes. A top-level `jobs.<job_id>.uses`
|
|
40
|
+
caller cannot accept `timeout-minutes`; set it on every concrete job in the called workflow.
|
|
41
|
+
- If the operation cannot finish inside that bound, split it into event-driven phases. Lowering or
|
|
42
|
+
moving the timeout does not fix the design. Preserve a required job or check name with a bounded
|
|
43
|
+
fan-in job when the split would otherwise change the merge contract.
|
|
44
|
+
- Each underlying phase also has a deadline of no more than 30 minutes and supports cancellation,
|
|
45
|
+
rollback, or an explicit terminal retained or recovery state. A callback may report completion. It
|
|
46
|
+
must not hide a longer-running operation in another service.
|
|
47
|
+
- Keep each job's `timeout-minutes` below any hard platform limit of its runner so the job's own
|
|
48
|
+
cancellation fires first and `always()`/`cancelled()` cleanup steps still run. Example: no more
|
|
49
|
+
than 14 minutes on a runner with a 15-minute hard cap that `timeout-minutes` cannot raise.
|
|
50
|
+
- Give every long-running, network-bound, or waiting step its own `timeout-minutes` inside the job
|
|
51
|
+
budget. Bound every network call, such as `curl --connect-timeout … --max-time …`.
|
|
52
|
+
|
|
53
|
+
## Runners and persistent workspaces
|
|
54
|
+
|
|
55
|
+
- Prefer GitHub-hosted runners for public and private repositories. Choose the smallest hosted
|
|
56
|
+
runner the job fits, such as `ubuntu-slim` for a short job that needs no Docker daemon. Use a full
|
|
57
|
+
VM or native-architecture runner only for work the smaller runner cannot do. A consumer that still
|
|
47
58
|
requires self-hosted or disposable runners names its approved labels in repository-local policy.
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
instead of the runner being killed outright once the platform limit is reached. Give every
|
|
52
|
-
long-running, network-bound, or waiting step its own `timeout-minutes` inside the job budget, and
|
|
53
|
-
bound every network call, such as `curl --connect-timeout … --max-time …`.
|
|
54
|
-
- Ephemeral hosted runners start from a clean workspace. Do not add workspace-cleanup steps for them,
|
|
55
|
-
and check out with `persist-credentials: false` unless a later step must push with that token.
|
|
59
|
+
- Ephemeral hosted runners start from a clean workspace. Do not add workspace-cleanup steps for
|
|
60
|
+
them, and check out with `persist-credentials: false` unless a later step must push with that
|
|
61
|
+
token.
|
|
56
62
|
- Moving a job from a self-hosted or other persistent runner to a GitHub-hosted one drops every
|
|
57
|
-
piece of runner-local state the job
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
piece of runner-local state the job assumed was already there. Audit browser installs (a
|
|
64
|
+
Playwright, Cypress, or Puppeteer cache), package-manager stores (pnpm/npm, Go modules, a Rust
|
|
65
|
+
`target/` directory, Gradle), `apt-get install` steps that used to be a no-op because the package
|
|
66
|
+
was already present, and Docker image pulls that used to hit a warm local image store. A comment
|
|
67
|
+
that a tool "persists between runs so caching is not needed" describes the old runner and becomes
|
|
68
|
+
false the moment `runs-on` changes; replace that assumption with a keyed `actions/cache` step
|
|
69
|
+
instead. Re-derive `timeout-minutes` from a real passing run on the new runner rather than
|
|
70
|
+
carrying over a budget calibrated on a warm host.
|
|
71
|
+
- A persistent workspace checks out the full tree. Do not configure sparse checkout. Enforce that
|
|
72
|
+
with a YAML-aware check over intended tracked workflow and action files, with accepted and
|
|
73
|
+
rejected fixtures.
|
|
74
|
+
- Fix workspace ownership at the producer. A writable workspace bind mount uses a non-root identity
|
|
75
|
+
whose ownership and write access match the runner workspace.
|
|
76
|
+
- Do not add an unconditional pre-checkout workspace-wide permission or ownership traversal.
|
|
77
|
+
- Migrate a contaminated workspace once, while the runner is drained.
|
|
78
|
+
- Routine repair may cover bounded known generated paths. A workspace-wide fallback must be
|
|
79
|
+
failure-gated, same-filesystem, directory-only, and batched,
|
|
80
|
+
and must record path count and timing.
|
|
81
|
+
|
|
82
|
+
## Pinning
|
|
83
|
+
|
|
84
|
+
- Pin every repository-backed external `uses:` reference — anything other than a local `./...`
|
|
85
|
+
action or a `$/` self-repository reference — to a full lowercase 40-character Git SHA and its
|
|
86
|
+
immediate machine-maintainable version comment, such as `# v4.2.0`, so Dependabot can update both.
|
|
87
|
+
- A `$/` reference is the same repository at the running commit. It must not include an `@ref`.
|
|
88
|
+
- Pin `docker://...` actions to an immutable `@sha256:` image digest. Keep GitHub Actions dependency
|
|
89
|
+
updates enabled.
|
|
82
90
|
- Workflow tests and fixtures must not assert an action dependency's exact SHA or version. Assert
|
|
83
|
-
the action identity and Git SHA shape, or
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
the action identity and Git SHA shape, or read the ref from the workflow under test.
|
|
92
|
+
- This does not prohibit asserting an exact source revision in `with.ref` when exact-head checkout
|
|
93
|
+
is a workflow security invariant.
|
|
94
|
+
|
|
95
|
+
## Edit
|
|
87
96
|
|
|
88
|
-
1. Read every applicable `AGENTS.md`
|
|
89
|
-
plus
|
|
90
|
-
|
|
97
|
+
1. Read every applicable `AGENTS.md` from the repository root through the workflow,
|
|
98
|
+
plus CI docs and callers. On conflict, apply the closest instruction. Name trusted inputs,
|
|
99
|
+
untrusted inputs, and every credential boundary.
|
|
91
100
|
2. Give each job the least permissions it needs. Keep untrusted pull-request content out of shell
|
|
92
101
|
interpolation, privileged tokens, and write-capable steps.
|
|
93
|
-
3. Apply
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
unsupported runner assumptions, and unreachable workflow paths.
|
|
102
|
+
3. Apply this baseline and any stricter consumer policy. Keep checkout refs, artifact boundaries,
|
|
103
|
+
caches, and concurrency explicit.
|
|
104
|
+
4. Validate changed YAML with the local workflow checker and run the affected tests or scripts.
|
|
105
|
+
Update local CI docs when behavior or operator expectations change.
|
|
106
|
+
5. Review the diff for privilege escalation, secret exposure, unsafe quoting, unsupported runner
|
|
107
|
+
assumptions, and unreachable paths.
|
|
100
108
|
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
Consumer wrapper owns: runner labels, action SHAs, workflow directories, concurrency scheme, and
|
|
110
|
+
release policy.
|
|
@@ -5,91 +5,95 @@ description: Search, create, update, link, or assess GitHub issues using the rep
|
|
|
5
5
|
|
|
6
6
|
# GitHub issues
|
|
7
7
|
|
|
8
|
-
Use for durable follow-ups and pull-request linkage. Read local `AGENTS.md`,
|
|
9
|
-
templates, and repository-routing policy before
|
|
8
|
+
Use for durable follow-ups and pull-request linkage. Read local `AGENTS.md`, issue
|
|
9
|
+
templates, and repository-routing policy before any remote mutation.
|
|
10
10
|
|
|
11
11
|
## Mutation authority
|
|
12
12
|
|
|
13
|
-
Caller authorization is required before any issue or taxonomy mutation
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
- Caller authorization is required before any issue or taxonomy mutation. A credential does not
|
|
14
|
+
grant scope.
|
|
15
|
+
- Resolve the authenticated identity, current repository, and requested target. Do not assume an
|
|
16
|
+
owner prefix or visibility.
|
|
17
|
+
- Immediately before every write, refetch the exact target. Its canonical identity must still
|
|
18
|
+
match, and the repository must not be archived.
|
|
19
|
+
- Issue operations require issues to be enabled and `viewerPermission` of `TRIAGE`, `WRITE`,
|
|
20
|
+
`MAINTAIN`, or `ADMIN`. Issue creation additionally requires `viewerCanCreateIssues`.
|
|
21
|
+
- Applying existing metadata to a pull request uses that same permission set and does not require
|
|
22
|
+
issues to be enabled.
|
|
23
|
+
- Creating, changing, or deleting taxonomy definitions requires `WRITE`, `MAINTAIN`, or `ADMIN`
|
|
24
|
+
plus the operation-specific API capability. Creating, renaming, or closing a project requires
|
|
25
|
+
project-write.
|
|
26
|
+
- Insufficient permission or capability, missing or inaccessible data, an identity change, or a
|
|
27
|
+
mismatch is a hard deny. Approval cannot override it.
|
|
28
|
+
- Adding an item to an existing project uses the same permission set as applying existing metadata,
|
|
29
|
+
plus project-write. That add mutates project membership and needs no separate approval.
|
|
30
|
+
- Missing project scope or capability denies the project step only. Skip it, report the gap, and
|
|
31
|
+
do not work around it. The issue and its other metadata still proceed.
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
## Denied external target
|
|
34
|
+
|
|
35
|
+
- Do not write to a denied external creation target.
|
|
36
|
+
- Search for, then create or reuse, a tracking issue in the current repository or a
|
|
37
|
+
consumer-selected tracker. Immediately before that write, refetch the destination and apply the
|
|
38
|
+
issue-operation gate above.
|
|
39
|
+
- Include the intended upstream repository and a copy-ready report.
|
|
40
|
+
- Before naming that upstream repository, resolve it and compare the returned canonical name with
|
|
41
|
+
the name being written. A rename redirect resolves under the stale name, so existence is not
|
|
42
|
+
identity. This check is report accuracy, not the hard-deny mismatch above: write the canonical
|
|
43
|
+
name. When the name does not resolve, route the follow-up to the current repository and do not
|
|
44
|
+
name the unreachable target.
|
|
45
|
+
- Before copying details to a less-restricted destination, remove private repository identity,
|
|
46
|
+
paths, links, code, and findings. If redaction would make the report unusable, require explicit
|
|
47
|
+
destination approval or return the draft without mutation.
|
|
48
|
+
- Authorization to file the external issue includes this tracking fallback unless the caller opts
|
|
49
|
+
out. Report the reroute. If no tracker passes, return the draft without mutation.
|
|
50
|
+
- Do not fall back silently, and do not fall back to an unverified repository.
|
|
45
51
|
|
|
46
52
|
## Issue workflow
|
|
47
53
|
|
|
48
|
-
1. Search open and relevant closed issues in the
|
|
49
|
-
|
|
50
|
-
2. Before editing, commenting, relating, closing, or otherwise changing state, refetch the issue
|
|
51
|
-
its
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
3. Write a self-contained issue
|
|
55
|
-
|
|
54
|
+
1. Search open issues and relevant closed issues in the destination. Return a likely duplicate
|
|
55
|
+
instead of filing one. Verify the paths and current behavior the issue names.
|
|
56
|
+
2. Before editing, commenting, relating, closing, or otherwise changing state, refetch the issue
|
|
57
|
+
and its discussion. Confirm the mutation is still authorized and supported. Close only when the
|
|
58
|
+
documented outcome and acceptance evidence show the work is resolved. Otherwise leave state
|
|
59
|
+
unchanged and report the gap.
|
|
60
|
+
3. Write a self-contained issue: problem, desired outcome, ownership boundaries, concrete areas,
|
|
61
|
+
validation, and external context. A discovered blocker does not widen implementation scope.
|
|
56
62
|
4. Fetch the complete live taxonomy, including open projects. Apply matching existing labels and a
|
|
57
|
-
selected existing milestone
|
|
58
|
-
strategic, initiative-level tracking and a milestone for
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
7. Use native sub-issues only for real hierarchy, blocked-by relationships only for genuine known
|
|
88
|
-
dependencies, and prose links for merely related work. Read every created relationship back.
|
|
63
|
+
selected existing milestone with no separate approval.
|
|
64
|
+
- Use an existing open project for strategic, initiative-level tracking, and a milestone for
|
|
65
|
+
repo-local release or sequencing. Choose by the initiative, not by how many repositories it
|
|
66
|
+
touches. A single-repo strategic initiative can have a project. An initiative can have both.
|
|
67
|
+
An issue belongs to at most one project, and not every issue needs one.
|
|
68
|
+
- Before adding a project item, check that item and any item the project's automation could
|
|
69
|
+
pull in with it, such as a parent issue's sub-issues. If any already belongs to a different
|
|
70
|
+
project, skip the add and report the conflict.
|
|
71
|
+
- Adding an item to an existing, described project needs no separate approval. Creating,
|
|
72
|
+
renaming, or closing a project is a separate taxonomy operation, as is creating a milestone.
|
|
73
|
+
- Missing project scope or permission skips the project step. Report the gap and do not work
|
|
74
|
+
around it.
|
|
75
|
+
- Do not set a project status that closes the issue unless closing is separately authorized.
|
|
76
|
+
GitHub's Auto-close issue workflow closes the issue when status becomes Done.
|
|
77
|
+
- When a plan issue's source already has a milestone, apply that same milestone. When the source
|
|
78
|
+
already has a project, refetch memberships and apply that project only when exactly one
|
|
79
|
+
accessible open membership exists. Otherwise skip the project and report the conflict.
|
|
80
|
+
- Omit a missing optional milestone. A missing required milestone blocks the issue. Omit a
|
|
81
|
+
declined optional label. A missing required label blocks the issue.
|
|
82
|
+
- For a missing label, use
|
|
83
|
+
[review-github-issue-taxonomy](../review-github-issue-taxonomy/SKILL.md) and get explicit
|
|
84
|
+
approval of the exact repository, name, description, and color before creating it.
|
|
85
|
+
5. Refetch the created or updated issue and verify metadata, including project membership. After a
|
|
86
|
+
project add, re-read the project: automation can pull in more items, including into a second
|
|
87
|
+
project. Report a partial failure without retrying creation. Preserve history and report the
|
|
88
|
+
action, URL, labels, milestone, and project.
|
|
89
|
+
6. Link a pull request with a closing reference only when it fully resolves the issue. Fully
|
|
90
|
+
qualify cross-repository references. Pull-request creation authority stays separate.
|
|
91
|
+
7. Use native sub-issues only for a real hierarchy, blocked-by only for a known dependency, and
|
|
92
|
+
prose links for related work. Read every created relationship back.
|
|
89
93
|
|
|
90
|
-
For batch
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
For a batch, preflight every entry before writing any issue. One invalid entry fails the whole
|
|
95
|
+
batch. A partial transport failure stops further creation and reports every issue already created.
|
|
96
|
+
Do not retry an entry that succeeded.
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
Consumer wrapper owns: repository allowlist, taxonomy, issue template, credential, and CLI wrapper.
|
|
99
|
+
It may tighten this gate and may not weaken it.
|
|
@@ -5,11 +5,13 @@ description: Apply Vitest patterns for Next.js components, routes, and server-si
|
|
|
5
5
|
|
|
6
6
|
# Next.js Vitest test authoring
|
|
7
7
|
|
|
8
|
-
Apply [vitest-test-authoring](../vitest-test-authoring/SKILL.md) first.
|
|
9
|
-
headers, and server-only boundaries at the framework edge, then test component behavior through
|
|
10
|
-
rendered output and user-visible state. Keep API-response fixtures representative and avoid testing
|
|
11
|
-
framework internals. Use browser tests for behavior that cannot be represented in the test runtime.
|
|
8
|
+
Apply [vitest-test-authoring](../vitest-test-authoring/SKILL.md) first.
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
- Mock framework navigation, headers, and server-only boundaries at the framework edge.
|
|
11
|
+
- Test component behavior through rendered output and user-visible state.
|
|
12
|
+
- Keep API-response fixtures representative. Do not test framework internals.
|
|
13
|
+
- Use a browser test for behavior the test runtime cannot represent.
|
|
14
|
+
- Read [framework boundaries](references/framework-boundaries.md) for module shape and server-only
|
|
15
|
+
cases.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Consumer wrapper owns: framework mock helpers, render libraries, and route fixture conventions.
|