mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
Foreslå regler: task lifecycle governance (BC-opgave, én opgave ad gangen, rød/grøn-gate, versionsløft) + Smiley Task Lifecycle stop gate
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e0906a38a7
commit
c5089370ab
5 changed files with 300 additions and 1 deletions
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
kind: watchdog
|
||||
id: curabis-smiley
|
||||
version: 1
|
||||
version: 2
|
||||
title: Smiley — Session Watchdog
|
||||
description: >
|
||||
Always-active session observer. Shapes Claude's behavior from within.
|
||||
|
|
@ -93,6 +93,47 @@ Ambiguous task detected
|
|||
Smiley will wave the flag hard here. "Hurtig lige" is a red flag.
|
||||
Coding before clarity is the most expensive mistake in development.
|
||||
|
||||
### 🔴 STOP GATE — Task Lifecycle (start, focus, close)
|
||||
|
||||
Enforces the four lifecycle rules: `development-requires-bc-task`,
|
||||
`one-task-in-progress-at-a-time`, `testcase-must-fail-before-implementation`,
|
||||
`release-must-update-app-version`.
|
||||
|
||||
**Start gate — activate when development is about to begin:**
|
||||
- Customer app (`app.json` idRanges within 50000–99999): a BC task MUST exist.
|
||||
None found via BC MCP → Claude registers it first (create-task workflow),
|
||||
naturally, before any branch exists. AppSource app: offer, never block.
|
||||
- Then, in order: feature branch created → BC `gitHubDevStatus = "In Progress"`
|
||||
→ test case written (including missing fields/setup the scenario needs)
|
||||
→ test run red.
|
||||
- **The red result is a human checkpoint.** Claude shows the failing run and
|
||||
waits for the developer to confirm red before writing implementation code.
|
||||
Claude never self-certifies red. This pause is not optional and not undercover —
|
||||
it surfaces as a natural "testen fejler som forventet — bekræft, så bygger jeg."
|
||||
|
||||
**Focus gate — activate when new work arrives mid-task:**
|
||||
- One task in progress at a time. A "hurtigt lige" request while a task is open
|
||||
→ Claude naturally offers the binary choice: finish first, or park (BC
|
||||
`On Hold` + WIP commit). Never a second branch on top of an open task.
|
||||
- Break-fix overrides this gate, as always — a broken build interrupts.
|
||||
|
||||
**Close gate — activate when a task is about to be finished:**
|
||||
- Test case green (actually run, not assumed) → merge to the declared track
|
||||
branch → BC `Done`. Red test = the task cannot close, no exceptions.
|
||||
- At release (track branch → main, tag, AppSource submission): app.json
|
||||
version consciously bumped before the merge.
|
||||
|
||||
**The chain:**
|
||||
```
|
||||
Task requested
|
||||
→ BC task exists? (mandatory 50000–99999, optional AppSource)
|
||||
→ branch + BC "In Progress"
|
||||
→ test case written → RED confirmed by developer
|
||||
→ implementation
|
||||
→ test GREEN → merge to track branch → BC "Done"
|
||||
→ at release: version bump
|
||||
```
|
||||
|
||||
### ⚡ BREAK-FIX — al-triage
|
||||
|
||||
**Activate when:**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [bc-task, task-registration, customer-app, pte, appsource, lifecycle, before-development]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Development requires a registered BC task
|
||||
|
||||
## Description
|
||||
|
||||
Development work on a **customer app** must not begin until the task is
|
||||
registered in Business Central. The enforcement point is branch creation:
|
||||
before a feature branch is created, the BC task must exist and be resolvable
|
||||
via BC MCP.
|
||||
|
||||
Whether an app is a customer app is decided by its object ID ranges in
|
||||
`app.json`:
|
||||
|
||||
| `idRanges` in app.json | App type | BC task |
|
||||
|---|---|---|
|
||||
| Within 50000–99999 | Customer app (PTE) | **Mandatory** before development |
|
||||
| Outside 50000–99999 (e.g. 100000+) | AppSource app | Recommended, optional |
|
||||
|
||||
## Why
|
||||
|
||||
Customer-app work is billable, customer-facing work. A task that exists only
|
||||
in a chat conversation or a developer's head cannot be traced, invoiced, or
|
||||
picked up by anyone else. Registering the task in BC *before* development —
|
||||
not after — is what makes the rest of the lifecycle chain work: branch naming,
|
||||
dev-status sync, and commit traceability all key off the BC task.
|
||||
|
||||
For AppSource apps the work is product investment, not customer billing, so
|
||||
the task is optional — but the same chain applies whenever a task exists.
|
||||
|
||||
## Decision point
|
||||
|
||||
Before `git checkout -b feature/...` on a customer app:
|
||||
|
||||
1. Resolve the task via BC MCP (see `[[bc-mcp-find-active-task-for-branch]]`)
|
||||
2. No task found → create it first (see bc-mcp.agent.md create-task workflow)
|
||||
or have the project manager register it
|
||||
3. Only then create the branch, named after the task, and sync status
|
||||
(see `[[git-lifecycle-must-sync-bc-status]]`)
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
# Customer app, idRanges 50000..99999
|
||||
git checkout -b feature/quick-price-fix # no BC task exists
|
||||
# ...development starts, task registered "later" (= never, or wrong)
|
||||
|
||||
## Best Practice
|
||||
|
||||
# 1. BC MCP: task exists (or is created) → taskNo 004 on DEV2023-00027
|
||||
# 2. Branch keyed to the task:
|
||||
git checkout -b feature/DEV2023-00027-004-price-lookup
|
||||
# 3. BC: gitHubDevStatus = "In Progress"
|
||||
# 4. Commits prefixed [#taskId] (see commit-message-must-include-bc-task-id)
|
||||
|
||||
## Scope
|
||||
|
||||
All CURABIS repositories. Mandatory for apps whose `app.json` idRanges lie
|
||||
within 50000–99999; optional but recommended for AppSource-range apps. Related:
|
||||
`[[commit-message-must-include-bc-task-id]]`, `[[one-task-in-progress-at-a-time]]`.
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [one-task, focus, wip-limit, lifecycle, branch, in-progress, park]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# One task in progress at a time
|
||||
|
||||
## Description
|
||||
|
||||
A developer — and a Claude session — works on **at most one task per
|
||||
repository at a time**. Starting a task is an atomic sequence; nothing else
|
||||
starts until the task is finished or explicitly parked.
|
||||
|
||||
**Starting a task means, in order:**
|
||||
|
||||
1. Feature branch created in VS Code (named per the convention in
|
||||
`[[git-lifecycle-must-sync-bc-status]]`)
|
||||
2. BC subtask updated: `gitHubDevStatus = "In Progress"` (when a BC task
|
||||
exists — see `[[development-requires-bc-task]]`)
|
||||
3. Test case created and confirmed red
|
||||
(see `[[testcase-must-fail-before-implementation]]`)
|
||||
4. Implementation begins
|
||||
|
||||
**Finishing a task means:** test case green, feature branch merged to the
|
||||
declared track branch (see `[[feature-branch-must-merge-to-track-branch]]`),
|
||||
BC status `Done`.
|
||||
|
||||
## Why
|
||||
|
||||
Half-finished work is the most expensive inventory a codebase carries. Two
|
||||
open tasks means two branches drifting, two test cases in unknown state, and
|
||||
a merge conflict being cultivated. The WIP limit of one is what makes the
|
||||
red→green gate meaningful: at any moment, the repo's state answers the
|
||||
question "what are we building right now?" with exactly one answer.
|
||||
|
||||
## When new work arrives mid-task
|
||||
|
||||
"Hurtigt lige..." is the anti-pattern. The choice is binary:
|
||||
|
||||
| Option | Action |
|
||||
|---|---|
|
||||
| Finish first | Complete the current task to green + merged, then start the new one |
|
||||
| Park | BC status `On Hold`, commit or stash work-in-progress, then start the new one |
|
||||
|
||||
What is never allowed: starting the new work on top of the open task's branch,
|
||||
or leaving the open task in `In Progress` while working on something else.
|
||||
|
||||
**Exception — break-fix:** a production error or broken build interrupts
|
||||
immediately and does not count as a second task. Fix, then return.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
# Task A in progress, test still red
|
||||
# "Hurtigt lige" request arrives:
|
||||
git checkout -b feature/task-b # Task A abandoned in limbo
|
||||
# BC still says Task A "In Progress" — now a lie
|
||||
|
||||
## Best Practice
|
||||
|
||||
# Park Task A explicitly:
|
||||
# BC: Task A gitHubDevStatus = "On Hold"
|
||||
git add -A && git commit -m "[#8738] WIP: parked for urgent task B"
|
||||
git checkout main && git checkout -b feature/DEV2023-00027-005-task-b
|
||||
# BC: Task B gitHubDevStatus = "In Progress"
|
||||
|
||||
## Scope
|
||||
|
||||
All CURABIS repositories — customer apps and AppSource apps alike.
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [version, release, app-json, semver, al-go, appsource]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Release must update the app version
|
||||
|
||||
## Description
|
||||
|
||||
At every release, the app's version is consciously updated. A release is any
|
||||
of: track branch merged to `main`, a tagged release build, or an AppSource
|
||||
submission.
|
||||
|
||||
| Version part | Owner | When |
|
||||
|---|---|---|
|
||||
| Major | Developer decision | Breaking change (schema, API, removed objects) |
|
||||
| Minor | Developer decision | Every release with new functionality |
|
||||
| Build / Revision | AL-Go pipeline | Automatic — never hand-edited |
|
||||
|
||||
The decision point is the release itself: before the track branch merges to
|
||||
`main` (see `[[feature-branch-must-merge-to-track-branch]]`), the
|
||||
`version` in `app.json` (and `repoVersion` in AL-Go settings, where used)
|
||||
reflects the new release — not the previous one.
|
||||
|
||||
## Why
|
||||
|
||||
The version number is the only identity a deployed app has. Two customer
|
||||
environments running "the same" version with different code is an
|
||||
undiagnosable support case; an AppSource submission with an unchanged
|
||||
major.minor is a rejected submission. AL-Go increments build numbers on every
|
||||
CI run, which creates the illusion that versioning is handled — but
|
||||
major.minor is a **human statement about compatibility**, and no pipeline can
|
||||
make it.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
# Track branch "purchase" merged to main and released.
|
||||
# app.json still says "version": "1.2.0.0" — same as the previous release.
|
||||
# Two different code states now share one version identity.
|
||||
|
||||
## Best Practice
|
||||
|
||||
# Before the release merge:
|
||||
# app.json: "version": "1.3.0.0" (new functionality → minor bump)
|
||||
# AL-Go settings: "repoVersion": "1.3" (where used)
|
||||
# Then: track branch → main via PR, tag, release.
|
||||
|
||||
## Scope
|
||||
|
||||
All CURABIS apps — customer apps and AppSource apps alike. Enforced at the
|
||||
release gate, not per feature branch: feature branches never touch the
|
||||
version; only the release does.
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: testing
|
||||
keywords: [tdd, red-green, test-first, testcase, verification, human-checkpoint, lifecycle]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Test case must fail before implementation begins
|
||||
|
||||
## Description
|
||||
|
||||
Every task starts with a test case, and the test case must **demonstrably
|
||||
fail (red)** — verified by the developer, not self-certified by the AI —
|
||||
before implementation begins. The task may only be completed when the same
|
||||
test case **passes (green)**.
|
||||
|
||||
The lifecycle gate, in order:
|
||||
|
||||
1. Task started (branch + BC status — see `[[one-task-in-progress-at-a-time]]`)
|
||||
2. Test case written for the requirement — including any fields, setup
|
||||
objects, or test data structures the scenario needs that do not yet exist
|
||||
3. Test is run; **the developer verifies the red result** — an AI session
|
||||
must never assert "the test fails" without a run the developer has seen
|
||||
4. Implementation begins
|
||||
5. Test is run again; **green is a precondition for finishing the task** —
|
||||
no merge to the track branch, no BC `Done`, while the test case is red
|
||||
|
||||
## Why
|
||||
|
||||
A test written after the code proves only that the code does what the code
|
||||
does. A test that was red first proves two separate things: that the test
|
||||
actually exercises the requirement (red = the gap is real), and later that
|
||||
the requirement is met (green = the gap is closed). The human verification
|
||||
of red is the cheap insurance: thirty seconds of looking at a failing test
|
||||
catches the test that accidentally passes vacuously — the most dangerous
|
||||
test in any suite.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
// Implementation written first, test added afterwards to "cover" it.
|
||||
// Test passes on first run — it has never been observed red.
|
||||
// Nobody knows whether it tests the requirement or just the code.
|
||||
|
||||
## Best Practice
|
||||
|
||||
// [GIVEN] a customer with a tier-price agreement
|
||||
// [WHEN] FindPrice is called for quantity 100 (test-one-when-per-test)
|
||||
// [THEN] the tier price is returned, not the unit price
|
||||
//
|
||||
// Run 1 (before implementation): FAILS — developer confirms red ✓
|
||||
// ... implementation ...
|
||||
// Run 2: PASSES — task may now be completed ✓
|
||||
|
||||
Test structure follows the existing testing rules:
|
||||
`[[test-one-when-per-test]]`, `[[test-setup-must-use-library-codeunit]]`,
|
||||
`[[test-data-must-be-random-and-complete]]`, `[[test-feature-scenario-tags]]`.
|
||||
|
||||
## Scope
|
||||
|
||||
All CURABIS repositories — customer apps and AppSource apps alike. Applies to
|
||||
every task that changes behavior. Pure refactorings keep existing tests green
|
||||
throughout; documentation/translation tasks are exempt.
|
||||
Loading…
Add table
Add a link
Reference in a new issue