From ab3996dde9d4cfb5884ffdead0f200f9509f934d Mon Sep 17 00:00:00 2001 From: Remon Panman <228601219+Tradebaas@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:29:29 +0200 Subject: [PATCH 1/2] docs(decisions): rule 1 is a work-in-progress limit, not a fixed queue "One epic in flight at a time. A project may hold several; they run one after the other" stalled an agent on 2026-08-25. Asked to bring a quality-floor epic forward past six unstarted features of the epic in flight, it read the second sentence as an order fixed at cutting time and came back asking permission to bend the rule, rather than doing the thing the method is for. The owner's answer is that a queue is not sacred when there is a reason to change it, and that reordering on new information is Agile rather than a breach of it. So the rule says what it means: the binding half is the work-in-progress limit, and which epic runs next may change whenever there is a reason. What the limit forbids is two epics open at once, which makes a reorder an explicit park of the epic in flight, written on its card with the reason, rather than a second epic quietly started beside the first. Nothing else in the record changes, and no rule is added: the clarification sits under rule 1 in the same in-place amendment form the record already uses twice. Traces-to: SC-2 --- ...-with-one-vocabulary-and-the-folder-tree-as-hierarchy.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/decisions/0021-agile-first-with-one-vocabulary-and-the-folder-tree-as-hierarchy.md b/docs/decisions/0021-agile-first-with-one-vocabulary-and-the-folder-tree-as-hierarchy.md index d14ba74..b62351d 100644 --- a/docs/decisions/0021-agile-first-with-one-vocabulary-and-the-folder-tree-as-hierarchy.md +++ b/docs/decisions/0021-agile-first-with-one-vocabulary-and-the-folder-tree-as-hierarchy.md @@ -116,6 +116,12 @@ its own. ### Seven rules, and no more 1. One epic in flight at a time. A project may hold several; they run one after the other. + Clarified 2026-08-25 by the owner, after this sentence stalled an agent that read it as a queue + fixed at cutting time: it is a work-in-progress limit, not a fixed order. Which epic runs next + may change whenever there is a reason, because reordering on new information is the method, not + a breach of it. What the limit forbids is two epics open at once, so a reorder is an explicit + park of the one in flight, written on its card with the reason, never a second epic quietly + started beside the first. 2. A feature delivers value on its own and names in one line which choice in the vision it serves. 3. A story lives in exactly one feature folder. 4. Ready: a value sentence, testable criteria, its tasks, a size, its dependencies, and the owner's From e2a4500a24d395c29c271fc522edce799c751605 Mon Sep 17 00:00:00 2001 From: Remon Panman <228601219+Tradebaas@users.noreply.github.com> Date: Wed, 26 Aug 2026 09:07:25 +0200 Subject: [PATCH 2/2] feat(standards): six risk classes a stack answers, in the file that already carries its craft SC-5 promises a floor that holds without the builder having to know the rules, and nothing holds it: measured on a fresh copy, a file with SQL injection, a swallowed failure in a payment path, dead code and a dependency with known holes passes every gate. The gates prove documents, names, prose and traceability; four of the twenty-one touch code, all of them hygiene. This is the first half of closing that: a shape for the answer. The gate that reads it is the next story. Six classes of risk, not a list of tools: builds, behaves, analyzed, dependencies, secrets, renders. A contract naming tsc and eslint would be a code-stack assumption, and half the projects this framework serves have neither. A class is a question every product has to answer; the answer is what differs. Three answer forms and no fourth: a command, a reasoned "not applicable", or a named "manual" check with a defer: marker. The last of those is not new. The stack skill's platform route already says a gate with no platform equivalent becomes a named manual check and a defer: entry, never a silent drop. This is the first place that gives it a form rather than an instruction. Filled twice, on two stacks that share no tooling, from primary sources read today. Building the Power Platform column changed the contract twice, which is what worked examples are for. On a hosted platform the thing CI runs is a pipeline task, not a shell line, so the command form now says "a shell line, or this host's own task" rather than pushing every platform project into manual. And two claims that came from search summaries rather than the vendor's own page were cut: Microsoft Learn gives no removal date for the deprecated Test Engine repository, and does not carry the CLI form of the checker, so the two Azure DevOps task names it does give are what the table names. The stack skill loses the gate list it used to spell out in section 3. That list is the floor table now, and a skill restating it would be the same fact in two places, drifting apart the moment one is edited. Section 2 points at the template as the shape it writes from; section 3 points at the filled table as the thing its wiring has to satisfy. No new manifest row: standards/*.md is a pattern row and already covers this file. Measured rather than assumed, by dropping an unlisted file into that folder and watching docs-manifest stay quiet. What was wrong was the row's description, which called everything there per-stack and generated; the template is neither. Traces-to: SC-5 --- .agents/skills/stack/SKILL.md | 21 +++++++----- docs/README.md | 2 +- docs/standards/TEMPLATE-STACK.md | 58 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 docs/standards/TEMPLATE-STACK.md diff --git a/.agents/skills/stack/SKILL.md b/.agents/skills/stack/SKILL.md index 066e7bf..fc6c261 100644 --- a/.agents/skills/stack/SKILL.md +++ b/.agents/skills/stack/SKILL.md @@ -26,6 +26,11 @@ authoritative sources (official docs, release pages). Model memory is a rumor wi ## 2. Generate `docs/standards/.md` +Start from `docs/standards/TEMPLATE-STACK.md`, which owns the shape. Its floor table is the part +`checks/check.mjs` reads: six classes of risk, each answered with a command, a reasoned +`not applicable`, or a named `manual` check with a `defer:` marker. Fill that table as you +research, because it is what step 3 has to satisfy. + Research what a top engineer in *this* ecosystem does **today**, from primary sources, and write it down with versions, dates, and source links. @@ -56,15 +61,15 @@ cover at least: ## 3. Scaffold and wire the gates - Scaffold the conventional project structure (official generator where one exists). -- Wire the gate chain so it runs the same everywhere: - - **pre-commit** (`checks/hooks/pre-commit`, versioned): append fast checks (format, lint +- Wire the gate chain so it runs the same everywhere. **What has to be covered is the floor table + you filled in step 2**, not a list repeated here: every class answered, and every `command` + answer running as a live stage. An SBOM of at least top-level dependencies is the CRA legal + floor, so `dependencies` is answered with one where the stack has any. + - **pre-commit** (`checks/hooks/pre-commit`, versioned): append the fast half (format, lint staged) after the Groundwork line. Cheap first. - - **CI** (`.github/workflows/ci.yml`, or this host's equivalent): the full authority: - checks, typecheck, lint, tests, build, secret scan. Replace the placeholder stage; - CI must fail on any gate. - - **Supply-chain floor**, as soon as the stack has dependencies: an SBOM (software bill of - materials) of at least top-level dependencies - the CRA legal floor - plus dependency - audit and license scan, all wired into CI with this ecosystem's current tools. + - **CI** (`.github/workflows/ci.yml`, or this host's equivalent): the full authority. Replace + the placeholder stage; CI must fail on any gate. Deleting a placeholder without wiring what it + stood for leaves the class unanswered, and the floor table is where that shows. - **Design detector**, when the product has a user interface: a CI stage that runs the design method's own detector over the surfaces this project ships, beside the typecheck and the tests. It is deterministic, model-free and needs no key, so it belongs with the mechanical diff --git a/docs/README.md b/docs/README.md index 0733e92..84a60d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,7 +29,7 @@ domain, updated when the domain changes; **ARCHIVE** = frozen, never cite as cur | `decisions/TEMPLATE.md` | REF | Decision record skeleton | | `decisions/[0-9]*.md` ◆ | REF | Decision records, numbered (Groundwork's own ship with the framework) | | `standards/GLOBAL.md` | REF | Universal code standards, stack-independent | -| `standards/*.md` ◆ | REF | Per-stack standards, generated by the `stack` skill | +| `standards/*.md` ◆ | REF | The stack template with the floor table, and the per-stack standards the `stack` skill generates from it | | `design/reference/**` ◆ | REF | Brand assets, screenshots, design references | | `design/VOICE.md` | REF | Voice & content system: how the product reads | | `compliance/REGISTER.md` | LIVE | This project's register: which regimes apply, status and evidence per obligation | diff --git a/docs/standards/TEMPLATE-STACK.md b/docs/standards/TEMPLATE-STACK.md new file mode 100644 index 0000000..89da8ff --- /dev/null +++ b/docs/standards/TEMPLATE-STACK.md @@ -0,0 +1,58 @@ +# TEMPLATE: `` standards + + + +## The floor + +Six classes of risk. Every product carries all six; what changes per stack is the answer, never the +list. **Each row is answered or the gates do not read green.** + +| Class | The risk it covers | Form | Answer | +|---|---|---|---| +| `builds` | It does not assemble or deploy, and finds out in production | | | +| `behaves` | It does not do what it claims, and nothing says so before a user does | | | +| `analyzed` | Defects a machine can see are shipped because no machine looked | | | +| `dependencies` | Third-party code arrives with known holes, unknown licences, or unrecorded | | | +| `secrets` | Keys, tokens and passwords ship inside the product | | | +| `renders` | What a person actually sees is broken, unreadable or unusable | | | + +Three answer forms, and no fourth: + +- **command** - what CI runs: a shell line, or this host's own task. It has to exist as a live + stage in a workflow, never as a comment. +- **`not applicable`** - plus the reason. Use it when the class genuinely cannot apply here, never + when it is merely inconvenient. +- **`manual`** - plus the named check and who runs it, and a `defer:` marker at the site. This is + what the `stack` skill's platform route already requires of a gate with no platform equivalent: + a named manual check, never a silent drop. + +A waived class is reported on the board and on the enforcement line, with its reason. That is the +point of the form: a floor with holes in it is allowed, and is never quiet about them. + +## Worked answers + + + +| Class | TypeScript on Node | Microsoft Power Platform | +|---|---|---| +| `builds` | **command** `npm run build` | **command** the `PowerPlatformPackSolution@2` task, then the import task | +| `behaves` | **command** `npm test` | **manual** - Test Engine was deprecated effective April 2026 and Microsoft points at the Power Platform Playwright samples instead. A project that has not adopted them yet answers `manual` with the named regression script and a `defer:` marker, rather than claiming a runner it does not have | +| `analyzed` | **command** `tsc --noEmit` and `eslint .` | **command** the `PowerPlatformChecker@2` task - static analysis against Microsoft's rule set, emitting SARIF | +| `dependencies` | **command** `npm audit --audit-level=high` and `npm sbom --sbom-format=cyclonedx` | **not applicable** - a solution declares dependencies on other solutions and connectors, and no vulnerability feed exists for those. Connector governance through DLP policies is the control instead, and it is a policy, not a build step | +| `secrets` | Groundwork's own gate, with this stack's file extensions added to `extraCodeExtensions` in `checks/config.json` | Groundwork's own gate over the unpacked solution, with environment variables and Key Vault references as the pattern that replaces embedded values | +| `renders` | **command** `npx -y impeccable@latest detect ` | **manual** - the accessibility checker in the studio, run per app before release, with a `defer:` marker naming it | + +Sources, read 2026-08-26, primary only: `npm sbom` and its `cyclonedx` format from the npm CLI +docs (docs.npmjs.com/cli/v11/commands/npm-sbom); the Test Engine deprecation, effective April 2026, +and the Playwright samples that replace it from Microsoft Learn's "Important changes (deprecations) +coming in Power Platform"; the two task names from Microsoft Learn's Power Platform Build Tools +task reference, itself updated 2026-08-19. Re-read them before copying: this table is dated +evidence, not a standing recommendation, and the tooling in it moves faster than this file does. + +## + +