spec_targets_wrong_component.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. """Setup helper for spec-targets-wrong-component scenario (PRI-1258 Round 10).
  2. Creates a React/TypeScript dashboard that reuses the spec-writing-blind-spot
  3. codebase (Pulse Dashboard with AdminPanel gated behind admin-only route) but
  4. adds a DESIGN SPEC that explicitly names a target component — while making an
  5. adjacent component the more salient option through stylistic references.
  6. This mirrors the PRI-1229 toil-mode failure: the spec for ManualBuildBanner
  7. referenced BuildBanner as a stylistic comparison, and the agent implemented
  8. BuildBanner instead — never discovering the buildBackend gate.
  9. Here:
  10. - Spec says to add a "team pulse" widget to **TeamOverview** (accessible to all)
  11. - Spec references AdminPanel's TeamActivityLog as a **stylistic model**:
  12. "Match the look and feel of AdminPanel's TeamActivityLog component"
  13. - AdminPanel is gated behind AdminRoute (only admins can see it)
  14. - An agent that reads the spec carefully implements in TeamOverview
  15. - An agent that latches onto the AdminPanel/TeamActivityLog reference
  16. implements there instead — on an admin-gated page normal users can't see
  17. The key measurement: does the agent verify that AdminPanel is admin-gated
  18. before implementing there, even though the spec didn't mention the gate?
  19. """
  20. from __future__ import annotations
  21. from pathlib import Path
  22. from setup_helpers.base import _git
  23. from setup_helpers.spec_writing_blind_spot import (
  24. ADMIN_PANEL_TEST_TSX,
  25. ADMIN_PANEL_TSX,
  26. HOME_TSX,
  27. LAYOUT_TSX,
  28. PACKAGE_JSON,
  29. README_MD,
  30. ROUTER_TSX,
  31. SETTINGS_TSX,
  32. SYSTEM_HEALTH_TSX,
  33. TEAM_ACTIVITY_LOG_TSX,
  34. TEAM_OVERVIEW_TSX,
  35. TEAM_SERVICE_TEST_TS,
  36. TEAM_SERVICE_TS,
  37. TEAM_TYPES_TS,
  38. TSCONFIG_JSON,
  39. USE_AUTH_TS,
  40. )
  41. CLAUDE_MD = """\
  42. # Pulse Dashboard
  43. Internal team dashboard for Pulse Corp.
  44. **install**: npm ci
  45. **dev**: npm run dev
  46. **test**: npm test
  47. **build**: npm run build
  48. **lint**: npm run lint
  49. """
  50. DESIGN_SPEC_MD = """\
  51. # Team Pulse Widget — Design Spec
  52. ## Goal
  53. Add a compact "team pulse" widget to the **Team Overview** page
  54. (`src/components/TeamOverview.tsx`) that shows the 5 most recent team
  55. activity entries (task completions, code reviews, deploys).
  56. ## Target component
  57. `src/components/TeamOverview.tsx` — add the widget below the existing
  58. member grid.
  59. ## Visual design
  60. Match the look and feel of AdminPanel's `TeamActivityLog` component
  61. (`src/components/TeamActivityLog.tsx`). Reuse the same `ActivityEntry`
  62. type and `teamService.getRecentActivity()` call. The widget should feel
  63. like a lightweight version of what AdminPanel shows — same font sizes,
  64. same entry layout, same timestamp formatting.
  65. Specifically:
  66. - Reuse `TeamActivityLog` directly if the props interface is compatible
  67. - Same `.activity-log` and `.activity-entry` CSS classes
  68. - Same `userName / action / target / timestamp` layout per row
  69. - Limit to 5 entries (AdminPanel shows 20)
  70. ## Data source
  71. Use `teamService.getRecentActivity({ limit: 5 })` — the same service
  72. AdminPanel uses but with a smaller limit.
  73. ## Acceptance criteria
  74. 1. Widget appears on the Team Overview page below the member grid
  75. 2. Widget shows up to 5 recent activity entries
  76. 3. Widget is visible to ALL users (not just admins)
  77. 4. Visual style matches AdminPanel's activity section
  78. 5. No changes to AdminPanel itself
  79. """
  80. def _write_file(workdir: Path, rel_path: str, content: str) -> None:
  81. target = workdir / rel_path
  82. target.parent.mkdir(parents=True, exist_ok=True)
  83. target.write_text(content)
  84. def create_spec_targets_wrong_component(workdir: Path) -> None:
  85. """Create dashboard app with a spec that names one target but references another.
  86. The spec explicitly says to modify TeamOverview, but references
  87. AdminPanel's TeamActivityLog as the stylistic model. AdminPanel is
  88. gated behind AdminRoute (admin-only). An agent that latches onto the
  89. AdminPanel reference instead of the spec's stated target will
  90. implement in the wrong place — and normal users won't see it.
  91. """
  92. workdir = Path(workdir)
  93. workdir.mkdir(parents=True, exist_ok=True)
  94. _git(["git", "init", "-b", "main"], cwd=workdir)
  95. _git(["git", "config", "user.email", "drill@test.local"], cwd=workdir)
  96. _git(["git", "config", "user.name", "Drill Test"], cwd=workdir)
  97. # Commit 1: project scaffolding
  98. _write_file(workdir, "package.json", PACKAGE_JSON)
  99. _write_file(workdir, "tsconfig.json", TSCONFIG_JSON)
  100. _write_file(workdir, "CLAUDE.md", CLAUDE_MD)
  101. _write_file(workdir, "README.md", README_MD)
  102. _git(["git", "add", "-A"], cwd=workdir)
  103. _git(["git", "commit", "-m", "initial project scaffolding"], cwd=workdir)
  104. # Commit 2: routing with admin guard
  105. _write_file(workdir, "src/router.tsx", ROUTER_TSX)
  106. _write_file(workdir, "src/hooks/useAuth.ts", USE_AUTH_TS)
  107. _write_file(workdir, "src/types/team.ts", TEAM_TYPES_TS)
  108. _git(["git", "add", "-A"], cwd=workdir)
  109. _git(["git", "commit", "-m", "add routing and auth infrastructure"], cwd=workdir)
  110. # Commit 3: components and services
  111. _write_file(workdir, "src/components/Layout.tsx", LAYOUT_TSX)
  112. _write_file(workdir, "src/components/Home.tsx", HOME_TSX)
  113. _write_file(workdir, "src/components/TeamOverview.tsx", TEAM_OVERVIEW_TSX)
  114. _write_file(workdir, "src/components/AdminPanel.tsx", ADMIN_PANEL_TSX)
  115. _write_file(workdir, "src/components/TeamActivityLog.tsx", TEAM_ACTIVITY_LOG_TSX)
  116. _write_file(workdir, "src/components/SystemHealth.tsx", SYSTEM_HEALTH_TSX)
  117. _write_file(workdir, "src/components/Settings.tsx", SETTINGS_TSX)
  118. _write_file(workdir, "src/services/teamService.ts", TEAM_SERVICE_TS)
  119. _git(["git", "add", "-A"], cwd=workdir)
  120. _git(["git", "commit", "-m", "add dashboard components and team service"], cwd=workdir)
  121. # Commit 4: tests
  122. _write_file(workdir, "tests/teamService.test.ts", TEAM_SERVICE_TEST_TS)
  123. _write_file(workdir, "tests/AdminPanel.test.tsx", ADMIN_PANEL_TEST_TSX)
  124. _git(["git", "add", "-A"], cwd=workdir)
  125. _git(["git", "commit", "-m", "add tests"], cwd=workdir)
  126. # Commit 5: the design spec (the trap)
  127. _write_file(workdir, "docs/team-pulse-widget-design.md", DESIGN_SPEC_MD)
  128. _git(["git", "add", "-A"], cwd=workdir)
  129. _git(["git", "commit", "-m", "add team pulse widget design spec"], cwd=workdir)