Add timeout, busy-state, parser-variant and build-freshness rules
- task-discipline: require explicit target platform/language before implementation - go-api: bounded context deadline on every outbound network/DB call - controls-selection: visible busy state for any control triggering such a call - import-export: enumerate real format variants before writing a parser - app-binary: embedded assets do not hot-reload; verify rebuild before diagnosing Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e092fea98f
commit
59e3107197
@@ -1,6 +1,6 @@
|
|||||||
# Contract: Application Binary
|
# Contract: Application Binary
|
||||||
|
|
||||||
Version: 1.0
|
Version: 1.1
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
@@ -21,4 +21,7 @@ See `README.md` for deployment examples and a sample config template.
|
|||||||
- For local SQLite mode, the database file lives next to the config and its path is derived by the application, not configured separately.
|
- For local SQLite mode, the database file lives next to the config and its path is derived by the application, not configured separately.
|
||||||
- On first run with no config, the application must create the config, print its path, exit 0, and stop. It must not continue startup with a fresh placeholder config.
|
- On first run with no config, the application must create the config, print its path, exit 0, and stop. It must not continue startup with a fresh placeholder config.
|
||||||
- The binary must not depend on the caller's working directory.
|
- The binary must not depend on the caller's working directory.
|
||||||
|
- Assets bundled at compile time (`//go:embed` and equivalents) do not hot-reload. Before diagnosing
|
||||||
|
a bug reported against a generated or served artifact, confirm the running process was rebuilt and
|
||||||
|
restarted after the last change; use the displayed build version (`build-version-display`) to check.
|
||||||
- Build with `CGO_ENABLED=0` when possible. Enable CGO only when the chosen storage/runtime actually requires it, such as SQLite drivers that need CGO.
|
- Build with `CGO_ENABLED=0` when possible. Enable CGO only when the chosen storage/runtime actually requires it, such as SQLite drivers that need CGO.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contract: Controls + Selection
|
# Contract: Controls + Selection
|
||||||
|
|
||||||
Version: 1.2
|
Version: 1.3
|
||||||
|
|
||||||
## Shared Base
|
## Shared Base
|
||||||
|
|
||||||
@@ -16,6 +16,11 @@ Version: 1.2
|
|||||||
- Button text should describe the action outcome, not implementation detail.
|
- Button text should describe the action outcome, not implementation detail.
|
||||||
- Buttons are text-first; icons are optional and must not replace labels on primary/danger actions.
|
- Buttons are text-first; icons are optional and must not replace labels on primary/danger actions.
|
||||||
- Base examples must show both `disabled` and `loading` states.
|
- Base examples must show both `disabled` and `loading` states.
|
||||||
|
- Any control that triggers a network or database call must show a visible busy state for the whole
|
||||||
|
duration of that call (spinner on the control, disabled control, or an equivalent indicator), and
|
||||||
|
must not be re-triggerable while busy. Without it, "slow" is indistinguishable from "broken".
|
||||||
|
- This applies to every call, not only to long-running background tasks. The server-side half of the
|
||||||
|
rule — a bounded timeout on the call itself — is owned by `go-api`.
|
||||||
- Do not use a hyperlink (`<a>`/link-styled text) to open a modal, drawer, detail view, or any
|
- Do not use a hyperlink (`<a>`/link-styled text) to open a modal, drawer, detail view, or any
|
||||||
other in-page element. Use a `button` (or button-styled control) instead, unless the user
|
other in-page element. Use a `button` (or button-styled control) instead, unless the user
|
||||||
explicitly asks for a hyperlink. Hyperlinks are reserved for navigation to another URL/page.
|
explicitly asks for a hyperlink. Hyperlinks are reserved for navigation to another URL/page.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contract: REST API Conventions (Go Web Applications)
|
# Contract: REST API Conventions (Go Web Applications)
|
||||||
|
|
||||||
Version: 1.1
|
Version: 1.2
|
||||||
|
|
||||||
## URL Naming
|
## URL Naming
|
||||||
|
|
||||||
@@ -68,6 +68,16 @@ All non-2xx responses return a consistent JSON body:
|
|||||||
- File uploads use `multipart/form-data`.
|
- File uploads use `multipart/form-data`.
|
||||||
- Query parameters for filtering and pagination: `?page=1&per_page=50&search=abc&status=active`.
|
- Query parameters for filtering and pagination: `?page=1&per_page=50&search=abc&status=active`.
|
||||||
|
|
||||||
|
## Timeouts
|
||||||
|
|
||||||
|
- Every outbound network or database call must run under a bounded `context.Context` deadline.
|
||||||
|
No call reachable from a user action may block indefinitely.
|
||||||
|
- The deadline is set by the handler or service that owns the request, not by the caller of the app.
|
||||||
|
- On timeout, return a real error status (`504` for an upstream timeout, `500` for an internal one)
|
||||||
|
with a human-readable message. Never let a timed-out call fall through as an empty success.
|
||||||
|
- The UI side of the same rule — visible busy state for the duration of the call — is owned by
|
||||||
|
`controls-selection`.
|
||||||
|
|
||||||
## Health and Utility Endpoints
|
## Health and Utility Endpoints
|
||||||
|
|
||||||
Every application must expose:
|
Every application must expose:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contract: Import / Export Workflows
|
# Contract: Import / Export Workflows
|
||||||
|
|
||||||
Version: 1.0
|
Version: 1.1
|
||||||
|
|
||||||
See `README.md` for the reference export handler and locale examples.
|
See `README.md` for the reference export handler and locale examples.
|
||||||
|
|
||||||
@@ -11,6 +11,17 @@ See `README.md` for the reference export handler and locale examples.
|
|||||||
- Warnings and errors should be visible per row and in aggregate.
|
- Warnings and errors should be visible per row and in aggregate.
|
||||||
- The confirm step must communicate scope and side effects clearly.
|
- The confirm step must communicate scope and side effects clearly.
|
||||||
|
|
||||||
|
## Parsing Real-World Formats
|
||||||
|
|
||||||
|
- Before writing a parser for a third-party text export (1C, CSV, vendor reports), enumerate the
|
||||||
|
actual format variants present in a real sample file: delimiters, encodings, decimal and date
|
||||||
|
formats, header repetitions, multi-line and merged records, trailing summary rows.
|
||||||
|
- Write the parser against the enumerated variant list. Do not assume a single convention and repair
|
||||||
|
it reactively per bug report.
|
||||||
|
- Record the enumerated variants next to the parser (test fixtures or a short comment) so later
|
||||||
|
changes know which shapes must keep working.
|
||||||
|
- Unrecognized lines must be reported as explicit per-row errors, never silently skipped.
|
||||||
|
|
||||||
## Export Rules
|
## Export Rules
|
||||||
|
|
||||||
- The user must explicitly choose export scope when ambiguity exists, such as `selected`, `filtered`, or `all`.
|
- The user must explicitly choose export scope when ambiguity exists, such as `selected`, `filtered`, or `all`.
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
# Contract: Task Discipline
|
# Contract: Task Discipline
|
||||||
|
|
||||||
Version: 1.0
|
Version: 1.1
|
||||||
|
|
||||||
## Principle
|
## Principle
|
||||||
|
|
||||||
Finish before switching. A task is not done until it reaches a logical end.
|
Finish before switching. A task is not done until it reaches a logical end.
|
||||||
|
|
||||||
|
## Scope Definition
|
||||||
|
|
||||||
|
- Before implementation starts, the task description must state the target platform and language
|
||||||
|
explicitly: CLI, server-rendered web app, desktop app, library, and the language/runtime it runs on.
|
||||||
|
- If the platform is not stated, ask before writing code. Do not infer it from the surrounding repo.
|
||||||
|
- A platform pivot after implementation invalidates connection, config, and transport plumbing built
|
||||||
|
around the previous shape. Treat such a pivot as a new task, not as a continuation.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Do not start a new task while the current one is unfinished. Switching mid-task leaves half-done work that is harder to recover than if it had never been started.
|
- Do not start a new task while the current one is unfinished. Switching mid-task leaves half-done work that is harder to recover than if it had never been started.
|
||||||
|
|||||||
Reference in New Issue
Block a user