Compare commits
10
Commits
46bea03757
...
a6e2474379
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6e2474379 | ||
|
|
da623ac234 | ||
|
|
0278e2080a | ||
|
|
c0c217019c | ||
|
|
e153f7c355 | ||
|
|
547b12ca4a | ||
|
|
72604385bc | ||
|
|
20ebd90554 | ||
|
|
cd6be1b9c3 | ||
|
|
4c5efb0604 |
+54
-4
@@ -5,6 +5,31 @@ on:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
permissions:
|
||||
pull-requests: read
|
||||
outputs:
|
||||
code: ${{ steps.filter.outputs.code }}
|
||||
steps:
|
||||
- uses: dorny/paths-filter@v4
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
code:
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.js'
|
||||
- '**/*.json'
|
||||
- '**/*.yaml'
|
||||
- '**/*.yml'
|
||||
- 'apps/**'
|
||||
- 'packages/**'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'Dockerfile'
|
||||
- 'docker-compose*.yml'
|
||||
|
||||
fast-checks:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
@@ -42,8 +67,9 @@ jobs:
|
||||
|
||||
api:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
# Runs in PARALLEL with fast-checks (D-03) — no needs: dependency.
|
||||
needs: [changes]
|
||||
if: github.event_name == 'pull_request' && needs.changes.outputs.code == 'true'
|
||||
# Runs in PARALLEL with fast-checks (D-03) — skipped for doc-only PRs.
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:11
|
||||
@@ -128,8 +154,9 @@ jobs:
|
||||
|
||||
harness:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
# Runs in PARALLEL with fast-checks + api (D-03) — no needs: dependency.
|
||||
needs: [changes]
|
||||
if: github.event_name == 'pull_request' && needs.changes.outputs.code == 'true'
|
||||
# Runs in PARALLEL with fast-checks (D-03) — skipped for doc-only PRs.
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:11
|
||||
@@ -314,3 +341,26 @@ jobs:
|
||||
apps/pwa/test-results/
|
||||
apps/pwa/playwright-report/
|
||||
retention-days: 14
|
||||
|
||||
gate:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [fast-checks, changes, api, harness]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check all required jobs passed or were skipped
|
||||
run: |
|
||||
# fast-checks always runs — must be success
|
||||
if [ "${{ needs.fast-checks.result }}" != "success" ]; then
|
||||
echo "fast-checks: ${{ needs.fast-checks.result }}"
|
||||
exit 1
|
||||
fi
|
||||
# api and harness are conditionally skipped — success OR skipped are both acceptable
|
||||
# NOTE: uses individual needs.X.result checks (not the wildcard aggregate) due to
|
||||
# Gitea 1.26.2 bug #31007 where the wildcard expression returns false even when jobs succeed.
|
||||
for result in "${{ needs.api.result }}" "${{ needs.harness.result }}"; do
|
||||
if [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
|
||||
echo "Heavy job failed or was cancelled: $result"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Gate passed."
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
# GITEA_-prefixed names cannot be created. GITEA_TOKEN / GITHUB_TOKEN cannot push packages.
|
||||
#
|
||||
# Safety gate: branch protection on main, NOT a needs: dependency in this file.
|
||||
# The PR test jobs (fast-checks, api, harness in ci.yml) run on pull_request — they never
|
||||
# run in the same workflow invocation as publish.yml. Tests gate the PR; main is trusted to
|
||||
# be green because direct push and force push are blocked and the three required checks
|
||||
# (CI / fast-checks, CI / api, CI / harness) must pass before merge.
|
||||
# The PR test jobs (fast-checks, api, harness, gate in ci.yml) run on pull_request — they
|
||||
# never run in the same workflow invocation as publish.yml. Tests gate the PR; main is
|
||||
# trusted to be green because direct push and force push are blocked and the two required
|
||||
# checks (CI / fast-checks, CI / gate) must pass before merge. CI / api and CI / harness
|
||||
# are conditionally skipped on doc-only PRs and are gated via the always-running CI / gate
|
||||
# aggregate rather than being required directly.
|
||||
#
|
||||
# To bump the milestone tag at a milestone boundary: edit MILESTONE below.
|
||||
|
||||
|
||||
@@ -284,11 +284,11 @@ Plans:
|
||||
Plans:
|
||||
**Wave 1**
|
||||
|
||||
- [ ] 15-01-PLAN.md — markdownlint-cli2 + `.markdownlint-cli2.jsonc` + `md:lint` script + fast-checks step + fix 13 baseline violations (SC-4)
|
||||
- [x] 15-01-PLAN.md — markdownlint-cli2 + `.markdownlint-cli2.jsonc` + `md:lint` script + fast-checks step + fix 13 baseline violations (SC-4)
|
||||
|
||||
**Wave 2** *(blocked on Wave 1 completion)*
|
||||
|
||||
- [ ] 15-02-PLAN.md — ci.yml: `changes` (dorny/paths-filter@v4) + conditional api/harness + always-running `gate` aggregate (SC-1/SC-2, SC-3 YAML)
|
||||
- [x] 15-02-PLAN.md — ci.yml: `changes` (dorny/paths-filter@v4) + conditional api/harness + always-running `gate` aggregate (SC-1/SC-2, SC-3 YAML)
|
||||
|
||||
**Wave 3** *(blocked on Wave 2 completion)*
|
||||
|
||||
@@ -314,7 +314,7 @@ Plans:
|
||||
| 12. Initial Setup Wizard | v1.1 | 0/? | Not started | - |
|
||||
| 13. Real Lint Gate (ESLint) | v1.1 | 3/3 | Complete | 2026-06-12 |
|
||||
| 14. Desktop E2E Coverage | v1.1 | 1/1 | Complete | 2026-06-12 |
|
||||
| 15. Doc-Only CI Skip + MD Lint | v1.1 | 0/3 | Planned | - |
|
||||
| 15. Doc-Only CI Skip + MD Lint | v1.1 | 2/3 | In Progress| |
|
||||
|
||||
## Backlog
|
||||
|
||||
@@ -322,7 +322,7 @@ Plans:
|
||||
|
||||
**Goal:** [Captured for future planning] Abstract the calendar backend behind a provider interface so Fastmail/CalDAV is one implementation among potentially many. Shipping with a single provider is fine, but the broker, sync, and event-expansion layers should be structured so additional providers (e.g. other CalDAV hosts, Google Calendar, generic ICS feeds) can be added without rework. Captures the "provider" seam as an explicit architectural concern.
|
||||
**Requirements:** TBD
|
||||
**Plans:** 1/1 plans complete
|
||||
**Plans:** 2/3 plans executed
|
||||
|
||||
Plans:
|
||||
|
||||
|
||||
+16
-4
@@ -25,10 +25,22 @@ See: .planning/PROJECT.md (updated 2026-06-10)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 15 (ci-skip-api-harness-jobs-for-doc-only-prs) — EXECUTING
|
||||
Plan: 1 of 3
|
||||
Status: Executing Phase 15
|
||||
Last activity: 2026-06-12 -- Phase 15 execution started
|
||||
Phase: 15 (ci-skip-api-harness-jobs-for-doc-only-prs) — PENDING (deferred checkpoint)
|
||||
Plan: 15-03 (Task 2 of 2 — human-action checkpoint, deferred)
|
||||
Status: Plans 15-01 + 15-02 complete; 15-03 Task 1 (publish.yml comment) committed (da623ac); 15-03 Task 2 awaiting operator after branch merges to main
|
||||
Last activity: 2026-06-12 -- Phase 15 code complete; PR pushed; 15-03 operator checkpoint deferred to post-merge
|
||||
|
||||
### Deferred Checkpoint — Phase 15 Plan 15-03 Task 2 (human-action)
|
||||
|
||||
Operator must update Gitea branch protection on `main` AFTER this branch merges and `CI / gate` has reported at least once:
|
||||
- Set required status checks to EXACTLY: `CI / fast-checks` + `CI / gate`
|
||||
- REMOVE: `CI / api` + `CI / harness` (now conditionally skipped on doc-only PRs, gated via the always-running `CI / gate`)
|
||||
- CLI option (login Bergerhouse): `tea api --method PATCH repos/luckberg/familysync/branches/main/protection --data '{"status_check_contexts":["CI / fast-checks","CI / gate"]}'`
|
||||
- Verify: throwaway doc-only PR is mergeable with api/harness skipped (SC-1/SC-3); throwaway code PR runs+gates all jobs (SC-2); close both.
|
||||
|
||||
ORDERING HAZARD: do NOT make this change before `CI / gate` exists on `main` (premature drop leaves main ungated / can block PRs).
|
||||
|
||||
Resume: after the operator completes the change, re-run `/gsd-execute-phase 15` (re-dispatches 15-03 → Task 1 already satisfied, confirm Task 2, write 15-03-SUMMARY) — then phase verification + completion run.
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
---
|
||||
phase: 15-ci-skip-api-harness-jobs-for-doc-only-prs
|
||||
plan: "01"
|
||||
subsystem: ci
|
||||
tags: [markdownlint, ci, docs, fast-checks]
|
||||
dependency_graph:
|
||||
requires: []
|
||||
provides:
|
||||
- markdownlint-cli2 root devDependency (0.22.1)
|
||||
- md:lint root package.json script
|
||||
- .markdownlint-cli2.jsonc config (Prettier-compatible preset + content rules)
|
||||
- Markdown lint step in fast-checks CI job
|
||||
affects:
|
||||
- .gitea/workflows/ci.yml (fast-checks job — new Markdown lint step)
|
||||
- package.json (new script + devDependency)
|
||||
- 7 doc files (13 baseline violations fixed)
|
||||
tech_stack:
|
||||
added:
|
||||
- markdownlint-cli2@0.22.1 (root devDependency)
|
||||
patterns:
|
||||
- Config-file-driven markdownlint (globs/ignores in .markdownlint-cli2.jsonc, not CLI args)
|
||||
- markdownlint/style/prettier preset to avoid Prettier/markdownlint rule conflicts
|
||||
key_files:
|
||||
created:
|
||||
- .markdownlint-cli2.jsonc
|
||||
modified:
|
||||
- package.json
|
||||
- pnpm-lock.yaml
|
||||
- .gitea/workflows/ci.yml
|
||||
- README.md
|
||||
- apps/api/README.md
|
||||
- apps/pwa/README.md
|
||||
- apps/pwa/e2e/README.md
|
||||
- docs/API.md
|
||||
- docs/ARCHITECTURE.md
|
||||
- docs/DEVELOPMENT.md
|
||||
- docs/GETTING-STARTED.md
|
||||
decisions:
|
||||
- "md:lint script uses no glob args — globs and ignores live in .markdownlint-cli2.jsonc so pnpm md:lint and npx markdownlint-cli2 behave identically (RESEARCH Open Question 3)"
|
||||
- "MD031 re-enabled despite prettier preset disabling it — GETTING-STARTED.md has a genuine structural fix (fence inside list item with no blank lines); verified MD031 fix does not conflict with Prettier (format:check still 0 after fix)"
|
||||
- "MD040 bare fences tagged as 'text' for plain-output blocks (SSE event format, directory trees); 'bash' for shell commands"
|
||||
- "Prettier reformatted .markdownlint-cli2.jsonc (added trailing commas per JSONC trailingComma:all rule) — committed in Task 2"
|
||||
metrics:
|
||||
duration_minutes: 4
|
||||
completed_date: "2026-06-12"
|
||||
tasks_completed: 2
|
||||
files_changed: 12
|
||||
---
|
||||
|
||||
# Phase 15 Plan 01: Markdown Lint Gate Summary
|
||||
|
||||
**One-liner:** markdownlint-cli2@0.22.1 with Prettier-compatible config wired into fast-checks CI; 13 baseline violations fixed across 7 doc files, gate starts green.
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
| Task | Name | Commit | Files |
|
||||
|------|------|--------|-------|
|
||||
| 1 | Install markdownlint-cli2, add md:lint script, create .markdownlint-cli2.jsonc | adb7641 | .markdownlint-cli2.jsonc, package.json, pnpm-lock.yaml |
|
||||
| 2 | Fix 13 baseline violations; green md:lint + format:check; wire fast-checks step | 46bea03 | .gitea/workflows/ci.yml, .markdownlint-cli2.jsonc (Prettier reformat), README.md, apps/api/README.md, apps/pwa/README.md, apps/pwa/e2e/README.md, docs/API.md, docs/ARCHITECTURE.md, docs/DEVELOPMENT.md, docs/GETTING-STARTED.md |
|
||||
|
||||
## What Was Built
|
||||
|
||||
### Task 1: markdownlint-cli2 install + config
|
||||
|
||||
- Installed `markdownlint-cli2@0.22.1` as a root workspace devDependency via `pnpm add -D markdownlint-cli2@0.22.1 --workspace-root`
|
||||
- Added `"md:lint": "markdownlint-cli2"` script to root `package.json` after `format:check`
|
||||
- Created `.markdownlint-cli2.jsonc` at repo root with:
|
||||
- `extends: "markdownlint/style/prettier"` — disables the 23 rules Prettier owns (including MD013 line-length, which would produce 700+ false positives against printWidth 100)
|
||||
- Content rules ENABLED: MD001, MD024, MD040, MD031, MD051, MD052
|
||||
- Rules DISABLED: MD041 (CLAUDE.md starts with `## Project`), MD034 (pkg@version syntax in version tables), MD036 (docs/API.md uses `**Response 200**` as semantic labels)
|
||||
- `globs`: `["docs/**/*.md", "*.md", "apps/**/*.md"]`
|
||||
- `ignores`: `[".planning/**", "node_modules/**", "**/node_modules/**", ".pnpm-store/**"]`
|
||||
|
||||
### Task 2: Baseline fixes + CI wiring
|
||||
|
||||
Fixed all 13 violations:
|
||||
- **MD040 (11 bare fences):** Added language tags across 7 files:
|
||||
- `apps/api/README.md:19` — directory tree → `text`
|
||||
- `apps/pwa/e2e/README.md:76` — pseudo-code block → `text`
|
||||
- `apps/pwa/README.md:45` — directory tree → `text`
|
||||
- `docs/API.md:517` — SSE event format → `text`
|
||||
- `docs/API.md:544` — SSE event format example → `text`
|
||||
- `docs/ARCHITECTURE.md:64` — directory tree → `text`
|
||||
- `docs/ARCHITECTURE.md:171` — backend module flow → `text`
|
||||
- `docs/DEVELOPMENT.md:9` — directory tree → `text`
|
||||
- `docs/DEVELOPMENT.md:22` — directory tree → `text`
|
||||
- `README.md:78` — monorepo structure → `text`
|
||||
- `README.md:119` — CalDAV principal URL → `text`
|
||||
- **MD031 (2 violations):** `docs/GETTING-STARTED.md:52-54` — added blank lines before ```` ```bash ```` and after closing ```` ``` ```` surrounding the `node -e` command inside a list item
|
||||
|
||||
Wired CI step in `.gitea/workflows/ci.yml`:
|
||||
```yaml
|
||||
- name: Markdown lint
|
||||
run: pnpm md:lint
|
||||
```
|
||||
Inserted after `Format check`, before `Typecheck` in the `fast-checks` job.
|
||||
|
||||
**Verification performed:**
|
||||
- `pnpm md:lint` exits 0 (Summary: 0 error(s), 12 files scanned)
|
||||
- `pnpm format:check` exits 0 (no Prettier conflict from MD031 blank-line additions)
|
||||
- Gate-can-fail test: appended a bare fence to README.md, confirmed `pnpm md:lint` exits non-zero (1 error), then reverted via `git checkout -- README.md` (NOTE: this reverted the Task 2 README.md fixes; they were re-applied before the Task 2 commit)
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] Prettier reformatted .markdownlint-cli2.jsonc**
|
||||
- **Found during:** Task 2 format:check run
|
||||
- **Issue:** `.markdownlint-cli2.jsonc` created in Task 1 had no trailing commas; Prettier's `trailingComma: "all"` added trailing commas to the JSONC properties and arrays
|
||||
- **Fix:** Ran `pnpm format -- .markdownlint-cli2.jsonc` to apply Prettier's preferred style; verified `pnpm md:lint` still passes after the reformat
|
||||
- **Files modified:** `.markdownlint-cli2.jsonc`
|
||||
- **Commit:** 46bea03 (included in Task 2 commit with the doc fixes)
|
||||
|
||||
**2. [Rule 1 - Bug] gate-can-fail test reverted README.md MD040 fixes**
|
||||
- **Found during:** Task 2 gate verification test
|
||||
- **Issue:** Using `git checkout -- README.md` to revert the test bare fence also reverted the two MD040 fixes previously applied in Task 2 (README.md:78 and :119). The gate-can-fail test used `git checkout -- README.md` for cleanup which is a blanket revert.
|
||||
- **Fix:** Re-read README.md, re-applied both MD040 fixes (`text` language tags at lines 78 and 119), confirmed `pnpm md:lint` exits 0 before committing
|
||||
- **Files modified:** README.md
|
||||
- **Commit:** 46bea03
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — plan goal (markdownlint gate) is fully wired and green.
|
||||
|
||||
## Threat Surface Scan
|
||||
|
||||
No new network endpoints, auth paths, file access patterns, or schema changes introduced. The only surface is the `markdownlint-cli2` devDependency (supply chain) — addressed in the plan's threat model (T-15-01: pinned to exact 0.22.1, package legitimacy audit OK in RESEARCH.md).
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- `.markdownlint-cli2.jsonc` exists at repo root: FOUND
|
||||
- `package.json` contains `md:lint` script and `markdownlint-cli2` devDep: FOUND
|
||||
- `.gitea/workflows/ci.yml` contains `pnpm md:lint` step: FOUND
|
||||
- Commit adb7641 exists: FOUND
|
||||
- Commit 46bea03 exists: FOUND
|
||||
- `pnpm md:lint` exits 0: VERIFIED
|
||||
- `pnpm format:check` exits 0: VERIFIED
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
phase: 15-ci-skip-api-harness-jobs-for-doc-only-prs
|
||||
plan: "02"
|
||||
subsystem: ci
|
||||
tags: [ci, gitea-actions, paths-filter, gate, doc-only-skip]
|
||||
dependency_graph:
|
||||
requires: [15-01]
|
||||
provides: [CI / gate commit-status, doc-only PR skip]
|
||||
affects: [.gitea/workflows/ci.yml]
|
||||
tech_stack:
|
||||
added:
|
||||
- dorny/paths-filter@v4 (Gitea action for PR diff detection)
|
||||
patterns:
|
||||
- changes job with paths-filter
|
||||
- always-running gate aggregate job
|
||||
- Gitea-safe individual needs.X.result checks
|
||||
key_files:
|
||||
modified:
|
||||
- .gitea/workflows/ci.yml
|
||||
decisions:
|
||||
- D-15-02-CHANGES-JOB: dorny/paths-filter@v4 with positive code filter; code==false means doc-only; ambiguous files default to full gate
|
||||
- D-15-02-GATE-INDIVIDUAL: individual needs.X.result checks (not wildcard) due to Gitea 1.26.2 bug #31007
|
||||
- D-15-02-GATE-ALWAYS: if:always() on gate prevents deadlock on skipped upstream jobs (fix in Gitea 1.21.8, instance is 1.26.2)
|
||||
metrics:
|
||||
duration_minutes: 5
|
||||
completed_date: "2026-06-12"
|
||||
tasks_completed: 2
|
||||
tasks_total: 2
|
||||
files_modified: 1
|
||||
---
|
||||
|
||||
# Phase 15 Plan 02: CI doc-only skip + gate aggregate Summary
|
||||
|
||||
**One-liner:** `changes` job (dorny/paths-filter@v4) classifies each PR; `api`/`harness` skip on `code==false`; always-running `gate` job aggregates all results using Gitea-safe individual `needs.X.result` checks, emitting the `CI / gate` status that Plan 03's branch-protection update requires.
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
| Task | Name | Commit | Files |
|
||||
|------|------|--------|-------|
|
||||
| 1 | Add changes job and gate api/harness on code output | 7260438 | .gitea/workflows/ci.yml |
|
||||
| 2 | Add always-running gate aggregate job | 547b12c | .gitea/workflows/ci.yml |
|
||||
|
||||
## What Was Built
|
||||
|
||||
**Task 1 — changes job + conditional api/harness:**
|
||||
|
||||
A new `changes` job using `dorny/paths-filter@v4` was inserted before `fast-checks` in `.gitea/workflows/ci.yml`. It:
|
||||
- Runs on `ubuntu-latest` with `if: github.event_name == 'pull_request'`
|
||||
- Declares `permissions: pull-requests: read` (job-scoped, required by paths-filter v4)
|
||||
- Emits `outputs.code: ${{ steps.filter.outputs.code }}`
|
||||
- Contains a single `uses: dorny/paths-filter@v4` step with `id: filter` and NO `actions/checkout`
|
||||
- Defines a positive `code` filter covering `**/*.ts`, `**/*.tsx`, `**/*.js`, `**/*.json`, `**/*.yaml`, `**/*.yml`, `apps/**`, `packages/**`, `pnpm-lock.yaml`, `Dockerfile`, `docker-compose*.yml`
|
||||
|
||||
The `api` and `harness` jobs were modified:
|
||||
- Added `needs: [changes]`
|
||||
- Changed `if` from `github.event_name == 'pull_request'` to `github.event_name == 'pull_request' && needs.changes.outputs.code == 'true'`
|
||||
- Updated inline comment to say "skipped for doc-only PRs"
|
||||
- All services, env, and step bodies left unchanged
|
||||
|
||||
**Task 2 — gate aggregate job:**
|
||||
|
||||
A new `gate` job was appended at the end of `ci.yml`:
|
||||
- `runs-on: ubuntu-latest`
|
||||
- `needs: [fast-checks, changes, api, harness]`
|
||||
- `if: always()` — ensures the job reports regardless of upstream outcome
|
||||
- One step running a bash script that:
|
||||
1. Fails (exit 1) if `needs.fast-checks.result` is not `success` (fast-checks always runs)
|
||||
2. Iterates over `needs.api.result` and `needs.harness.result`, failing if either is not `success` or `skipped`
|
||||
3. Echoes "Gate passed." otherwise
|
||||
- Uses individual `needs.X.result` references (not `contains(needs.*.result,...)`) due to Gitea 1.26.2 bug #31007
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- **D-15-02-CHANGES-JOB:** Positive `code` filter chosen (not a `docs` exclusion filter) so any new or ambiguous file type defaults to the full gate. A doc-only PR must have every changed file fall outside the code patterns.
|
||||
- **D-15-02-GATE-INDIVIDUAL:** Individual `needs.X.result` checks used instead of `contains(needs.*.result, ...)` wildcard — Gitea 1.26.2 issue #31007 confirms the wildcard returns false even when jobs succeed.
|
||||
- **D-15-02-GATE-ALWAYS:** `if: always()` on the `gate` job prevents deadlock when upstream jobs are skipped. The deadlock bug (Gitea #27906) was fixed in 1.21.8; this instance runs 1.26.2.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Threat Model Coverage
|
||||
|
||||
| Threat | Mitigation | Status |
|
||||
|--------|-----------|--------|
|
||||
| T-15-04: gate passes when fast-checks fails | gate exits 1 on fast-checks != success; skipped accepted only for api/harness | Implemented |
|
||||
| T-15-05: code PR misclassified doc-only | positive code filter — any ambiguous file matches code and runs full gate | Implemented |
|
||||
| T-15-06: supply chain via dorny/paths-filter@v4 | pinned to @v4 tag; pull-requests:read only; no secrets access | Implemented |
|
||||
| T-15-07: required check deadlock | gate uses if:always(); api/harness NOT added as required checks (Plan 03 scope) | Implemented |
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — this plan produces only CI workflow YAML. No runtime state or UI involved.
|
||||
|
||||
## Threat Flags
|
||||
|
||||
None — no new network endpoints, auth paths, file access patterns, or schema changes.
|
||||
|
||||
## Verification
|
||||
|
||||
**Static (pre-merge):**
|
||||
- Python yaml.safe_load parses ci.yml without error
|
||||
- `changes` job present with `dorny/paths-filter@v4`, `id: filter`, `permissions: pull-requests: read`, `outputs.code`
|
||||
- No `actions/checkout` step in `changes` job
|
||||
- `api` and `harness` have `needs: [changes]` and combined `if` with `needs.changes.outputs.code == 'true'`
|
||||
- `gate` job present with `if: always()` and `needs: [fast-checks, changes, api, harness]`
|
||||
- `needs.fast-checks.result`, `needs.api.result`, `needs.harness.result` individually referenced in gate
|
||||
- No `contains(needs.*.result` wildcard in file
|
||||
|
||||
**Behavioral (post-merge, per 15-VALIDATION.md):**
|
||||
- Doc-only PR: `changes` emits `code=false`; `api`/`harness` show skipped; `fast-checks` runs; `gate` passes
|
||||
- Code PR: all three run; `gate` passes when green
|
||||
- Gate-fail path: failing fast-checks causes `gate` to exit 1
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- `.gitea/workflows/ci.yml` modified: EXISTS
|
||||
- Commit 7260438 (Task 1): FOUND
|
||||
- Commit 547b12c (Task 2): FOUND
|
||||
Reference in New Issue
Block a user