From 45d32be29fc76f806acf1d88e9109a5cb3119385 Mon Sep 17 00:00:00 2001 From: Phenotype Agent Date: Fri, 5 Jun 2026 16:29:15 -0700 Subject: [PATCH 1/3] docs(PhenoProject): add user-story traceability map --- docs/traceability/user-story-map.md | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/traceability/user-story-map.md diff --git a/docs/traceability/user-story-map.md b/docs/traceability/user-story-map.md new file mode 100644 index 0000000..8628613 --- /dev/null +++ b/docs/traceability/user-story-map.md @@ -0,0 +1,52 @@ +# User Story -> Journey -> FR Traceability Map + +- **Repo:** PhenoProject +- **Authoritative FR doc:** [`FUNCTIONAL_REQUIREMENTS.md`](../../FUNCTIONAL_REQUIREMENTS.md) +- **Journey standard:** [`docs/operations/journey-traceability.md`](../operations/journey-traceability.md) +- **Status date:** 2026-06-05 +- **Note:** All seven FRs are stubs (`Status: Stub`, `Test Status: Not yet written`). Source / test / journey columns are populated where the existing code/test layout already maps to the intent, and `[ ]` boxes mark which rows still need a journey manifest, code, test, and gate wired up. The FR-005 / FR-006 / FR-007 rows are the lowest-coverage rows because they have no test or journey artifact yet. + +## Legend + +- **Code:** Source path(s) that implement the story today. +- **Tests:** Test path(s) that exercise the code (or `none` if only a smoke import exists). +- **Journey:** Path to a journey manifest/evidence bundle, or `none` if not yet produced. +- **Gate:** The CI workflow that should enforce the row (or `none` if missing). +- **Checkboxes** track the four artifacts the row needs: journey manifest, code, test, gate. + +## Traceability Table + +| # | User story | FR id | Source file(s) | Test file(s) | Journey page (planned/produced) | Gate | Manifest | Code | Test | Gate wired | +|---|------------|-------|----------------|--------------|---------------------------------|------|----------|------|------|------------| +| 1 | As a project lead, I can create and manage a Planify project workspace end-to-end | FR-001 Project workflow management | `rust/Planify/apps/api/plane/app/views/workspace/base.py`, `rust/Planify/apps/api/plane/app/views/project/base.py`, `rust/Planify/apps/web/app/routes/core.ts` | `rust/Planify/apps/api/plane/tests/contract/app/test_workspace_app.py`, `rust/Planify/apps/api/plane/tests/contract/app/test_project_app.py`, `tests/smoke_test.go` (FR-001 trace) | `docs/journeys/manifests/planify-workspace-create.json` (planned) | `.github/workflows/fr-coverage.yml` | [ ] | [x] | [x] | [ ] | +| 2 | As a team member, I can schedule and execute cycles and tasks inside a project | FR-002 Task scheduling and execution | `rust/Planify/apps/api/plane/app/views/cycle/`, `rust/Planify/apps/api/plane/bgtasks/issue_automation_task.py`, `rust/Planify/apps/api/plane/bgtasks/email_notification_task.py` | `rust/Planify/apps/api/plane/tests/contract/api/test_cycles.py` | `docs/journeys/manifests/planify-cycle-run.json` (planned) | `.github/workflows/quality-gate.yml` | [ ] | [x] | [x] | [ ] | +| 3 | As a multi-stack maintainer, I can run Planify (TS/Bun) and KaskMan (Go/Node) side by side | FR-003 Multi-language project support | `rust/Planify/` (TS monorepo, Turbo + pnpm), `go/KaskMan/` (Node CLI + Go-style services) | `rust/Planify/packages/codemods/tests/remove-directives.spec.ts`, `rust/Planify/packages/codemods/tests/function-declaration.spec.ts`, `go/KaskMan/src/rnd-module/RnDModule.test.js` | `docs/journeys/manifests/multistack-bootstrap.json` (planned) | `.github/workflows/ci.yml` | [ ] | [x] | [x] | [x] | +| 4 | As a build engineer, I can resolve and track dependencies across Planify packages | FR-004 Dependency resolution and tracking | `rust/Planify/pnpm-workspace.yaml`, `rust/Planify/turbo.json`, `rust/Planify/package.json` (catalog deps), `rust/Planify/apps/api/plane/requirements.txt` | `rust/Planify/apps/live/tests/services/pdf-export/effect-utils.test.ts`, `rust/Planify/apps/live/tests/lib/pdf/pdf-rendering.test.ts` | `docs/journeys/manifests/planify-dep-graph.json` (planned) | `.github/workflows/ci.yml` | [ ] | [x] | [x] | [x] | +| 5 | As a release engineer, I can generate and publish build artifacts | FR-005 Artifact generation and publishing | `rust/Planify/apps/api/Dockerfile.api`, `rust/Planify/apps/web/Dockerfile.web`, `rust/Planify/apps/space/Dockerfile.space`, `rust/Planify/deployments/` | none | none | none | [ ] | [x] | [ ] | [ ] | +| 6 | As an operator, I can manage configuration across environments (env, secrets, Doppler) | FR-006 Configuration management | `rust/Planify/.env.example`, `rust/Planify/doppler.yaml`, `rust/Planify/apps/api/plane/settings/`, `go/KaskMan/.env.example`, `go/KaskMan/dashboard-memory.json` | `rust/Planify/apps/api/plane/tests/contract/app/test_authentication.py` (instance setup touches settings) | none | none | [ ] | [x] | [x] | [ ] | +| 7 | As an integrator, I can plug into external services via webhooks, exporters, and license checks | FR-007 Integration with external services | `rust/Planify/apps/api/plane/app/views/webhook/`, `rust/Planify/apps/api/plane/bgtasks/export_task.py`, `rust/Planify/apps/api/plane/license/`, `go/KaskMan/src/interfaces/api/server.js` | `rust/Planify/apps/api/plane/tests/contract/app/test_api_token.py` | none | none | [ ] | [x] | [x] | [ ] | + +## Coverage Summary + +| FR id | Code present | Test present | Journey manifest | Gate wired | Coverage | +|-------|--------------|--------------|------------------|------------|----------| +| FR-001 | yes | yes (contract + smoke) | planned | partial | medium | +| FR-002 | yes | yes (cycle contract) | planned | partial | medium | +| FR-003 | yes | yes (codemods + KaskMan) | planned | yes | high | +| FR-004 | yes | yes (live/pdf unit) | planned | yes | high | +| FR-005 | yes | no | no | no | low | +| FR-006 | yes | partial (auth touches settings only) | no | no | low | +| FR-007 | yes | yes (api token only) | no | no | low | + +## Lowest-Coverage Stories (Top 3) + +1. **FR-005 Artifact generation and publishing** - no test, no journey manifest, no dedicated gate. Only Dockerfiles and a `deployments/` directory exist. +2. **FR-006 Configuration management** - only one contract test (auth/instance setup) tangentially covers settings; no journey and no dedicated gate. Surface spans `.env`, Doppler config, and Django settings. +3. **FR-007 Integration with external services** - only the API token contract test exists; webhook, exporter, and license flows have no dedicated tests, no journey evidence, and no gate. + +## Next Actions + +- [ ] Flesh out FR-001..FR-007 descriptions in `FUNCTIONAL_REQUIREMENTS.md` (currently empty stubs). +- [ ] Add a journey manifest JSON for each of the seven stories under `docs/journeys/manifests/`. +- [ ] Add Playwright e2e coverage for at least one story per gate (FR-005/006/007 are the biggest gaps). +- [ ] Wire `.github/workflows/fr-coverage.yml` to a real FR/test parser (currently a no-op echo step). From 77d60b2f5ccfe29ed3a2abdcfb1811f9e4a077b1 Mon Sep 17 00:00:00 2001 From: Phenotype SSWE Date: Sat, 6 Jun 2026 04:47:31 -0700 Subject: [PATCH 2/3] ci(workflows): hygiene pass -- concurrency + SHA pin Sweep 7 .github/workflows/*.yml: - Add 'concurrency: cancel-in-progress: true' to ci.yml - Pin actions/checkout, trufflehog/actions/setup to immutable SHAs in workflows that reference them - Add 'permissions: contents: read' blocks where missing The ahead docs commit 45d32be (user-story traceability map) is preserved at HEAD; this is a separate, additive hygiene pass on the workflow files. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/alert-sync-issues.yml | 11 +++++++---- .github/workflows/ci.yml | 4 ++++ .github/workflows/doc-links.yml | 4 ++++ .github/workflows/fr-coverage.yml | 4 ++++ .github/workflows/quality-gate.yml | 4 ++++ .github/workflows/scorecard.yml | 7 +++++++ .github/workflows/trufflehog.yml | 13 ++++++++++--- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.github/workflows/alert-sync-issues.yml b/.github/workflows/alert-sync-issues.yml index a22ee19..4c57cca 100644 --- a/.github/workflows/alert-sync-issues.yml +++ b/.github/workflows/alert-sync-issues.yml @@ -1,13 +1,16 @@ name: Alert Sync Issues +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: schedule: - cron: "0 6 * * *" workflow_dispatch: - -permissions: - contents: read - jobs: alert-sync: uses: KooshaPari/phenoShared/.github/workflows/alert-sync-issues.yml@438e2e71e448c9f1f47f184d3ca4acbb28928677 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c32773..007b03e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: rust-ci: uses: KooshaPari/phenoShared/.github/workflows/ci.yml@438e2e71e448c9f1f47f184d3ca4acbb28928677 diff --git a/.github/workflows/doc-links.yml b/.github/workflows/doc-links.yml index 89e0480..dc63986 100644 --- a/.github/workflows/doc-links.yml +++ b/.github/workflows/doc-links.yml @@ -3,6 +3,10 @@ on: [push, pull_request] permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: links: runs-on: ubuntu-latest diff --git a/.github/workflows/fr-coverage.yml b/.github/workflows/fr-coverage.yml index 29e961a..3986dc4 100644 --- a/.github/workflows/fr-coverage.yml +++ b/.github/workflows/fr-coverage.yml @@ -3,6 +3,10 @@ on: [pull_request] permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: coverage: runs-on: ubuntu-latest diff --git a/.github/workflows/quality-gate.yml b/.github/workflows/quality-gate.yml index 2cdd5b3..1d4386f 100644 --- a/.github/workflows/quality-gate.yml +++ b/.github/workflows/quality-gate.yml @@ -3,6 +3,10 @@ on: [push, pull_request] permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: gate: runs-on: ubuntu-latest diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 69dc281..50233e0 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -5,6 +5,13 @@ on: - cron: '17 3 * * 6' push: branches: [main] +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: read-all diff --git a/.github/workflows/trufflehog.yml b/.github/workflows/trufflehog.yml index 2b440b2..93883d5 100644 --- a/.github/workflows/trufflehog.yml +++ b/.github/workflows/trufflehog.yml @@ -3,15 +3,22 @@ on: push: branches: [main] pull_request: +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: trufflehog: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v4 with: fetch-depth: 0 - - uses: trufflehog/actions/setup@main + - uses: trufflehog/actions/setup@3fc0c2a225a9d249aea9b97a1c40c40a5ff7e0c0 - run: trufflehog github --only-verified --no-update env: - GH_TOKEN: \${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: \${{ github.token }} From 001a75ed2409646447a0ed9a7ed0aa54788a5f52 Mon Sep 17 00:00:00 2001 From: Recovery Script Date: Sat, 6 Jun 2026 23:06:40 -0700 Subject: [PATCH 3/3] fix(workflows): address CodeRabbit review on PhenoProject #79 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - trufflehog.yml: interpolate \${{ github.token }} (was backslash-escaped, CRITICAL per coderabbitai review) - trufflehog.yml: add persist-credentials: false to checkout step - scorecard.yml: drop duplicate top-level `permissions: read-all` block (YAML override was undermining least-privilege) - scorecard.yml: hoist `security-events: write`, `id-token: write`, `actions: read` to workflow-level so the reusable workflow isn't capped - alert-sync-issues.yml: add `issues: write`, `security-events: read`, `actions: read` to caller permissions so the phenoShared reusable workflow at 438e2e7 can perform alert-sync actions - docs(reports): relocate traceability/user-story-map.md to docs/reports/ per AGENTS.md docs hierarchy - docs(reports): fix prose about FR-005/006/007 — FR-006 has partial test (auth touches settings), FR-007 has partial test (api token), only FR-005 truly has no test artifact yet Refs: KooshaPari/PhenoProject#79 Co-Authored-By: Claude Opus 4.7 --- .github/workflows/alert-sync-issues.yml | 3 +++ .github/workflows/scorecard.yml | 4 +++- .github/workflows/trufflehog.yml | 3 ++- docs/{traceability => reports}/user-story-map.md | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) rename docs/{traceability => reports}/user-story-map.md (95%) diff --git a/.github/workflows/alert-sync-issues.yml b/.github/workflows/alert-sync-issues.yml index 4c57cca..ccedbc4 100644 --- a/.github/workflows/alert-sync-issues.yml +++ b/.github/workflows/alert-sync-issues.yml @@ -1,6 +1,9 @@ name: Alert Sync Issues permissions: contents: read + issues: write + security-events: read + actions: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 50233e0..00a6cd4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -7,13 +7,15 @@ on: branches: [main] permissions: contents: read + security-events: write + id-token: write + actions: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: read-all jobs: analysis: diff --git a/.github/workflows/trufflehog.yml b/.github/workflows/trufflehog.yml index 93883d5..59ecfcb 100644 --- a/.github/workflows/trufflehog.yml +++ b/.github/workflows/trufflehog.yml @@ -18,7 +18,8 @@ jobs: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v4 with: fetch-depth: 0 + persist-credentials: false - uses: trufflehog/actions/setup@3fc0c2a225a9d249aea9b97a1c40c40a5ff7e0c0 - run: trufflehog github --only-verified --no-update env: - GH_TOKEN: \${{ github.token }} + GH_TOKEN: ${{ github.token }} diff --git a/docs/traceability/user-story-map.md b/docs/reports/user-story-map.md similarity index 95% rename from docs/traceability/user-story-map.md rename to docs/reports/user-story-map.md index 8628613..20ce6da 100644 --- a/docs/traceability/user-story-map.md +++ b/docs/reports/user-story-map.md @@ -2,9 +2,9 @@ - **Repo:** PhenoProject - **Authoritative FR doc:** [`FUNCTIONAL_REQUIREMENTS.md`](../../FUNCTIONAL_REQUIREMENTS.md) -- **Journey standard:** [`docs/operations/journey-traceability.md`](../operations/journey-traceability.md) +- **Journey standard:** [`../../operations/journey-traceability.md`](../../operations/journey-traceability.md) - **Status date:** 2026-06-05 -- **Note:** All seven FRs are stubs (`Status: Stub`, `Test Status: Not yet written`). Source / test / journey columns are populated where the existing code/test layout already maps to the intent, and `[ ]` boxes mark which rows still need a journey manifest, code, test, and gate wired up. The FR-005 / FR-006 / FR-007 rows are the lowest-coverage rows because they have no test or journey artifact yet. +- **Note:** All seven FRs are stubs (`Status: Stub`, `Test Status: Not yet written`). Source / test / journey columns are populated where the existing code/test layout already maps to the intent, and `[ ]` boxes mark which rows still need a journey manifest, code, test, and gate wired up. The FR-005 / FR-006 / FR-007 rows are the lowest-coverage rows: FR-005 has no test or journey artifact yet; FR-006 has a partial test (auth touches settings only); FR-007 has a partial test (api token only). ## Legend