gentle-pi 3.7.0 → 4.1.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 +155 -10
- package/assets/agents/gentle-ai-explore.md +13 -6
- package/assets/agents/gentle-ai-verify.md +27 -6
- package/assets/agents/gentle-ai-worker.md +13 -15
- package/assets/install-wizard/index.html +47 -0
- package/assets/install-wizard/wizard.css +1279 -0
- package/assets/install-wizard/wizard.js +951 -0
- package/assets/orchestrator-delegation.md +75 -169
- package/assets/orchestrator-memory.md +12 -26
- package/assets/orchestrator-prompts.md +48 -0
- package/assets/orchestrator-skills.md +1 -1
- package/assets/orchestrator-tracking.md +53 -0
- package/assets/orchestrator-verification.md +28 -0
- package/assets/orchestrator-writer.md +38 -0
- package/assets/orchestrator.md +30 -38
- package/assets/sounds/LICENSE.md +52 -0
- package/assets/sounds/attention.wav +0 -0
- package/assets/sounds/error.wav +0 -0
- package/assets/sounds/success.wav +0 -0
- package/assets/support/strict-tdd-verify.md +4 -266
- package/assets/support/strict-tdd.md +8 -360
- package/bin/engram-guard +9 -0
- package/bin/gentle-shell-install.mjs +302 -0
- package/bin/gentle-shell.mjs +956 -50
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +7 -7
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/manifest.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/orchestration/pi.md +16 -4
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-capabilities.baseline.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-roles.baseline.json +1 -1
- package/docs/bundled-install.md +397 -0
- package/docs/delegated-verification.md +27 -4
- package/docs/gentle-agents-activity.md +537 -0
- package/docs/gentle-shell-uninstall.md +136 -0
- package/docs/gentle-shell.md +165 -51
- package/docs/install-wizard.md +2040 -0
- package/docs/native-authority-architecture.md +3 -3
- package/docs/permission-modes.md +82 -0
- package/docs/prompt-history.md +280 -0
- package/docs/readme-reference.md +364 -231
- package/docs/render-cache-performance.md +28 -0
- package/docs/sound-notifications-proposal.md +191 -0
- package/docs/sound-notifications.md +114 -0
- package/docs/telemetry.md +1 -1
- package/docs/yolo-mode.md +86 -0
- package/extensions/child-context.ts +35 -0
- package/extensions/child-safety.ts +25 -0
- package/extensions/codegraph-tools.ts +18 -5
- package/extensions/gentle-agents.ts +1093 -326
- package/extensions/gentle-ai.ts +1636 -890
- package/extensions/gentle-herdr-activity.ts +81 -0
- package/extensions/gentle-notifications.ts +104 -0
- package/extensions/gentle-shell.ts +1619 -136
- package/extensions/gentle-stats.ts +101 -0
- package/extensions/gentle-todo.ts +126 -20
- package/extensions/history/atomic-write.ts +38 -0
- package/extensions/history/hide-prompts.ts +183 -0
- package/extensions/history/index.ts +1424 -0
- package/extensions/history/load-shared-history.ts +39 -0
- package/extensions/history/selector-helpers.ts +538 -0
- package/extensions/history/session-scan.ts +233 -0
- package/extensions/history/store.ts +1119 -0
- package/extensions/nan-provider.ts +6 -0
- package/extensions/pi-pretty.ts +39 -3
- package/extensions/quiet-tools.ts +254 -92
- package/extensions/resume-hint.ts +60 -0
- package/extensions/skill-registry.ts +191 -58
- package/extensions/startup-banner.ts +71 -33
- package/lib/agent-assets.ts +604 -0
- package/lib/agent-home.ts +10 -1
- package/lib/agent-model-resolution.ts +80 -0
- package/lib/agent-profile-pin.ts +12 -0
- package/lib/agent-profiles.ts +13 -3
- package/lib/agents-completion-delivery.ts +11 -3
- package/lib/agents-message-delivery.ts +181 -0
- package/lib/agents-messaging.ts +1 -1
- package/lib/agents-protocol.ts +99 -0
- package/lib/agents-runner.ts +180 -107
- package/lib/agents-view.ts +26 -3
- package/lib/agents-widget.ts +16 -9
- package/lib/append-system-prompt.ts +21 -0
- package/lib/auto-permission-classifier.ts +280 -0
- package/lib/auto-permission-runtime.ts +268 -0
- package/lib/background-jobs-tools.ts +202 -0
- package/lib/background-jobs.ts +253 -0
- package/lib/background-monitor.ts +154 -0
- package/lib/bounded-writer-admission.ts +220 -0
- package/lib/builtin-codemode-optout.ts +166 -0
- package/lib/card-content-policy.ts +85 -0
- package/lib/card-style-policy.ts +60 -0
- package/lib/child-context-files.ts +166 -0
- package/lib/child-package-injection.ts +62 -0
- package/lib/codemode-renderer.ts +195 -0
- package/lib/command-palette-catalog.ts +5 -10
- package/lib/command-palette.ts +25 -14
- package/lib/context-threshold.ts +26 -0
- package/lib/destructive-command-guard.ts +144 -0
- package/lib/gentle-ai-binary.ts +109 -4
- package/lib/gentle-ai-elapsed-store.ts +87 -0
- package/lib/gentle-ai-renderer.ts +196 -39
- package/lib/gentle-shell-bundled.ts +517 -0
- package/lib/gentle-shell-launcher.ts +89 -27
- package/lib/gentle-shell-resume-hint.ts +176 -0
- package/lib/gentle-shell-startup-flow.ts +54 -0
- package/lib/gentle-shell-startup-update.ts +92 -0
- package/lib/gentle-shell-uninstall.ts +840 -0
- package/lib/gentle-shell-update-panel.ts +231 -0
- package/lib/herdr-activity.ts +183 -0
- package/lib/history-capture-policy.ts +95 -0
- package/lib/inprocess-reviewer.ts +3 -0
- package/lib/jobs-sidebar-state.ts +20 -0
- package/lib/jobs-view.ts +161 -0
- package/lib/model-price-ratio.ts +83 -0
- package/lib/model-routing-authority.ts +5 -1
- package/lib/nan-provider.ts +249 -0
- package/lib/native-review-cli.ts +242 -180
- package/lib/notification-audio-native.ts +162 -0
- package/lib/notification-audio-windows.ts +399 -0
- package/lib/notification-audio.ts +332 -0
- package/lib/notification-customize.ts +241 -0
- package/lib/notification-events.ts +113 -0
- package/lib/notification-policy.ts +148 -0
- package/lib/notification-pulse-client.ts +367 -0
- package/lib/notification-pulse-protocol.ts +305 -0
- package/lib/notification-pulse-stream.ts +213 -0
- package/lib/notification-pulse-worker.ts +66 -0
- package/lib/notification-scheduler.ts +173 -0
- package/lib/notification-service.ts +202 -0
- package/lib/notification-ui.ts +87 -0
- package/lib/odd-phase-inference.ts +231 -0
- package/lib/odd-phase.ts +141 -0
- package/lib/orchestrator-alias.ts +20 -0
- package/lib/orchestrator-catalog.ts +79 -0
- package/lib/orchestrator-consultation.ts +61 -0
- package/lib/orchestrator-discovery.ts +49 -0
- package/lib/orchestrator-helper-consent.ts +122 -0
- package/lib/orchestrator-helper.ts +167 -0
- package/lib/orchestrator-message-card.ts +105 -0
- package/lib/orchestrator-presence.ts +115 -14
- package/lib/orchestrator-scope.ts +80 -0
- package/lib/orchestrator-state.ts +107 -0
- package/lib/orchestrator-tool-card.ts +280 -0
- package/lib/orchestrator-work-search.ts +218 -0
- package/lib/orchestrator-work.ts +79 -0
- package/lib/overlay-repaint.ts +26 -0
- package/lib/permission-mode-policy.ts +59 -0
- package/lib/pi-tui-keys.ts +53 -0
- package/lib/review-candidate-view-owner.ts +73 -21
- package/lib/review-candidate-view.ts +115 -27
- package/lib/review-compact-contract.ts +2 -2
- package/lib/review-host-relay.ts +7 -2
- package/lib/review-integration-v2.ts +100 -22
- package/lib/review-publication-gate.ts +1 -1
- package/lib/review-reminder-receipt.ts +48 -8
- package/lib/review-risk-assessment.ts +227 -56
- package/lib/review-sidebar-state.ts +224 -0
- package/lib/review-transaction.ts +72 -3
- package/lib/runtime-metrics-children.ts +1 -1
- package/lib/runtime-metrics-native.ts +3 -2
- package/lib/selection-engine.ts +527 -0
- package/lib/session-change-capture.ts +5 -4
- package/lib/session-changes.ts +27 -22
- package/lib/session-messaging-grants.ts +135 -0
- package/lib/session-profile-binding.ts +83 -0
- package/lib/session-profile-freeze.ts +266 -0
- package/lib/session-worktree-registry.ts +87 -9
- package/lib/shell-bar.ts +215 -30
- package/lib/shell-card.ts +287 -18
- package/lib/shell-changes-view.ts +42 -14
- package/lib/shell-changes.ts +86 -71
- package/lib/shell-prompt.ts +102 -6
- package/lib/shell-sidebar-layout.ts +83 -15
- package/lib/shell-sidebar.ts +15 -1
- package/lib/shell-todo.ts +84 -31
- package/lib/shell-usage-view.ts +9 -4
- package/lib/shell-usage.ts +70 -13
- package/lib/stats-collector.ts +381 -0
- package/lib/stats-view.ts +431 -0
- package/lib/status-timing-diagnostics.ts +201 -0
- package/lib/telemetry-trigger.ts +3 -1
- package/lib/theme-customization.ts +52 -0
- package/lib/vim-editor-adapter.ts +383 -0
- package/lib/vim-normal-engine.ts +154 -0
- package/lib/vim-operator-engine.ts +416 -0
- package/lib/vim-policy.ts +49 -0
- package/lib/vim-visual-engine.ts +107 -0
- package/lib/visual-customization-policy.ts +119 -0
- package/lib/visual-customize-view.ts +481 -0
- package/lib/visual-profiles.ts +228 -0
- package/lib/writer-surfaces.ts +162 -0
- package/lib/yolo-session-policy.ts +317 -0
- package/package.json +20 -8
- package/runtime/child-package-injection.mjs +63 -0
- package/runtime/gentle-ai-binary.mjs +109 -4
- package/runtime/gentle-shell-bundled.mjs +518 -0
- package/runtime/gentle-shell-launcher.mjs +87 -25
- package/runtime/gentle-shell-resume-hint.mjs +177 -0
- package/runtime/gentle-shell-startup-flow.mjs +55 -0
- package/runtime/gentle-shell-startup-update.mjs +93 -0
- package/runtime/gentle-shell-uninstall.mjs +841 -0
- package/runtime/gentle-shell-update-panel.mjs +232 -0
- package/runtime/native-review-cli.mjs +239 -177
- package/runtime/review-integration-v2.mjs +100 -22
- package/runtime/review-risk-assessment.mjs +225 -54
- package/runtime/status-timing-diagnostics.mjs +202 -0
- package/runtime/telemetry-trigger.mjs +3 -1
- package/scripts/bootstrap.cmd +255 -0
- package/scripts/bootstrap.sh +168 -0
- package/scripts/build-distribution.mjs +157 -0
- package/scripts/build-installer-bundles.mjs +136 -0
- package/scripts/build-runtime-modules.mjs +8 -0
- package/scripts/bundled-install.mjs +1308 -0
- package/scripts/bundled-wizard.mjs +399 -0
- package/scripts/check-types.mjs +4 -6
- package/scripts/gentle-ai-installer.mjs +83 -35
- package/scripts/install-gentle-ai.mjs +48 -1
- package/scripts/install-tui-mode-setting.mjs +10 -1
- package/scripts/install-wizard-preview.mjs +154 -0
- package/scripts/installer-downloads.mjs +648 -0
- package/scripts/installer-preflight.mjs +387 -0
- package/scripts/installer-probes.mjs +564 -0
- package/scripts/installer-runner.mjs +1102 -0
- package/scripts/installer-server.mjs +881 -0
- package/scripts/installer-windows-artifacts.json +15 -0
- package/scripts/installer-windows.mjs +752 -0
- package/scripts/main-channel.mjs +452 -0
- package/scripts/mirror-odd-routing.mjs +2 -2
- package/scripts/npm-pack-result.mjs +31 -0
- package/scripts/render-cache-performance-worker.mjs +205 -0
- package/scripts/render-cache-performance.mjs +115 -0
- package/scripts/run-test-suite.mjs +90 -0
- package/scripts/test-installer-acceptance.sh +161 -0
- package/scripts/test-packed-runner.mjs +54 -19
- package/scripts/types-baseline.json +2 -92
- package/scripts/verify-package-files.mjs +91 -38
- package/skills/branch-pr/SKILL.md +24 -52
- package/skills/chained-pr/SKILL.md +31 -15
- package/skills/chained-pr/references/chaining-details.md +31 -20
- package/skills/gentle-ai/SKILL.md +16 -21
- package/skills/issue-creation/SKILL.md +8 -2
- package/skills/issue-creation/references/delegated-workflow-actions.md +19 -0
- package/skills/work-unit-commits/SKILL.md +4 -3
- package/tests/agent-home.test.ts +56 -3
- package/tests/agent-model-resolution.test.ts +113 -0
- package/tests/agent-profiles.test.ts +30 -0
- package/tests/agent-risk-escalation.test.ts +123 -0
- package/tests/agents-completion-delivery.test.ts +17 -0
- package/tests/agents-fake-child.ts +2 -2
- package/tests/agents-message-delivery.test.ts +106 -0
- package/tests/agents-protocol.test.ts +97 -0
- package/tests/agents-queries.test.ts +9 -9
- package/tests/agents-runner-process.test.ts +31 -0
- package/tests/agents-runner.test.ts +467 -93
- package/tests/agents-view-thread-identity.test.ts +169 -0
- package/tests/agents-view.test.ts +8 -2
- package/tests/agents-widget.test.ts +154 -15
- package/tests/append-system-prompt-route.test.ts +160 -0
- package/tests/append-system-prompt.test.ts +46 -0
- package/tests/artifact-language.test.ts +19 -213
- package/tests/ask-user-question.test.ts +44 -1
- package/tests/asset-installation-runtime.test.ts +5 -16
- package/tests/auto-mode-invariants.test.ts +258 -0
- package/tests/auto-mode-sdk.test.ts +57 -0
- package/tests/auto-mode.test.ts +49 -0
- package/tests/auto-permission-classifier.test.ts +283 -0
- package/tests/auto-permission-runtime.test.ts +196 -0
- package/tests/autonomous-guard.test.ts +69 -1
- package/tests/background-cache-warming.test.ts +2 -1
- package/tests/background-jobs.test.ts +227 -0
- package/tests/background-monitor.test.ts +195 -0
- package/tests/background-subagents-default-mode.test.ts +28 -5
- package/tests/bounded-stop-contract.test.ts +85 -0
- package/tests/bounded-writer-admission.test.ts +146 -0
- package/tests/branch-pr-skill.test.ts +43 -0
- package/tests/bridge-wake-lifecycle.test.ts +129 -0
- package/tests/bridge-wake-rendering.test.ts +56 -0
- package/tests/build-distribution.test.ts +269 -0
- package/tests/builtin-codemode-optout.test.ts +242 -0
- package/tests/bundled-install.test.ts +1319 -0
- package/tests/bundled-wizard.test.ts +505 -0
- package/tests/card-content-policy.test.ts +68 -0
- package/tests/card-style-policy.test.ts +87 -0
- package/tests/chained-pr-skill.test.ts +124 -0
- package/tests/child-codegraph-bootstrap.test.ts +74 -0
- package/tests/child-context-files.test.ts +255 -0
- package/tests/child-package-entrypoints.test.ts +65 -0
- package/tests/child-package-injection.test.ts +74 -0
- package/tests/child-safety.test.ts +94 -0
- package/tests/child-web-package.test.ts +224 -0
- package/tests/codegraph-tools.test.ts +35 -0
- package/tests/codemode-rendering.test.ts +596 -0
- package/tests/command-palette.test.ts +43 -7
- package/tests/context-threshold.test.ts +31 -0
- package/tests/delegate-for-reason-contract.test.ts +327 -0
- package/tests/delegated-key-learnings-contract.test.ts +3 -78
- package/tests/destructive-command-guard.test.ts +84 -0
- package/tests/devbinary/native-review-parity.devtest.ts +171 -3
- package/tests/devbinary/non-git-subagent-bootstrap.devtest.ts +193 -0
- package/tests/devbinary/pi-host-relay.devtest.ts +173 -3
- package/tests/engram-safety.test.ts +288 -0
- package/tests/fixtures/stats/sessions/--work-alpha--/2026-09-28T10-00-00-000Z_aaa.jsonl +7 -0
- package/tests/fixtures/stats/sessions/--work-alpha--/2026-09-29T23-00-00-000Z_bbb.jsonl +3 -0
- package/tests/fixtures/stats/sessions/--work-alpha--/2026-09-30T08-00-00-000Z_ddd.jsonl +2 -0
- package/tests/fixtures/stats/sessions/--work-alpha--/2026-09-30T09-00-00-000Z_eee.jsonl +3 -0
- package/tests/fixtures/stats/sessions/--work-alpha--/run-1/session.jsonl +2 -0
- package/tests/fixtures/stats/sessions/--work-beta--/2026-09-01T12-00-00-000Z_ccc.jsonl +2 -0
- package/tests/fixtures/stats/user-pi/sessions/--work-alpha--/2026-09-28T10-00-00-000Z_aaa.jsonl +2 -0
- package/tests/fixtures/stats/user-pi/sessions/--work-alpha--/2026-09-29T23-00-00-000Z_bbb.jsonl +4 -0
- package/tests/fixtures/stats/user-pi/sessions/--work-gamma--/2026-09-20T09-00-00-000Z_fff.jsonl +3 -0
- package/tests/generic-agent-tools.test.ts +69 -0
- package/tests/gentle-agents.test.ts +2804 -346
- package/tests/gentle-ai-binary-isolation.test.ts +135 -0
- package/tests/gentle-ai-binary.test.ts +21 -4
- package/tests/gentle-ai-child-guards.test.ts +202 -0
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +125 -15
- package/tests/gentle-ai-elapsed-store.test.ts +68 -0
- package/tests/gentle-ai-installer.test.ts +566 -62
- package/tests/gentle-ai-prompt-model-routing.test.ts +123 -0
- package/tests/gentle-ai-renderer.test.ts +493 -14
- package/tests/gentle-ai.test.ts +1427 -236
- package/tests/gentle-card-text.ts +2 -1
- package/tests/gentle-herdr-activity.test.ts +100 -0
- package/tests/gentle-notifications.test.ts +427 -0
- package/tests/gentle-shell-bin.test.ts +896 -115
- package/tests/gentle-shell-bundled.test.ts +1002 -0
- package/tests/gentle-shell-launcher.test.ts +333 -65
- package/tests/gentle-shell-resume-hint.test.ts +270 -0
- package/tests/gentle-shell-startup-flow.test.ts +75 -0
- package/tests/gentle-shell-startup-update.test.ts +85 -0
- package/tests/gentle-shell-uninstall.test.ts +978 -0
- package/tests/gentle-shell-update-panel.test.ts +158 -0
- package/tests/gentle-shell.test.ts +4216 -119
- package/tests/gentle-stats.test.ts +152 -0
- package/tests/gentle-theme.test.ts +4 -1
- package/tests/gentle-todo.test.ts +333 -10
- package/tests/herdr-activity.test.ts +243 -0
- package/tests/history-agent-home.test.ts +81 -0
- package/tests/history-atomic-write.test.ts +57 -0
- package/tests/history-capture-policy.test.ts +102 -0
- package/tests/history-child-guard.test.ts +70 -0
- package/tests/history-command-registration.test.ts +164 -0
- package/tests/history-dedupe-entries.test.ts +123 -0
- package/tests/history-delete-backfill.test.ts +190 -0
- package/tests/history-delete-confirm.test.ts +460 -0
- package/tests/history-dispatch.test.ts +180 -0
- package/tests/history-drain-hidden.test.ts +110 -0
- package/tests/history-drain-order.test.ts +98 -0
- package/tests/history-expanded-globals.test.ts +62 -0
- package/tests/history-gc.test.ts +832 -0
- package/tests/history-header-layout.test.ts +265 -0
- package/tests/history-hide-prompts.test.ts +275 -0
- package/tests/history-lazy-windowing.test.ts +508 -0
- package/tests/history-legacy-migrate-v2.test.ts +297 -0
- package/tests/history-load-shared-history.test.ts +53 -0
- package/tests/history-max-results-cap.test.ts +76 -0
- package/tests/history-multi-reader.test.ts +203 -0
- package/tests/history-off-path.test.ts +170 -0
- package/tests/history-openflow-integration.test.ts +173 -0
- package/tests/history-overlay-margin.test.ts +326 -0
- package/tests/history-preview-layout.test.ts +93 -0
- package/tests/history-registry.test.ts +143 -0
- package/tests/history-scope-delete.test.ts +411 -0
- package/tests/history-search-caret-keys.test.ts +142 -0
- package/tests/history-seed-bootstrap.test.ts +170 -0
- package/tests/history-seed-regen.test.ts +129 -0
- package/tests/history-selector-windowing.test.ts +94 -0
- package/tests/history-session-scan-directory.test.ts +87 -0
- package/tests/history-session-scan-extract.test.ts +583 -0
- package/tests/history-session-writer.test.ts +351 -0
- package/tests/history-store-paths.test.ts +79 -0
- package/tests/history-tombstone-exact.test.ts +139 -0
- package/tests/history-wheel-mouse.test.ts +242 -0
- package/tests/inprocess-reviewer.test.ts +49 -19
- package/tests/install-gentle-ai-failure.test.ts +69 -0
- package/tests/install-tui-mode-setting.test.ts +15 -0
- package/tests/install-wizard.test.ts +1223 -0
- package/tests/installer-bundles.test.ts +122 -0
- package/tests/installer-posix-bootstrap.test.ts +1201 -0
- package/tests/installer-preflight.test.ts +750 -0
- package/tests/installer-probes.test.ts +1106 -0
- package/tests/installer-runner.test.ts +2158 -0
- package/tests/installer-server.test.ts +1567 -0
- package/tests/installer-windows-bootstrap.test.ts +2410 -0
- package/tests/issue-creation-skill.test.ts +61 -0
- package/tests/jobs-view.test.ts +160 -0
- package/tests/main-channel-upgrade.test.ts +389 -0
- package/tests/main-channel.test.ts +344 -0
- package/tests/maintainer/provider-relay.maintest.ts +13 -12
- package/tests/model-price-ratio.test.ts +116 -0
- package/tests/model-profiles-preservation.test.ts +153 -0
- package/tests/model-routing-authority.test.ts +16 -0
- package/tests/model-routing-package.test.ts +10 -0
- package/tests/nan-provider-runtime.test.ts +156 -0
- package/tests/nan-provider.test.ts +481 -0
- package/tests/native-binary-gate.test.ts +2 -0
- package/tests/native-review-capability-contract.test.ts +13 -1
- package/tests/native-review-cli.test.ts +239 -118
- package/tests/native-review-consent.test.ts +2 -2
- package/tests/native-review-parity-runtime.test.ts +101 -4
- package/tests/native-review-parity.test.ts +12 -48
- package/tests/native-risk-evidence-parity.test.ts +21 -0
- package/tests/no-self-pause-contract.test.ts +87 -0
- package/tests/notification-audio-native.test.ts +281 -0
- package/tests/notification-audio-windows.test.ts +581 -0
- package/tests/notification-audio.test.ts +548 -0
- package/tests/notification-customize.test.ts +655 -0
- package/tests/notification-events.test.ts +115 -0
- package/tests/notification-policy.test.ts +201 -0
- package/tests/notification-pulse-client.test.ts +356 -0
- package/tests/notification-pulse-protocol.test.ts +213 -0
- package/tests/notification-pulse-stream.test.ts +320 -0
- package/tests/notification-scheduler.test.ts +258 -0
- package/tests/notification-ui.test.ts +157 -0
- package/tests/npm-pack-result.test.ts +41 -0
- package/tests/odd-integration.test.ts +76 -0
- package/tests/odd-phase-inference.test.ts +213 -0
- package/tests/odd-phase-loader.test.ts +253 -0
- package/tests/odd-phase.test.ts +307 -0
- package/tests/odd-routing-canonical-ratchet.test.ts +60 -14
- package/tests/odd-routing-contract.test.ts +158 -50
- package/tests/orchestrator-budget.test.ts +43 -45
- package/tests/orchestrator-catalog.test.ts +146 -0
- package/tests/orchestrator-consultation-sdk.test.ts +614 -0
- package/tests/orchestrator-consultation.test.ts +111 -0
- package/tests/orchestrator-discovery.test.ts +241 -0
- package/tests/orchestrator-helper-consent.test.ts +171 -0
- package/tests/orchestrator-helper.test.ts +297 -0
- package/tests/orchestrator-message-card.test.ts +190 -0
- package/tests/orchestrator-presence.test.ts +23 -0
- package/tests/orchestrator-rdd-ownership.test.ts +8 -7
- package/tests/orchestrator-scope.test.ts +107 -0
- package/tests/orchestrator-state.test.ts +114 -0
- package/tests/orchestrator-status-publication-contract.test.ts +34 -0
- package/tests/orchestrator-tool-card.test.ts +398 -0
- package/tests/orchestrator-work-search.test.ts +318 -0
- package/tests/orchestrator-work.test.ts +147 -0
- package/tests/overlay-repaint.test.ts +74 -0
- package/tests/package-manifest.test.ts +344 -123
- package/tests/packed-runner-owned-path.test.ts +80 -0
- package/tests/parallel-reason-contract.test.ts +21 -0
- package/tests/parallel-writer-admission.test.ts +210 -0
- package/tests/permission-mode-policy.test.ts +194 -0
- package/tests/persona-single-channel.test.ts +10 -18
- package/tests/pi-pretty.test.ts +56 -0
- package/tests/provider-defect-handoff.test.ts +7 -14
- package/tests/quiet-bash-runtime.test.ts +76 -0
- package/tests/quiet-tool-rendering.test.ts +569 -187
- package/tests/rdd-aware-verification-contract.test.ts +103 -40
- package/tests/rdd-status-line.test.ts +9 -4
- package/tests/render-cache-performance.test.ts +48 -0
- package/tests/resume-hint-extension.test.ts +122 -0
- package/tests/review-agent-end-preflight.test.ts +237 -21
- package/tests/review-candidate-owner-retry.test.ts +22 -1
- package/tests/review-candidate-view.test.ts +399 -12
- package/tests/review-contract-prompt.test.ts +138 -44
- package/tests/review-controller-lock-status.test.ts +0 -1
- package/tests/review-controller-native-recovery.test.ts +327 -17
- package/tests/review-controller-native-routing.test.ts +866 -6
- package/tests/review-controller-workspace-root.test.ts +206 -6
- package/tests/review-controller.test.ts +2 -2
- package/tests/review-correction-lifecycle.test.ts +2 -1
- package/tests/review-gate.test.ts +7 -4
- package/tests/review-graph-schema.test.ts +2 -2
- package/tests/review-host-relay-routing.test.ts +342 -4
- package/tests/review-host-relay.test.ts +49 -2
- package/tests/review-integration-v2-forward.test.ts +221 -1
- package/tests/review-json-arguments.test.ts +167 -0
- package/tests/review-last-event-closure.test.ts +157 -8
- package/tests/review-ledger-contract.test.ts +14 -37
- package/tests/review-policy-judgment-day.test.ts +1 -1
- package/tests/review-policy-ordinary.test.ts +2 -2
- package/tests/review-relay-transport-agent.test.ts +66 -1
- package/tests/review-reminder-receipt.test.ts +47 -1
- package/tests/review-risk-assessment.test.ts +594 -26
- package/tests/review-session-standing-permission-controller.test.ts +16 -17
- package/tests/review-session-standing-permission-ipc.test.ts +6 -5
- package/tests/review-sidebar-state.test.ts +402 -0
- package/tests/review-test-fixtures.ts +7 -1
- package/tests/review-transaction.test.ts +18 -1
- package/tests/run-test-suite.test.ts +202 -0
- package/tests/runtime-harness.mjs +186 -800
- package/tests/runtime-metrics-children.test.ts +16 -23
- package/tests/runtime-metrics-extension.test.ts +1 -1
- package/tests/runtime-metrics-native.test.ts +31 -1
- package/tests/selection-engine.test.ts +451 -0
- package/tests/session-change-capture.test.ts +10 -10
- package/tests/session-changes-shell.test.ts +242 -48
- package/tests/session-changes.test.ts +17 -24
- package/tests/session-messaging-grants.test.ts +255 -0
- package/tests/session-profile-binding.test.ts +163 -0
- package/tests/session-profile-freeze.test.ts +381 -0
- package/tests/session-subject-routing-contract.test.ts +34 -0
- package/tests/session-worktree-registry.test.ts +134 -2
- package/tests/shell-bar.test.ts +422 -1
- package/tests/shell-card.test.ts +353 -1
- package/tests/shell-changes-view.test.ts +135 -32
- package/tests/shell-changes.test.ts +61 -62
- package/tests/shell-prompt.test.ts +94 -2
- package/tests/shell-render-cache-runtime.test.ts +69 -0
- package/tests/shell-render-cache.test.ts +129 -0
- package/tests/shell-sidebar-layout.test.ts +351 -22
- package/tests/shell-sidebar-scroll-benchmark.test.ts +255 -0
- package/tests/shell-todo.test.ts +207 -3
- package/tests/shell-usage-view.test.ts +28 -1
- package/tests/shell-usage.test.ts +108 -0
- package/tests/short-check-routing-contract.test.ts +49 -0
- package/tests/skill-registry-watcher.test.ts +119 -0
- package/tests/skill-registry.test.ts +357 -2
- package/tests/startup-banner.test.ts +246 -4
- package/tests/startup-home-repo.test.ts +170 -0
- package/tests/stats-collector.test.ts +195 -0
- package/tests/stats-view.test.ts +202 -0
- package/tests/status-timing-diagnostics.test.ts +283 -0
- package/tests/support/orchestrator-modules.ts +19 -0
- package/tests/task-size-routing-contract.test.ts +241 -0
- package/tests/telemetry-trigger.test.ts +107 -20
- package/tests/test-strength-contract.test.ts +124 -0
- package/tests/theme-customization.test.ts +72 -0
- package/tests/verify-agent-contract.test.ts +90 -0
- package/tests/verify-first-launch-contract.test.ts +139 -0
- package/tests/verify-package-files.test.ts +56 -0
- package/tests/vim-editor-adapter-host-resolution.test.ts +37 -0
- package/tests/vim-editor-adapter.test.ts +804 -0
- package/tests/vim-normal-engine.test.ts +101 -0
- package/tests/vim-operator-engine.test.ts +215 -0
- package/tests/vim-policy.test.ts +19 -0
- package/tests/vim-visual-engine.test.ts +52 -0
- package/tests/visual-customization-policy.test.ts +139 -0
- package/tests/visual-customize-view.test.ts +696 -0
- package/tests/visual-profiles.test.ts +87 -0
- package/tests/writer-edit-surface-scope.test.ts +59 -2
- package/tests/writer-surfaces.test.ts +199 -0
- package/tests/yolo-customize.test.ts +271 -0
- package/tests/yolo-mode-runtime.test.ts +188 -0
- package/tests/yolo-mode.test.ts +289 -0
- package/tests/yolo-session-policy.test.ts +59 -0
- package/themes/Gentle.json +2 -1
- package/themes/Gentleman-Cute.json +2 -1
- package/themes/Gentleman-Sexy.json +2 -1
- package/assets/agents/sdd-apply.md +0 -159
- package/assets/agents/sdd-archive.md +0 -228
- package/assets/agents/sdd-design.md +0 -49
- package/assets/agents/sdd-explore.md +0 -48
- package/assets/agents/sdd-init.md +0 -56
- package/assets/agents/sdd-onboard.md +0 -52
- package/assets/agents/sdd-proposal.md +0 -64
- package/assets/agents/sdd-remediate.md +0 -37
- package/assets/agents/sdd-research.md +0 -49
- package/assets/agents/sdd-spec.md +0 -192
- package/assets/agents/sdd-status.md +0 -54
- package/assets/agents/sdd-tasks.md +0 -108
- package/assets/agents/sdd-verify.md +0 -124
- package/assets/chains/sdd-full.chain.md +0 -83
- package/assets/chains/sdd-plan.chain.md +0 -56
- package/assets/chains/sdd-verify.chain.md +0 -43
- package/assets/sdd-orchestrator-workflow.md +0 -319
- package/assets/support/sdd-status-contract.md +0 -77
- package/docs/assets/diagrams/sdd-cycle.svg +0 -14
- package/extensions/sdd-init.ts +0 -816
- package/lib/openspec-deltas.ts +0 -156
- package/lib/sdd-preflight.ts +0 -1066
- package/lib/sdd-research-capabilities.ts +0 -94
- package/lib/sdd-status.ts +0 -26
- package/tests/fixtures/legacy/sdd-research-v2.5.0.md +0 -54
- package/tests/fixtures/native-review-cli/v2.1.3/bind-sdd.json +0 -25
- package/tests/fixtures/v0.10.7/assets/agents/sdd-apply.md +0 -132
- package/tests/openspec-deltas.test.ts +0 -209
- package/tests/sdd-agent-tools.test.ts +0 -156
- package/tests/sdd-archive-replay.test.ts +0 -82
- package/tests/sdd-classical-continuation.test.ts +0 -74
- package/tests/sdd-execution-routing-contract.test.ts +0 -44
- package/tests/sdd-managed-runtime-settlement.test.ts +0 -155
- package/tests/sdd-native-managed-uptake.test.ts +0 -243
- package/tests/sdd-no-attempts-contract.test.ts +0 -15
- package/tests/sdd-odd-integration.test.ts +0 -33
- package/tests/sdd-optional-research.test.ts +0 -124
- package/tests/sdd-planning-routing-contract.test.ts +0 -45
- package/tests/sdd-preflight-rpc-input.test.ts +0 -125
- package/tests/sdd-preflight.test.ts +0 -541
- package/tests/sdd-research-capabilities.test.ts +0 -114
- package/tests/sdd-research-live.test.ts +0 -241
- package/tests/sdd-selection-transport.test.ts +0 -653
- package/tests/sdd-status.test.ts +0 -9
- package/tests/sdd-task-truth.test.ts +0 -43
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/README.md +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/targeted-validator.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/targeted-validator.json +0 -0
|
@@ -1,269 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Applicable Test-First Development — ODD Verification
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> If you are reading this, the orchestrator already verified both conditions. Follow every instruction.
|
|
3
|
+
This legacy filename is retained for package compatibility. It does not represent a Strict TDD switch.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Assess applicability for each changed behavior: is there a runnable deterministic test with a clear expected outcome? Test existence alone does not establish applicability. For applicable behavior, inspect the reported observed RED (the intended failure before implementation), observed GREEN (focused passing execution after implementation), relevant alternate cases, and post-refactor checks. Do not infer RED from a test file existing or GREEN from a claim without execution. Report missing or contradictory evidence honestly; do not manufacture a lifecycle from the final diff.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Step 5a: TDD Compliance Check (includes Assertion Quality Audit)
|
|
11
|
-
|
|
12
|
-
Read the `apply-progress` artifact and verify that TDD was actually followed:
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
Read apply-progress artifact:
|
|
16
|
-
├── Find the "TDD Cycle Evidence" table
|
|
17
|
-
├── FOR EACH task row:
|
|
18
|
-
│ ├── RED column:
|
|
19
|
-
│ │ ├── Must say "✅ Written"
|
|
20
|
-
│ │ ├── Verify: test file EXISTS in the codebase
|
|
21
|
-
│ │ └── Flag: CRITICAL if test file does not exist
|
|
22
|
-
│ │
|
|
23
|
-
│ ├── GREEN column:
|
|
24
|
-
│ │ ├── Must say "✅ Passed"
|
|
25
|
-
│ │ ├── Cross-reference with Step 5b test execution results:
|
|
26
|
-
│ │ │ └── The test file listed must PASS when you run it
|
|
27
|
-
│ │ └── Flag: CRITICAL if test fails now (was it really green?)
|
|
28
|
-
│ │
|
|
29
|
-
│ ├── TRIANGULATE column:
|
|
30
|
-
│ │ ├── If "✅ N cases" → verify N test cases exist in the test file
|
|
31
|
-
│ │ ├── If "➖ Single" → verify spec truly has only one scenario for this task
|
|
32
|
-
│ │ └── Flag: WARNING if spec has multiple scenarios but only 1 test case
|
|
33
|
-
│ │
|
|
34
|
-
│ ├── SAFETY NET column:
|
|
35
|
-
│ │ ├── If "✅ N/N" → existing tests were run before modification (good)
|
|
36
|
-
│ │ ├── If "N/A (new)" → verify the file was actually NEW (not modified)
|
|
37
|
-
│ │ └── Flag: WARNING if file was modified but safety net shows "N/A"
|
|
38
|
-
│ │
|
|
39
|
-
│ └── REFACTOR column:
|
|
40
|
-
│ ├── Not strictly verifiable (subjective quality)
|
|
41
|
-
│ └── Skip verification, trust the report
|
|
42
|
-
│
|
|
43
|
-
├── If NO "TDD Cycle Evidence" table found:
|
|
44
|
-
│ └── Flag: CRITICAL — apply phase did not report TDD evidence
|
|
45
|
-
│ (Strict TDD was enabled but apply did not follow the protocol)
|
|
46
|
-
│
|
|
47
|
-
└── Summary: "{N}/{total} tasks have complete TDD evidence"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Step 5 Expanded: Test Layer Validation
|
|
51
|
-
|
|
52
|
-
Classify ALL test files related to this change by their testing layer:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
Scan test files created/modified by this change:
|
|
56
|
-
├── Classify each test file:
|
|
57
|
-
│ ├── Unit test: tests a single function/class in isolation
|
|
58
|
-
│ │ └── Indicators: no render(), no page., no HTTP calls, mocked dependencies
|
|
59
|
-
│ ├── Integration test: tests component interaction or user behavior
|
|
60
|
-
│ │ └── Indicators: render(), screen., userEvent., testing-library imports
|
|
61
|
-
│ ├── E2E test: tests full system through real browser/HTTP
|
|
62
|
-
│ │ └── Indicators: page.goto(), playwright/cypress imports, browser context
|
|
63
|
-
│ └── Unknown: cannot classify → report as-is
|
|
64
|
-
│
|
|
65
|
-
├── Report distribution:
|
|
66
|
-
│ ├── Unit: {N} tests across {N} files
|
|
67
|
-
│ ├── Integration: {N} tests across {N} files
|
|
68
|
-
│ ├── E2E: {N} tests across {N} files
|
|
69
|
-
│ └── Total: {N} tests
|
|
70
|
-
│
|
|
71
|
-
├── Cross-reference with capabilities:
|
|
72
|
-
│ ├── If integration tests exist but tools not in capabilities → how?
|
|
73
|
-
│ ├── If E2E tests exist but tools not in capabilities → how?
|
|
74
|
-
│ └── Flag: WARNING if tests use tools not detected in capabilities
|
|
75
|
-
│
|
|
76
|
-
└── For each spec scenario: note which layer covers it
|
|
77
|
-
└── Flag: SUGGESTION if critical business logic only has unit tests
|
|
78
|
-
(only if integration/E2E tools are available)
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Step 5d Expanded: Changed File Coverage
|
|
82
|
-
|
|
83
|
-
When coverage tool is available, report coverage for CHANGED files specifically:
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
IF coverage tool available (from cached capabilities):
|
|
87
|
-
├── Run: {test_command} --coverage (or equivalent)
|
|
88
|
-
├── Parse the coverage report
|
|
89
|
-
├── Filter to ONLY files created or modified in this change
|
|
90
|
-
│ (get file list from apply-progress "Files Changed" table)
|
|
91
|
-
├── Report per-file:
|
|
92
|
-
│ ├── File path
|
|
93
|
-
│ ├── Line coverage %
|
|
94
|
-
│ ├── Branch coverage % (if available)
|
|
95
|
-
│ ├── Uncovered line ranges (specific lines, not just %)
|
|
96
|
-
│ └── Flag per file:
|
|
97
|
-
│ ├── ≥ 95% → ✅ Excellent
|
|
98
|
-
│ ├── ≥ 80% → ⚠️ Acceptable
|
|
99
|
-
│ └── < 80% → ⚠️ Low (list uncovered lines)
|
|
100
|
-
├── Report aggregate:
|
|
101
|
-
│ ├── Average coverage of changed files
|
|
102
|
-
│ ├── Total uncovered lines in changed files
|
|
103
|
-
│ └── Compare to threshold if configured
|
|
104
|
-
└── Flag: WARNING if any changed file < 80% coverage
|
|
105
|
-
|
|
106
|
-
IF coverage tool NOT available:
|
|
107
|
-
└── Report: "Coverage analysis skipped — no coverage tool detected"
|
|
108
|
-
(NOT a failure — just not available)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Step 5e: Quality Metrics (if tools available)
|
|
112
|
-
|
|
113
|
-
Run quality checks ONLY on changed files, ONLY if tools are available:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
Read quality tools from cached capabilities:
|
|
117
|
-
|
|
118
|
-
IF linter available:
|
|
119
|
-
├── Run linter on changed files only
|
|
120
|
-
├── Report: errors and warnings
|
|
121
|
-
└── Flag: WARNING for errors, SUGGESTION for warnings
|
|
122
|
-
|
|
123
|
-
IF type checker available:
|
|
124
|
-
├── Run type checker (usually whole-project, not per-file)
|
|
125
|
-
├── Filter output to changed files
|
|
126
|
-
├── Report: type errors in changed files
|
|
127
|
-
└── Flag: WARNING for type errors
|
|
128
|
-
|
|
129
|
-
IF neither available:
|
|
130
|
-
└── Report: "Quality metrics skipped — no tools detected"
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Report Template Extension
|
|
134
|
-
|
|
135
|
-
When Strict TDD Mode is active, your verification report MUST include these additional sections:
|
|
136
|
-
|
|
137
|
-
```markdown
|
|
138
|
-
### TDD Compliance
|
|
139
|
-
| Check | Result | Details |
|
|
140
|
-
|-------|--------|---------|
|
|
141
|
-
| TDD Evidence reported | ✅ / ❌ | {Found in apply-progress / Missing} |
|
|
142
|
-
| All tasks have tests | ✅ / ❌ | {N}/{total} tasks have test files |
|
|
143
|
-
| RED confirmed (tests exist) | ✅ / ⚠️ | {N}/{total} test files verified |
|
|
144
|
-
| GREEN confirmed (tests pass) | ✅ / ❌ | {N}/{total} tests pass on execution |
|
|
145
|
-
| Triangulation adequate | ✅ / ⚠️ / ➖ | {N} tasks triangulated / {N} single-case |
|
|
146
|
-
| Safety Net for modified files | ✅ / ⚠️ | {N}/{total} modified files had safety net |
|
|
147
|
-
|
|
148
|
-
**TDD Compliance**: {N}/{total} checks passed
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
### Test Layer Distribution
|
|
153
|
-
| Layer | Tests | Files | Tools |
|
|
154
|
-
|-------|-------|-------|-------|
|
|
155
|
-
| Unit | {N} | {N} | {tool} |
|
|
156
|
-
| Integration | {N} | {N} | {tool or "not installed"} |
|
|
157
|
-
| E2E | {N} | {N} | {tool or "not installed"} |
|
|
158
|
-
| **Total** | **{N}** | **{N}** | |
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
### Changed File Coverage
|
|
163
|
-
| File | Line % | Branch % | Uncovered Lines | Rating |
|
|
164
|
-
|------|--------|----------|-----------------|--------|
|
|
165
|
-
| `path/to/file.ext` | 95% | 90% | — | ✅ Excellent |
|
|
166
|
-
| `path/to/other.ext` | 82% | 75% | L45-48, L62 | ⚠️ Acceptable |
|
|
167
|
-
| `path/to/new.ext` | 100% | 100% | — | ✅ Excellent |
|
|
168
|
-
|
|
169
|
-
**Average changed file coverage**: {N}%
|
|
170
|
-
{or "Coverage analysis skipped — no coverage tool detected"}
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
### Assertion Quality
|
|
175
|
-
| File | Line | Assertion | Issue | Severity |
|
|
176
|
-
|------|------|-----------|-------|----------|
|
|
177
|
-
| ... | ... | ... | ... | ... |
|
|
178
|
-
|
|
179
|
-
**Assertion quality**: {N} CRITICAL, {N} WARNING
|
|
180
|
-
{or "✅ All assertions verify real behavior"}
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
### Quality Metrics
|
|
185
|
-
**Linter**: ✅ No errors / ⚠️ {N} warnings / ❌ {N} errors / ➖ Not available
|
|
186
|
-
**Type Checker**: ✅ No errors / ❌ {N} errors / ➖ Not available
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Step 5f: Assertion Quality Audit (MANDATORY)
|
|
190
|
-
|
|
191
|
-
Scan ALL test files created or modified by this change and check for trivial/meaningless assertions:
|
|
192
|
-
|
|
193
|
-
```
|
|
194
|
-
FOR EACH test file related to the change:
|
|
195
|
-
├── Read the file content
|
|
196
|
-
├── Scan for BANNED assertion patterns:
|
|
197
|
-
│ ├── Tautologies: expect(true).toBe(true), assert True, expect(1).toBe(1)
|
|
198
|
-
│ ├── Orphan empty checks: expect(result).toEqual([]) or assert len(result) == 0
|
|
199
|
-
│ │ └── UNLESS there is a companion test with same setup that asserts NON-EMPTY
|
|
200
|
-
│ ├── Type-only assertions used alone: toBeDefined(), not.toBeNull(), typeof checks
|
|
201
|
-
│ │ └── These are OK if COMBINED with value assertions in the same test
|
|
202
|
-
│ ├── Assertions that never call production code (no function call, no render, no request)
|
|
203
|
-
│ ├── Ghost loops: assertions inside for/forEach over queryAll/filter results
|
|
204
|
-
│ │ └── Check if the collection could be empty — if so, the assertions NEVER RUN
|
|
205
|
-
│ │ Flag: CRITICAL — a loop over an empty array is a test that ALWAYS passes
|
|
206
|
-
│ ├── Incomplete TDD cycle: test passes because preconditions prevent code from running
|
|
207
|
-
│ │ └── e.g., testing behavior of a component that is never rendered due to state
|
|
208
|
-
│ │ Flag: CRITICAL — test must set up conditions where the code path IS exercised
|
|
209
|
-
│ ├── Smoke-test-only: render() + toBeInTheDocument() without behavioral assertions
|
|
210
|
-
│ │ └── "Renders without crash" is NOT a valid test — it must assert WHAT was rendered
|
|
211
|
-
│ │ Flag: WARNING — smoke tests do not count toward TDD coverage
|
|
212
|
-
│ ├── Implementation detail coupling: assertions on CSS classes, internal state, mock call counts
|
|
213
|
-
│ │ └── expect(el.className).toContain("text-xs") or expect(mock.calls.length).toBe(3)
|
|
214
|
-
│ │ Flag: WARNING — tests must assert behavior, not implementation
|
|
215
|
-
│ └── Mock/assertion ratio: count vi.mock() calls vs expect() calls per test file
|
|
216
|
-
│ └── If mocks > 2× assertions → Flag: WARNING — "Mock-heavy test ({N} mocks, {N} assertions)"
|
|
217
|
-
│ Recommend: extract logic to pure function or move to higher test layer
|
|
218
|
-
│
|
|
219
|
-
├── For each violation found:
|
|
220
|
-
│ ├── Record: file, line number, the assertion, why it's trivial
|
|
221
|
-
│ └── Classify:
|
|
222
|
-
│ ├── CRITICAL: tautology (expect(true).toBe(true)) — test proves NOTHING
|
|
223
|
-
│ ├── CRITICAL: assertion without production code call — test exercises nothing
|
|
224
|
-
│ ├── CRITICAL: ghost loop — assertions inside loop over possibly-empty collection
|
|
225
|
-
│ ├── WARNING: empty collection without companion non-empty test
|
|
226
|
-
│ ├── WARNING: type-only assertion without value assertion
|
|
227
|
-
│ ├── WARNING: smoke-test-only — render + toBeInTheDocument without behavioral check
|
|
228
|
-
│ ├── WARNING: CSS class / implementation detail assertion
|
|
229
|
-
│ └── WARNING: mock-heavy test (mocks > 2× assertions) — wrong test layer
|
|
230
|
-
│
|
|
231
|
-
├── Check triangulation quality:
|
|
232
|
-
│ ├── Count distinct test cases per behavior
|
|
233
|
-
│ ├── If only 1 test case exists for a behavior with multiple spec scenarios:
|
|
234
|
-
│ │ └── Flag: WARNING — "Insufficient triangulation for {behavior}"
|
|
235
|
-
│ ├── If all test cases assert the SAME type of value (e.g., all check empty arrays):
|
|
236
|
-
│ │ └── Flag: WARNING — "No variance in test expectations — all assert empty/trivial"
|
|
237
|
-
│ └── A well-triangulated behavior has tests asserting DIFFERENT expected values
|
|
238
|
-
│
|
|
239
|
-
└── Summary: "{N} trivial assertions found across {N} files"
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Assertion Quality Report Table
|
|
243
|
-
|
|
244
|
-
Include this table in the verification report when any issues are found:
|
|
245
|
-
|
|
246
|
-
```markdown
|
|
247
|
-
### Assertion Quality
|
|
248
|
-
| File | Line | Assertion | Issue | Severity |
|
|
249
|
-
|------|------|-----------|-------|----------|
|
|
250
|
-
| `path/test.ts` | 15 | `expect(true).toBe(true)` | Tautology — proves nothing | CRITICAL |
|
|
251
|
-
| `path/test.ts` | 23 | `expect(result).toEqual([])` | Empty without companion non-empty test | WARNING |
|
|
252
|
-
| `path/test.ts` | 31 | `expect(result).toBeDefined()` | Type-only — no value asserted | WARNING |
|
|
253
|
-
|
|
254
|
-
**Assertion quality**: {N} CRITICAL, {N} WARNING
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
If zero issues found, report: "**Assertion quality**: ✅ All assertions verify real behavior"
|
|
258
|
-
|
|
259
|
-
## Rules (Strict TDD Verify specific)
|
|
260
|
-
|
|
261
|
-
- ALWAYS check the TDD Cycle Evidence table from apply-progress — it's the primary artifact
|
|
262
|
-
- ALWAYS cross-reference reported test files against actual execution — don't trust the report blindly
|
|
263
|
-
- ALWAYS run the Assertion Quality Audit (Step 5f) — trivial tests are WORSE than missing tests
|
|
264
|
-
- If apply-progress has no TDD evidence table, flag as CRITICAL — the protocol was not followed
|
|
265
|
-
- If tautology assertions are found (expect(true).toBe(true)), flag as CRITICAL — these MUST be rewritten
|
|
266
|
-
- Coverage and quality metrics are informational, NOT blocking — only flag as WARNING, never CRITICAL
|
|
267
|
-
- Test layer distribution is informational — SUGGESTION level only
|
|
268
|
-
- DO NOT fix issues — only report. The orchestrator decides.
|
|
269
|
-
- If coverage/quality tools are not available, say so cleanly and move on — never flag missing tools as failures
|
|
7
|
+
For passive documentation, non-testable changes, an unavailable runner, or no meaningful RED, assess the stated exception and the proportionate ordinary functional or structural verification. Never demand a chat/TUI activation choice, and never skip all checks merely because test-first is inapplicable. Execute only exact commands authorized by the parent; report actual results, limitations and remaining uncertainty without editing code or overriding parent-owned RDD review.
|
|
@@ -1,364 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Applicable Test-First Development — ODD Implementation
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> If you are reading this, the orchestrator already verified both conditions. Follow every instruction.
|
|
3
|
+
This legacy filename is retained for package compatibility. It does not represent a Strict TDD switch.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
For behavior changes with applicable runnable deterministic tests and a clear expected outcome, use test-first by default:
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
1. RED — add the smallest behavior-level test before implementation; run it and capture the intended observed failure. A test file merely existing is not proof of applicability or RED.
|
|
8
|
+
2. GREEN — implement the minimum behavior and run the focused test to observe it passing.
|
|
9
|
+
3. TRIANGULATE — exercise relevant alternate or negative cases that protect the contract; do not require arbitrary case counts.
|
|
10
|
+
4. REFACTOR — improve clarity without changing behavior and rerun focused checks.
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
1. **Do NOT write production code** until you have a failing test
|
|
13
|
-
2. **Do NOT write more test** than is necessary to fail
|
|
14
|
-
3. **Do NOT write more code** than is necessary to pass the test
|
|
15
|
-
|
|
16
|
-
## TDD Implementation Cycle
|
|
17
|
-
|
|
18
|
-
For EVERY task assigned to you, follow this cycle strictly:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
FOR EACH TASK:
|
|
22
|
-
├── 0. SAFETY NET (only if modifying existing files)
|
|
23
|
-
│ ├── Run existing tests for files being modified
|
|
24
|
-
│ ├── Capture baseline: "{N} tests passing"
|
|
25
|
-
│ ├── If any FAIL → STOP, report as "pre-existing failure"
|
|
26
|
-
│ │ (do NOT fix pre-existing failures — report to orchestrator)
|
|
27
|
-
│ └── This baseline proves you did not break what already worked
|
|
28
|
-
│
|
|
29
|
-
├── 1. UNDERSTAND
|
|
30
|
-
│ ├── Read the task description
|
|
31
|
-
│ ├── Read relevant spec scenarios (these ARE your acceptance criteria)
|
|
32
|
-
│ ├── Read the design decisions (these CONSTRAIN your approach)
|
|
33
|
-
│ ├── Read existing code and test patterns (match the style)
|
|
34
|
-
│ └── Determine test layer (see "Choosing Test Layer" below)
|
|
35
|
-
│
|
|
36
|
-
├── 2. RED — Write a failing test FIRST
|
|
37
|
-
│ ├── Write test(s) that describe the expected behavior from the spec
|
|
38
|
-
│ ├── Prefer pure functions where possible (no side effects = easy to test)
|
|
39
|
-
│ ├── The test MUST reference production code that does NOT exist yet
|
|
40
|
-
│ │ (this guarantees failure — no need to execute to confirm)
|
|
41
|
-
│ ├── If the production code/function already exists:
|
|
42
|
-
│ │ └── Write a test for the NEW behavior that is NOT yet implemented
|
|
43
|
-
│ └── GATE: Do NOT proceed to GREEN until the test is written
|
|
44
|
-
│
|
|
45
|
-
├── 3. GREEN — Write the MINIMUM code to pass
|
|
46
|
-
│ ├── Implement ONLY what the failing test needs
|
|
47
|
-
│ ├── Fake It is VALID here (hardcoded return values are OK)
|
|
48
|
-
│ ├── EXECUTE tests → must PASS
|
|
49
|
-
│ │ ├── ✅ Passed → proceed to TRIANGULATE or REFACTOR
|
|
50
|
-
│ │ └── ❌ Failed → fix the implementation, NOT the test
|
|
51
|
-
│ └── GATE: Do NOT proceed until GREEN is confirmed by execution
|
|
52
|
-
│
|
|
53
|
-
├── 4. TRIANGULATE (MANDATORY for most tasks)
|
|
54
|
-
│ ├── DEFAULT: triangulation is REQUIRED. You need a compelling reason to skip it.
|
|
55
|
-
│ ├── Add a second test case with DIFFERENT inputs/expected outputs
|
|
56
|
-
│ ├── EXECUTE tests → if Fake It breaks (hardcoded no longer works):
|
|
57
|
-
│ │ └── Generalize to real logic (this is the whole point)
|
|
58
|
-
│ ├── Repeat until ALL spec scenarios for this task are covered
|
|
59
|
-
│ ├── Each triangulation pass: write test → run → fix implementation
|
|
60
|
-
│ ├── MINIMUM: at least 2 test cases per behavior (happy path + one edge case)
|
|
61
|
-
│ │ ├── One test with data that produces a NON-EMPTY/NON-TRIVIAL result
|
|
62
|
-
│ │ └── One test with data that exercises a DIFFERENT code path
|
|
63
|
-
│ ├── WATCH OUT for GREEN that passes trivially:
|
|
64
|
-
│ │ ├── If your test passes because the component/element isn't rendered → NOT a real GREEN
|
|
65
|
-
│ │ ├── If your test passes because a loop iterates 0 times → NOT a real GREEN
|
|
66
|
-
│ │ ├── If your test passes because the setup doesn't trigger the code path → NOT a real GREEN
|
|
67
|
-
│ │ └── A real GREEN means: production code RAN and produced the expected output
|
|
68
|
-
│ ├── Skip triangulation ONLY when ALL of these are true:
|
|
69
|
-
│ │ ├── The task is purely structural (config file, constant definition, type export)
|
|
70
|
-
│ │ ├── There is literally ONE possible output (no branching, no logic)
|
|
71
|
-
│ │ └── You explicitly note "Triangulation skipped: {reason}" in the evidence table
|
|
72
|
-
│ └── GATE: All spec scenarios for this task must have tests before REFACTOR
|
|
73
|
-
│
|
|
74
|
-
├── 5. REFACTOR — Improve without changing behavior
|
|
75
|
-
│ ├── Extract constants (eliminate magic numbers)
|
|
76
|
-
│ ├── Extract functions (reduce cyclomatic complexity)
|
|
77
|
-
│ ├── Improve naming, remove duplication
|
|
78
|
-
│ ├── Push toward pure functions where feasible
|
|
79
|
-
│ ├── Apply Boy Scout Rule: leave code cleaner than you found it
|
|
80
|
-
│ ├── EXECUTE tests after EACH refactoring step → must STILL PASS
|
|
81
|
-
│ │ ├── ✅ Still passing → refactoring is safe, continue
|
|
82
|
-
│ │ └── ❌ Failed → REVERT that refactoring step, try smaller
|
|
83
|
-
│ └── GATE: Tests green after EVERY refactoring change
|
|
84
|
-
│
|
|
85
|
-
├── 6. Mark task complete [x]
|
|
86
|
-
└── 7. Note any deviations or issues discovered
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Choosing Test Layer
|
|
90
|
-
|
|
91
|
-
Based on the testing capabilities cached in Engram (`sdd/{project}/testing-capabilities`), choose the appropriate test layer for each task:
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
Determine test layer by WHAT the task does:
|
|
95
|
-
├── Pure logic, utility function, calculation, data transformation
|
|
96
|
-
│ └── Unit test (always available if test runner exists)
|
|
97
|
-
│
|
|
98
|
-
├── Component rendering, user interaction, state changes
|
|
99
|
-
│ ├── IF integration tools available → Integration test
|
|
100
|
-
│ └── IF NOT → Unit test with mocks (degrade gracefully)
|
|
101
|
-
│
|
|
102
|
-
├── Multi-component flow, API interaction, context/provider behavior
|
|
103
|
-
│ ├── IF integration tools available → Integration test
|
|
104
|
-
│ └── IF NOT → Unit test with mocks
|
|
105
|
-
│
|
|
106
|
-
├── Critical business flow, full user journey, cross-page navigation
|
|
107
|
-
│ ├── IF E2E tools available → E2E test
|
|
108
|
-
│ ├── IF NOT but integration available → Integration test
|
|
109
|
-
│ └── IF neither → Unit test (degrade gracefully)
|
|
110
|
-
│
|
|
111
|
-
└── Default: Unit test (always the fallback)
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Key rule**: Use the HIGHEST available layer that fits the task. But NEVER skip a task because a layer is unavailable — degrade to the next available layer.
|
|
115
|
-
|
|
116
|
-
## Test Execution
|
|
117
|
-
|
|
118
|
-
Detect the test runner from the cached testing capabilities:
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
Read test command from:
|
|
122
|
-
├── Cached capabilities → test_runner.command (fastest — already detected)
|
|
123
|
-
├── openspec/config.yaml → rules.apply.test_command (override)
|
|
124
|
-
└── Fallback: detect from package.json/pyproject.toml/go.mod
|
|
125
|
-
|
|
126
|
-
When executing tests during TDD:
|
|
127
|
-
├── Run ONLY the relevant test file, not the entire suite
|
|
128
|
-
│ ├── JS/TS: {runner} {test-file-path} (e.g., pnpm vitest run src/utils/tax.test.ts)
|
|
129
|
-
│ ├── Python: pytest {test-file-path}
|
|
130
|
-
│ ├── Go: go test ./{package}/... -run {TestName}
|
|
131
|
-
│ └── Adapt to the runner's CLI
|
|
132
|
-
├── This keeps the cycle FAST
|
|
133
|
-
└── Full suite runs happen in sdd-verify, not here
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Pure Function Preference
|
|
137
|
-
|
|
138
|
-
When writing production code in GREEN/TRIANGULATE steps, prefer pure functions:
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
✅ PREFER (pure — easy to test):
|
|
142
|
-
function calculateDiscount(price: number, quantity: number): number {
|
|
143
|
-
return quantity >= 5 ? price * quantity * 0.1 : 0
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
❌ AVOID (impure — hard to test):
|
|
147
|
-
function calculateDiscount(item: Item) {
|
|
148
|
-
globalState.lastDiscount = item.price * 0.1 // side effect
|
|
149
|
-
updateDOM() // side effect
|
|
150
|
-
return globalState.lastDiscount
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**Why**: Pure functions are deterministic (same input → same output), have no side effects, and are trivially testable. TDD naturally pushes you toward pure functions — embrace it.
|
|
155
|
-
|
|
156
|
-
## Approval Testing (for refactoring existing code)
|
|
157
|
-
|
|
158
|
-
When a task involves REFACTORING existing code (not writing new code):
|
|
159
|
-
|
|
160
|
-
```
|
|
161
|
-
BEFORE touching production code:
|
|
162
|
-
├── 1. Identify existing behavior to preserve
|
|
163
|
-
├── 2. Write "approval tests" that capture current behavior:
|
|
164
|
-
│ ├── Call the function with known inputs
|
|
165
|
-
│ ├── Assert the CURRENT outputs (even if ugly or wrong)
|
|
166
|
-
│ └── These tests document what the code does NOW
|
|
167
|
-
├── 3. Run approval tests → must PASS (they describe current reality)
|
|
168
|
-
├── 4. NOW refactor the production code
|
|
169
|
-
├── 5. Run approval tests again → must STILL PASS
|
|
170
|
-
│ ├── ✅ Passing → refactoring preserved behavior
|
|
171
|
-
│ └── ❌ Failing → refactoring broke something, revert
|
|
172
|
-
└── 6. If the spec says behavior should CHANGE:
|
|
173
|
-
├── Update the approval test to reflect NEW expected behavior
|
|
174
|
-
├── Run → test FAILS (RED — new behavior not implemented yet)
|
|
175
|
-
└── Implement new behavior → GREEN
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Return Summary Extension
|
|
179
|
-
|
|
180
|
-
When Strict TDD Mode is active, your return summary MUST include this section:
|
|
181
|
-
|
|
182
|
-
```markdown
|
|
183
|
-
### TDD Cycle Evidence
|
|
184
|
-
| Task | Test File | Layer | Safety Net | RED | GREEN | TRIANGULATE | REFACTOR |
|
|
185
|
-
|------|-----------|-------|------------|-----|-------|-------------|----------|
|
|
186
|
-
| 1.1 | `path/test.ext` | Unit | ✅ 5/5 | ✅ Written | ✅ Passed | ✅ 3 cases | ✅ Clean |
|
|
187
|
-
| 1.2 | `path/test.ext` | Integration | N/A (new) | ✅ Written | ✅ Passed | ➖ Single | ✅ Clean |
|
|
188
|
-
| 1.3 | `path/test.ext` | Unit | ✅ 2/2 | ✅ Written | ✅ Passed | ✅ 2 cases | ➖ None needed |
|
|
189
|
-
|
|
190
|
-
### Test Summary
|
|
191
|
-
- **Total tests written**: {N}
|
|
192
|
-
- **Total tests passing**: {N}
|
|
193
|
-
- **Layers used**: Unit ({N}), Integration ({N}), E2E ({N})
|
|
194
|
-
- **Approval tests** (refactoring): {N} or "None — no refactoring tasks"
|
|
195
|
-
- **Pure functions created**: {N}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
**Column definitions**:
|
|
199
|
-
- **Safety Net**: Pre-existing tests run before modifying files. "N/A (new)" for new files.
|
|
200
|
-
- **RED**: Test written first, referencing code that doesn't exist yet. Always "✅ Written".
|
|
201
|
-
- **GREEN**: Tests executed and passing after minimal implementation. Must show execution result.
|
|
202
|
-
- **TRIANGULATE**: Additional test cases added to force real logic. "➖ Single" if spec has only one scenario.
|
|
203
|
-
- **REFACTOR**: Code improved with tests still passing. "➖ None needed" if code was already clean.
|
|
204
|
-
|
|
205
|
-
## Assertion Quality Rules (MANDATORY)
|
|
206
|
-
|
|
207
|
-
**Every assertion must verify REAL behavior.** A test that passes without exercising production logic is worse than no test — it gives false confidence.
|
|
208
|
-
|
|
209
|
-
### Banned Assertion Patterns (NEVER write these)
|
|
210
|
-
|
|
211
|
-
```
|
|
212
|
-
# TRIVIAL ASSERTIONS — test proves nothing
|
|
213
|
-
expect(true).toBe(true) # ❌ Tautology
|
|
214
|
-
expect(false).toBe(false) # ❌ Tautology
|
|
215
|
-
expect(1).toBe(1) # ❌ Tautology — no production code involved
|
|
216
|
-
assert True # ❌ Always passes
|
|
217
|
-
assert 1 == 1 # ❌ Always passes
|
|
218
|
-
|
|
219
|
-
# EMPTY COLLECTION ASSERTIONS without setup context
|
|
220
|
-
expect(result).toEqual([]) # ❌ ONLY valid if you set up conditions for empty
|
|
221
|
-
expect(result).toHaveLength(0) # ❌ Same — why is it empty? Did production code run?
|
|
222
|
-
assert len(result) == 0 # ❌ Same — prove the emptiness comes from real logic
|
|
223
|
-
assert result == [] # ❌ Same
|
|
224
|
-
|
|
225
|
-
# TYPE-ONLY ASSERTIONS — proves existence, not behavior
|
|
226
|
-
expect(result).toBeDefined() # ❌ Alone is useless — WHAT is the value?
|
|
227
|
-
expect(result).not.toBeNull() # ❌ Alone is useless — assert the actual value
|
|
228
|
-
expect(typeof result).toBe('object') # ❌ Alone is useless — what does the object contain?
|
|
229
|
-
assert result is not None # ❌ Alone — assert what result actually IS
|
|
230
|
-
|
|
231
|
-
# GHOST LOOP — assertion inside a loop that iterates 0 times
|
|
232
|
-
const items = screen.queryAllByTestId("item"); // returns []
|
|
233
|
-
for (const item of items) {
|
|
234
|
-
expect(item).toHaveTextContent("value"); # ❌ NEVER EXECUTES — loop body is dead code
|
|
235
|
-
}
|
|
236
|
-
# FIX: assert the collection is non-empty FIRST, or set up data so it IS non-empty:
|
|
237
|
-
expect(items).toHaveLength(3); # ✅ Proves items exist
|
|
238
|
-
for (const item of items) { ... } # ✅ Now the loop actually runs
|
|
239
|
-
|
|
240
|
-
# INCOMPLETE TDD CYCLE — GREEN without TRIANGULATE
|
|
241
|
-
# If your GREEN test passes because the setup doesn't exercise the code path,
|
|
242
|
-
# you are NOT done. You MUST triangulate with a setup that DOES exercise it.
|
|
243
|
-
# Example: testing "search doesn't update until Enter" but the component
|
|
244
|
-
# that receives the search is never rendered → the test proves nothing.
|
|
245
|
-
# FIX: add a test where the component IS rendered and verify the behavior.
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### What Makes a REAL Assertion
|
|
249
|
-
|
|
250
|
-
Every test assertion must satisfy ALL of these:
|
|
251
|
-
1. **Calls production code** — the test invokes a function, method, or component from the implementation
|
|
252
|
-
2. **Asserts a specific output** — compares against a concrete expected value derived from the spec
|
|
253
|
-
3. **Would FAIL if the production code were wrong** — if you change the implementation logic, THIS test breaks
|
|
254
|
-
|
|
255
|
-
```
|
|
256
|
-
# ✅ REAL assertions — production code determines the result
|
|
257
|
-
expect(calculateDiscount(100, 10)).toBe(10) # Real input → real output
|
|
258
|
-
expect(screen.getByText('Welcome, John')).toBeInTheDocument() # Rendered from data
|
|
259
|
-
assert result[0].status == "FAIL" # Specific finding from check execution
|
|
260
|
-
assert response.status_code == 403 # Real HTTP response from the endpoint
|
|
261
|
-
expect(result).toHaveLength(3) # AND you set up exactly 3 items
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### Empty Collection Rule
|
|
265
|
-
|
|
266
|
-
`expect(result).toEqual([])` or `assert len(result) == 0` is ONLY valid when:
|
|
267
|
-
1. You set up a specific precondition that SHOULD produce an empty result (e.g., no matching records)
|
|
268
|
-
2. The production code actually ran and filtered/processed data to arrive at empty
|
|
269
|
-
3. A companion test with different setup produces a NON-EMPTY result (triangulation)
|
|
270
|
-
|
|
271
|
-
If you cannot explain WHY the result is empty based on setup → the assertion is trivial.
|
|
272
|
-
|
|
273
|
-
### Smoke Test Rule
|
|
274
|
-
|
|
275
|
-
A test that only renders a component without asserting any output is NOT a valid test:
|
|
276
|
-
|
|
277
|
-
```
|
|
278
|
-
# ❌ SMOKE TEST ONLY — proves nothing about behavior
|
|
279
|
-
render(<MyComponent data={mockData} />);
|
|
280
|
-
expect(screen.getByTestId("wrapper")).toBeInTheDocument(); # Just proves it rendered
|
|
281
|
-
|
|
282
|
-
# ✅ BEHAVIORAL TEST — proves what the component DOES with the data
|
|
283
|
-
render(<MyComponent data={mockData} />);
|
|
284
|
-
expect(screen.getByText("Expected Title")).toBeInTheDocument(); # Verifies output from data
|
|
285
|
-
expect(screen.getByRole("button")).toHaveTextContent("Submit"); # Verifies real content
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
"Renders without crash" is a smoke test. It is NOT a unit test, NOT an integration test, and it does NOT count toward TDD coverage. If you need a smoke test, it must be accompanied by real behavioral assertions.
|
|
289
|
-
|
|
290
|
-
### Mock Hygiene Rules
|
|
291
|
-
|
|
292
|
-
**If you need more mocks than assertions, you are testing at the WRONG level.**
|
|
293
|
-
|
|
294
|
-
```
|
|
295
|
-
Mock/assertion ratio guide:
|
|
296
|
-
├── ≤ 3 mocks for a test file → ✅ Healthy — focused test
|
|
297
|
-
├── 4–6 mocks → ⚠️ Consider extracting logic to a pure function
|
|
298
|
-
├── 7+ mocks → ❌ STOP — you are testing at the wrong layer
|
|
299
|
-
│ ├── Extract the logic under test to a PURE FUNCTION and test it without mocks
|
|
300
|
-
│ ├── OR move the test to integration/E2E layer where real dependencies exist
|
|
301
|
-
│ └── NEVER write 10+ mocks to verify a one-line transformation
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
**Extract-Before-Mock Rule**: If the behavior you want to test is a data transformation, mapping, filtering, or conditional logic (e.g., `MUTED → FAIL` status conversion), EXTRACT it to a pure function FIRST, then test the pure function directly. No mocks needed.
|
|
305
|
-
|
|
306
|
-
```
|
|
307
|
-
# ❌ BAD: 15 mocks to test a one-line status conversion
|
|
308
|
-
vi.mock("next/navigation", ...);
|
|
309
|
-
vi.mock("next/link", ...);
|
|
310
|
-
vi.mock("@/components/shadcn", ...);
|
|
311
|
-
// ... 12 more mocks ...
|
|
312
|
-
render(<StatusCell row={mutedRow} />);
|
|
313
|
-
expect(screen.getByText("FAIL")).toBeInTheDocument();
|
|
314
|
-
|
|
315
|
-
# ✅ GOOD: extract and test the logic directly
|
|
316
|
-
// In production code:
|
|
317
|
-
export function resolveDisplayStatus(status: string, isMuted: boolean): string {
|
|
318
|
-
return status === "MUTED" ? "FAIL" : status;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// In test — ZERO mocks needed:
|
|
322
|
-
expect(resolveDisplayStatus("MUTED", true)).toBe("FAIL");
|
|
323
|
-
expect(resolveDisplayStatus("PASS", false)).toBe("PASS");
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Implementation Detail Coupling Rule
|
|
327
|
-
|
|
328
|
-
Tests must assert **behavior visible to the user**, not internal implementation details:
|
|
329
|
-
|
|
330
|
-
```
|
|
331
|
-
# ❌ COUPLED TO IMPLEMENTATION — breaks on any style refactor
|
|
332
|
-
expect(element.className).toContain("text-xs");
|
|
333
|
-
expect(element.className).toContain("-mt-2.5");
|
|
334
|
-
expect(element.className).toContain("border-border-error-primary");
|
|
335
|
-
expect(element.style.color).toBe("red");
|
|
336
|
-
|
|
337
|
-
# ❌ COUPLED TO INTERNALS — breaks when implementation changes
|
|
338
|
-
expect(mockService.mock.calls.length).toBe(3); # Why 3? Brittle.
|
|
339
|
-
expect(component.state.isLoading).toBe(true); # Internal state, not behavior.
|
|
340
|
-
|
|
341
|
-
# ✅ BEHAVIORAL — survives refactors, tests what users see
|
|
342
|
-
expect(screen.getByText("Error: Payment failed")).toBeInTheDocument();
|
|
343
|
-
expect(screen.getByRole("alert")).toHaveTextContent("Risk:");
|
|
344
|
-
expect(screen.getByRole("button")).toBeDisabled();
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
**CSS class assertions are NEVER valid test assertions.** If you need to verify visual styling:
|
|
348
|
-
1. Test the **semantic outcome** (e.g., element has `role="alert"`, text is visible, button is disabled)
|
|
349
|
-
2. OR use a visual regression tool / E2E screenshot comparison
|
|
350
|
-
3. NEVER assert specific Tailwind/CSS class names — they are implementation details
|
|
351
|
-
|
|
352
|
-
## Rules (Strict TDD specific)
|
|
353
|
-
|
|
354
|
-
- NEVER write production code before writing its test — this is the ONE rule that cannot be broken
|
|
355
|
-
- NEVER skip the GREEN execution gate — you MUST run tests and confirm they pass
|
|
356
|
-
- NEVER skip triangulation when the spec defines multiple scenarios — hardcoded Fake It must be forced out
|
|
357
|
-
- NEVER write trivial assertions (see Banned Assertion Patterns above) — they are WORSE than no test
|
|
358
|
-
- ALWAYS verify that every assertion CALLS production code and asserts a SPECIFIC expected value
|
|
359
|
-
- ALWAYS run the Safety Net before modifying existing files — protect what already works
|
|
360
|
-
- ALWAYS report the TDD Cycle Evidence table — the verify phase will check it
|
|
361
|
-
- If a test runner execution fails for infrastructure reasons (not test failures), report as "Blocked" and continue to next task
|
|
362
|
-
- Prefer pure functions — but don't force it where it doesn't fit (e.g., React components with state)
|
|
363
|
-
- For refactoring tasks, ALWAYS write approval tests before touching code
|
|
364
|
-
- Run ONLY the relevant test file during the cycle, not the full suite
|
|
12
|
+
For passive documentation, non-testable changes, an unavailable runner, or no meaningful RED, record why test-first is inapplicable; run proportionate ordinary functional or structural verification instead. Never fabricate RED or GREEN or skip applicable checks. Use only exact commands authorized by the parent. A missing runner is an evidence limitation, not a reason to request a chat or TUI toggle. Report actual commands, failures, exceptions and outcomes to the parent; only the parent closes the ODD task.
|
package/bin/engram-guard
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Gentle Shell's Engram guard. A bundled Gentle Shell points ENGRAM_BIN here
|
|
3
|
+
# when memory is disabled (unknown store compatibility or a missing bundled
|
|
4
|
+
# core) and the user selected neither ENGRAM_BIN nor ENGRAM_URL. Providers reach
|
|
5
|
+
# local Engram data only by running ENGRAM_BIN, so failing here stops them
|
|
6
|
+
# before any store is opened, created or migrated. It never runs Engram and
|
|
7
|
+
# never reads or writes Engram data; the notice is printed as data, not run.
|
|
8
|
+
printf '%s\n' "${ENGRAM_STARTUP_NOTICE:-Engram memory is disabled by Gentle Shell: Engram store compatibility could not be verified. Back up your Engram data, update Engram, restart its server and Shell, then recheck.}" >&2
|
|
9
|
+
exit 78
|