@starci/hfs 4.7.45 → 4.7.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/lint/run.mjs +1 -1
- package/package.json +1 -1
- package/release/candidate-ci.mjs +7 -7
- package/release/push.mjs +3 -3
- package/runtime/config.example.yaml +9 -10
- package/runtime/engine/config.mjs +3 -3
- package/runtime/engine/release-config.mjs +5 -5
- package/runtime/knowledge/grammars/offset-pop/playbook.yaml +1 -1
- package/runtime/knowledge/grammars/starci/playbook.yaml +16 -2
- package/runtime/knowledge/hfs/canon-pins.yaml +7 -7
- package/runtime/knowledge/hfs/ci-standard.yaml +1 -1
- package/runtime/knowledge/hfs/rules.yaml +36 -5
- package/runtime/knowledge/patterns/be/realtime.yaml +1 -0
- package/runtime/modules/kernel/command-policy.yaml +5 -5
- package/runtime/modules/kernel/failure-codes.yaml +32 -20
- package/runtime/modules/kernel/removed-vocabulary.yaml +33 -7
- package/runtime/packages/cli/src/catalog.generated.mjs +90 -37
- package/runtime/scripts/guards/command-policy.mjs +4 -4
- package/runtime/scripts/guards/push-scan.mjs +128 -0
- package/runtime/scripts/guards/release-push-gate.mjs +31 -29
- package/runtime/scripts/hfs/example-secrets.mjs +4 -4
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +5 -5
- package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +61 -0
- package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +4 -6
- package/runtime/scripts/lib/release-version.mjs +134 -134
- package/runtime/scripts/machine/home.mjs +2 -2
- package/stack/render.mjs +3 -1
- package/templates/app/ci-workflows/github/workflows/ci.yml +2 -2
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +2 -2
- package/templates/app/hooks/husky/pre-push +3 -56
- package/release/supabase-bucket.mjs +0 -8
- package/runtime/scripts/api/fs/write-json-file.mjs +0 -10
- package/runtime/scripts/api/git/merge-base-query.mjs +0 -5
- package/runtime/scripts/gates/commit-proof.mjs +0 -53
- package/runtime/scripts/guards/release-definition.mjs +0 -204
- package/runtime/scripts/guards/release-record.mjs +0 -58
- package/runtime/scripts/guards/release-suite-mode.mjs +0 -15
- package/runtime/scripts/hfs/runtime-rules/release-notes.mjs +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.7.47 - 2026-10-27
|
|
4
|
+
|
|
5
|
+
- Fixed: the rendered stack escapes every literal dollar once more, so a secret-reading command or healthcheck survives the second interpolation of docker stack deploy.
|
|
6
|
+
|
|
7
|
+
## 4.7.46 - 2026-10-26
|
|
8
|
+
|
|
9
|
+
- Changed: owner ruling push-main-after-scoped-check reaches product apps: the generated pre-push hook passes a fast-forward main push when the hooks pass and the secret scan is clean, a v* tag must be annotated, and app CI runs on pushes to main.
|
|
10
|
+
- Changed: candidate-ci keeps only catalogued failure codes.
|
|
11
|
+
|
|
3
12
|
## 4.7.45 - 2026-10-26
|
|
4
13
|
|
|
5
14
|
- Changed: the alpha.31.1 round folded into alpha.31; the bundled canon pins and runtime copies follow the final package versions. No rule changes.
|
package/lint/run.mjs
CHANGED
|
@@ -191,7 +191,7 @@ function exportsTarget(entry) {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
/** The import entry of a package found by the app's own node_modules lookup (the folders require.resolve.paths lists from cwd). */
|
|
194
|
-
|
|
194
|
+
function importEntry(require, packageName) {
|
|
195
195
|
for (const dir of require.resolve.paths(packageName) ?? []) {
|
|
196
196
|
const manifest = path.join(dir, packageName, 'package.json');
|
|
197
197
|
if (!fs.existsSync(manifest)) continue;
|
package/package.json
CHANGED
package/release/candidate-ci.mjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// red, with the owner confirming afterwards"). The push sends the exact release sha to refs/heads/release/candidate-<version> first (the managed ci.yml triggers on
|
|
3
3
|
// release/candidate-*), waits for the ci.yml run of THAT sha, and moves the default branch and the tag only when it is green:
|
|
4
4
|
// green the newest non-cancelled run of the sha concluded success and none of its jobs was skipped
|
|
5
|
-
// red
|
|
6
|
-
// timeout
|
|
7
|
-
// unknown
|
|
5
|
+
// red "candidate CI red" (a run or a job that concluded skipped is red, never a pass: owner ruling 2026-10-22, a skip is a loosening) with the run URL and the failing jobs and steps; nothing reaches the default branch. The candidate ref stays for diagnosis
|
|
6
|
+
// timeout "candidate CI timeout": no run listed within the grace (a queued run is listed), or it did not end within the wait
|
|
7
|
+
// unknown candidate CI unknown: GitHub could not be read to the end; a release never proceeds blind
|
|
8
8
|
// There is no override: a red candidate never passes (owner ruling 2026-10-22: a loosening is always red).
|
|
9
9
|
// Every process goes through ctx.spawn (git, gh); the wait through ctx.sleep and ctx.now.
|
|
10
10
|
|
|
@@ -95,9 +95,9 @@ export async function candidateStep(ctx, { head, tag, prefix, remote, wait = CAN
|
|
|
95
95
|
if (seen.state === 'red') {
|
|
96
96
|
const failing = failingJobs(ctx, seen.run);
|
|
97
97
|
const detail = failing.length ? failing.join('; ') : 'the failing jobs could not be read';
|
|
98
|
-
return { ok: false, lines: [...lines, `
|
|
98
|
+
return { ok: false, lines: [...lines, `candidate CI red: the ci.yml run of ${head.slice(0, 10)} on ${ref} is red${url}; failing: ${detail}. Nothing reached the default branch; the candidate ref stays for diagnosis`], data: { ref, state: 'red', run: seen.run, failing } };
|
|
99
99
|
}
|
|
100
|
-
if (seen.state === 'unstarted') return { ok: false, lines: [...lines, `
|
|
101
|
-
if (seen.state === 'timeout') return { ok: false, lines: [...lines, `
|
|
102
|
-
return { ok: false, lines: [...lines, `
|
|
100
|
+
if (seen.state === 'unstarted') return { ok: false, lines: [...lines, `candidate CI timeout: no ci.yml run started for ${head.slice(0, 10)} on ${ref} within ${wait.graceMinutes} minutes (does .github/workflows/ci.yml trigger on release/candidate-*? run starci app sync)`], data: { ref, state: 'unstarted' } };
|
|
101
|
+
if (seen.state === 'timeout') return { ok: false, lines: [...lines, `candidate CI timeout: the ci.yml run of ${head.slice(0, 10)} did not end within ${wait.waitMinutes} minutes${url}`], data: { ref, state: 'timeout', run: seen.run } };
|
|
102
|
+
return { ok: false, lines: [...lines, `candidate CI unknown: GitHub could not be read for the candidate ${head.slice(0, 10)} on ${ref}; a release never proceeds blind`], data: { ref, state: 'unknown' } };
|
|
103
103
|
}
|
package/release/push.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// push.mjs - `starci app release push`: sends the default branch and the release tag to the remote in ONE atomic push through the repository's own
|
|
2
|
-
// pre-push hook (never --no-verify).
|
|
2
|
+
// pre-push hook (never --no-verify). The explicit release command requires an annotated release tag on HEAD and the L4 record of the gate for that
|
|
3
3
|
// head and tag. `git push --dry-run --atomic` always runs first (the hook's verdict is the proof) and any failure refuses the push.
|
|
4
4
|
// With --execute the exact sha first goes to its candidate ref refs/heads/release/candidate-<version> and the push waits for the ci.yml run of that sha
|
|
5
|
-
// (candidate-ci.mjs, OWNER RULING candidate-ci 2026-10-18): only a green candidate
|
|
5
|
+
// (candidate-ci.mjs, OWNER RULING candidate-ci 2026-10-18): only a green candidate moves the branch and the tag.
|
|
6
6
|
// That wait runs only for an app that sets release.requireCi: true; the default false (owner ruling release-require-ci-per-project) pushes after the
|
|
7
7
|
// local gate and the dry run alone and says so. The tag, the L4 record and the dry run are never skipped.
|
|
8
8
|
import fs from 'node:fs';
|
|
@@ -21,7 +21,7 @@ function readRecord(file) {
|
|
|
21
21
|
const greenRecord = (record, head, tag) => record?.head === head && record?.tag === tag
|
|
22
22
|
&& Array.isArray(record.gates) && record.gates.length > 0 && record.gates.every((gate) => gate?.pass === true);
|
|
23
23
|
|
|
24
|
-
/** The release gate
|
|
24
|
+
/** The explicit release command gate: the annotated tag on HEAD whose L4 record names head and tag. Returns { tag } or { reason }. */
|
|
25
25
|
function gateState(ctx, head, prefix, expected) {
|
|
26
26
|
const tags = annotatedOnHead(ctx, prefix);
|
|
27
27
|
if (!tags.includes(expected)) return { reason: `no ANNOTATED tag ${expected} (the package.json version) on HEAD${tags.length > 0 ? `, which carries ${tags.join(', ')}` : ''}: run starci app release gate --execute first` };
|
|
@@ -38,8 +38,9 @@ parallel: {gear: 1}
|
|
|
38
38
|
# kernel (docs/supervisor.md) also takes, optional, defaults in home.mjs DEFAULTS:
|
|
39
39
|
# kernel: {agent, model, effort} its agent pin (default: the kernel pin below)
|
|
40
40
|
# workers: {base, max} the adaptive [Worker] cap, 0 to 10 (0 = the Supervisor runs no fix worker)
|
|
41
|
-
# landGate: {mode: shared}
|
|
42
|
-
# fast-forwards LOCAL main
|
|
41
|
+
# landGate: {mode: shared, push: true} shared lets running lanes commit directly; exclusive = gate only. A land
|
|
42
|
+
# fast-forwards LOCAL main; main reaches the remote right after a green scoped check through
|
|
43
|
+
# `starci release push` (push: true, the default; false locks the remote). CI is the critic.
|
|
43
44
|
supervisor:
|
|
44
45
|
# mode: chat (default) - the owner's desktop chat session is the Supervisor: it owns channel 'main'
|
|
45
46
|
# and reads Decision Items; nothing starts a [Supervisor] kernel. kernel - the optional [Supervisor]
|
|
@@ -49,7 +50,7 @@ supervisor:
|
|
|
49
50
|
pollIntervalMs: null
|
|
50
51
|
repos: []
|
|
51
52
|
# frozenMinutes: <n> # Host seat check: a busy frame unchanged this long is frozen, not busy
|
|
52
|
-
# landGate: {mode: shared|exclusive}
|
|
53
|
+
# landGate: {mode: shared|exclusive, push: true|false}
|
|
53
54
|
# delegation — while the owner is away, a named delegate (e.g. the supervisor chat) may
|
|
54
55
|
# answer owner asks until the given time; excluded classes stay owner-only. null = none.
|
|
55
56
|
# delegation: {asks: supervisor, until: 2026-09-23T09:00:00+07:00,
|
|
@@ -185,11 +186,9 @@ sonar: {organization: null}
|
|
|
185
186
|
# minFreeRamPct free-RAM percentage below which no new heavy op starts
|
|
186
187
|
# set them only in the gitignored config.yaml copy, e.g.
|
|
187
188
|
# resources: {minFreeDiskGb: 5, minFreeDiskPct: 1, minFreeRamPct: 10}
|
|
188
|
-
# release - where the
|
|
189
|
-
# suite: local the shipped default: `starci release cut` runs the
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
# A release can reach GitHub and its tag before the Linux parity has run; a red CI is fixed forward with the next pre-release (starci release ci-status).
|
|
194
|
-
# "none" is refused: the Linux parity does not vanish, it moves to CI. Set it only in the gitignored config.yaml copy: release: {suite: ci}
|
|
189
|
+
# release - where the full suite of a release is judged (scripts/guards/release-suite-mode.mjs; docs/releasing.md "Where the suite runs"). One key:
|
|
190
|
+
# suite: local the shipped default: `starci release cut` also runs the L4 rows on this host (root rows, example apps, Sonar proofs, Linux parity container) before it tags; it never gates a push
|
|
191
|
+
# suite: ci the owner's recorded choice (2026-10-09, widened 2026-10-26 by push-main-after-scoped-check): EVERY row is judged by the GitHub workflows (ci, examples, sonar) on each push to main;
|
|
192
|
+
# the cut runs none and lists each row as delegated, never green. A red CI opens the next alpha.N.M and never blocks the next push (starci release ci-status).
|
|
193
|
+
# "none" is refused: the suite does not vanish, it moves to CI. Set it only in the gitignored config.yaml copy: release: {suite: ci}
|
|
195
194
|
release: {suite: local}
|
|
@@ -294,13 +294,13 @@ const validateSupervisorBlock=(supervisor,profile)=>{
|
|
|
294
294
|
throw new Error('Invalid config.yaml: supervisor.mode must be chat or kernel, or null.');
|
|
295
295
|
// The [Supervisor] kernel seat (scripts/machine/home.mjs supervisorSettings): kernel {agent?, model?, effort?}
|
|
296
296
|
// pins its agent (default: the kernel pin), workers {base?, max?} its adaptive [Worker] cap (0 to 10; the shipped default is 0 fix workers),
|
|
297
|
-
// landGate {mode?: shared|exclusive} the land gate (scripts/supervisor/land.mjs).
|
|
297
|
+
// landGate {mode?: shared|exclusive, push?: boolean} the land gate (scripts/supervisor/land.mjs); push (default true, owner ruling push-main-after-scoped-check) lets `starci release push` send main to the remote after a green scoped check, false is the owner's lock on the remote.
|
|
298
298
|
const seat=supervisor.kernel,workers=supervisor.workers,gate=supervisor.landGate;
|
|
299
299
|
if(seat!==undefined&&seat!==null)validateAgentSeat(seat,'supervisor.kernel',profile);
|
|
300
300
|
if(!(workers===undefined||workers===null||(plain(workers)&&Object.keys(workers).every(key=>['base','max'].includes(key)&&Number.isInteger(workers[key])&&workers[key]>=0&&workers[key]<=10))))
|
|
301
301
|
throw new Error('Invalid config.yaml: supervisor.workers must be {base?, max?} integers from 0 to 10, or null.');
|
|
302
|
-
if(!(gate===undefined||gate===null||(plain(gate)&&Object.keys(gate).every(key=>key==='mode'&&['shared','exclusive'].includes(gate.mode)))))
|
|
303
|
-
throw new Error('Invalid config.yaml: supervisor.landGate must be {mode?: shared|exclusive}, or null.');
|
|
302
|
+
if(!(gate===undefined||gate===null||(plain(gate)&&Object.keys(gate).every(key=>(key==='mode'&&['shared','exclusive'].includes(gate.mode))||(key==='push'&&typeof gate.push==='boolean')))))
|
|
303
|
+
throw new Error('Invalid config.yaml: supervisor.landGate must be {mode?: shared|exclusive, push?: boolean}, or null.');
|
|
304
304
|
// stallMinutes: scripts/supervisor/stall.mjs calls a running workflow STALLED after this many minutes with no progress.
|
|
305
305
|
// frozenMinutes: scripts/supervisor/supervisor-watchdog.mjs reads a busy seat frame with no turn progress for this long as frozen.
|
|
306
306
|
const frozen=supervisor.frozenMinutes;
|
|
@@ -3,14 +3,14 @@ import {invalid} from './invalid-config.mjs';
|
|
|
3
3
|
|
|
4
4
|
/** The keys of the release block. */
|
|
5
5
|
export const RELEASE_KEYS=Object.freeze(['suite']);
|
|
6
|
-
/** Where the full test suite of a release is judged: `local` (the release cut runs it, the shipped default) or `ci` (the GitHub
|
|
6
|
+
/** Where the full test suite of a release is judged: `local` (the release cut also runs the L4 rows before it tags, the shipped default) or `ci` (the GitHub workflows judge EVERY row on each push to main; the cut runs none). */
|
|
7
7
|
export const SUITE_MODES=Object.freeze(['local','ci']);
|
|
8
|
-
|
|
8
|
+
const RELEASE_DEFAULTS=Object.freeze({suite:'local'});
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* config.yaml `release` - {suite?: local | ci}: who judges the full suite of a release (docs/releasing.md "Where the suite runs"). `local` is the shipped
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* config.yaml `release` - {suite?: local | ci}: who judges the full suite of a release (docs/releasing.md "Where the suite runs"). `local` is the shipped default: `starci release cut` also runs the
|
|
12
|
+
* L4 rows on this host before it tags. `ci` is the owner's recorded choice (2026-10-09, widened 2026-10-26 by push-main-after-scoped-check): the full suite runs on GitHub only, on every push
|
|
13
|
+
* to main; the cut runs no row and the verdict is read with `starci release ci-status`. The push of main needs neither mode: it needs a green scoped check.
|
|
14
14
|
* `none` is refused: the suite does not vanish, it moves to CI, and the value says so.
|
|
15
15
|
*/
|
|
16
16
|
export function validateRelease(release){
|
|
@@ -253,7 +253,7 @@ guidance:
|
|
|
253
253
|
a family where selection, current and focus share the same pink.
|
|
254
254
|
- id: big-touch-targets
|
|
255
255
|
requirement: |
|
|
256
|
-
Keep the published sizes: Common's
|
|
256
|
+
Keep the published sizes: Common's 40px control height for controls, the Subnav toggle and the TopBar
|
|
257
257
|
trigger, and `size="control"` throughout the navbar. Do not shrink them with app classes,
|
|
258
258
|
and put answer choices in RadioGroup/CheckboxGroup/SegmentedControl rather than small
|
|
259
259
|
custom chips.
|
|
@@ -185,7 +185,7 @@ shapes:
|
|
|
185
185
|
- id: navbar-controls
|
|
186
186
|
implements: [FE-APP-SHELL-2]
|
|
187
187
|
compose: |
|
|
188
|
-
Every bar control uses `size="control"`, the 2.
|
|
188
|
+
Every bar control uses `size="control"`, the 2.5rem (40px) shared height. Icon uses the family
|
|
189
189
|
size-5 token (20px) throughout the region. SearchField or its trigger shows Ctrl K and opens
|
|
190
190
|
on Ctrl/Cmd+K; inside a surface its variant resolves through the nesting context. A compact
|
|
191
191
|
language switch in a bar is SegmentedControl size="control" (the HeroUI lg group held to
|
|
@@ -250,7 +250,7 @@ shapes:
|
|
|
250
250
|
scrolls independently. Groups use translated headings such as Main, Operations and Settings
|
|
251
251
|
from modules/i18n/messages/app-shell.yaml. The expanded item has a size-5 icon, label and
|
|
252
252
|
Grammar current-page treatment. A keyboard-accessible toggle collapses it into icon-only
|
|
253
|
-
destinations with size-5 icons in 2.
|
|
253
|
+
destinations with size-5 icons in 2.5rem targets, current-page highlighting, count badges
|
|
254
254
|
and hover/focus tooltips. Group order is stable, spacing replaces group headings and
|
|
255
255
|
settings-type groups stay at the end. The application persists collapse state per user.
|
|
256
256
|
- id: conversation-panel
|
|
@@ -333,6 +333,20 @@ imageryClarification:
|
|
|
333
333
|
library-edit scope. Historical image notes are design references, not decisions for the current
|
|
334
334
|
product.
|
|
335
335
|
guidance:
|
|
336
|
+
- id: owner-ui-rulings-alpha-31
|
|
337
|
+
ownership: FE-RULE-OWNERSHIP
|
|
338
|
+
implements: [COLLECTION-1, LAYOUT-1, SURFACE-1, ACTION-3, CTA-6]
|
|
339
|
+
requirement: |
|
|
340
|
+
The canonical cases own the rule bodies; this entry only points to them. COLLECTION-1 case-9
|
|
341
|
+
(owner:selection-fill-no-check): navigation-like single selection uses ListBox
|
|
342
|
+
selectionIndicator="none", with the selectedKeys and accessibility contract unchanged.
|
|
343
|
+
LAYOUT-1 case-10 (owner:joined-multi-pane): the selected family realizes one touching pane
|
|
344
|
+
surface with vertical Dividers. SURFACE-1 case-4 (owner:scroll-region-background-tone):
|
|
345
|
+
VerticalScrollRegion tone="background" under messages and log entries, with the header and
|
|
346
|
+
composer on the surface. ACTION-3 case-5 (owner:hover-actions-floating-toolbar): ChatBubble's
|
|
347
|
+
public floating toolbar owns the IconButtons and tooltips beside the text; apps do not target
|
|
348
|
+
starci-core internals. CTA-6 case-4 (owner:button-variant-follows-intent): ordinary repeated
|
|
349
|
+
item commands are neutral and render ghost.
|
|
336
350
|
- id: nested-controls-and-panel-lists
|
|
337
351
|
ownership: FE-RULE-OWNERSHIP
|
|
338
352
|
implements: [ANATOMY-2, PADDING-0]
|
|
@@ -30,35 +30,35 @@ pins:
|
|
|
30
30
|
source: packages/event-stream/package.json
|
|
31
31
|
why: 'the one server-sent-events client of every front end (fe-stack event-stream, owner:event-stream-package): the transport client layer (modules/api/sse/clients) creates one instance for the app with the bearer token source and the stream operations follow on it; it carries Last-Event-ID resume, the capped doubling backoff, the heartbeat timeout, the single 401 renewal and the useSWRSubscription adapter, so no app keeps a hand-written reader.'
|
|
32
32
|
'@starci/grammar':
|
|
33
|
-
version: 0.12.
|
|
33
|
+
version: 0.12.14
|
|
34
34
|
group: starci
|
|
35
35
|
install: registry
|
|
36
36
|
side: fe
|
|
37
37
|
source: packages/grammar/package.json
|
|
38
38
|
why: 'the grammar front ends read: the brand layer sets `--font-sans` and `--font-mono` and the grammar reads them; it carries the Input tel kind, the copyable and read-only Input, the IconButton disclosure props and count badge, ChatBubble, FillViewport, Textarea mentions and Enter-to-send, the leading PrimaryRailLayout rail, the plate-less Image, ListRow, the soft Alert, Progress steps, the floating primary IconButton, FlowGraph, the STATE-8 loading views and the bordered selectable TagGroup chips. The runtime source version wins for a @starci package.'
|
|
39
39
|
'@starci/eslint-canon-be':
|
|
40
|
-
version: 3.4.
|
|
40
|
+
version: 3.4.56
|
|
41
41
|
group: starci
|
|
42
42
|
install: registry
|
|
43
43
|
side: be
|
|
44
44
|
source: packages/eslint/be/package.json
|
|
45
45
|
why: 'the back-end ESLint canon: `loadHfs(import.meta.url)` of be/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the be side, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; `starciBeConfig({ hfs: loadHfs(import.meta.url) })` is the typed factory and the BE-CONVENTION laws are its rules.'
|
|
46
46
|
'@starci/eslint-canon-fe':
|
|
47
|
-
version: 9.1.
|
|
47
|
+
version: 9.1.10
|
|
48
48
|
group: starci
|
|
49
49
|
install: registry
|
|
50
50
|
side: fe
|
|
51
51
|
source: packages/eslint/fe/package.json
|
|
52
52
|
why: 'the front-end ESLint canon: `loadHfs(import.meta.url)` of fe/eslint.config.mjs finds the app-root hfs.json (kind app) and gives every linted file the view of the fe side, and the project graph is built per side; its bundled runtime copies (slots, canon-pins, failure codes, the architecture machine) put .starcistacks and .sops.yaml at the app root; the front end has no tests (FE_NO_TESTS R97 in hfs) and no-vietnamese-in-source (R91) applies.'
|
|
53
53
|
'@starci/eslint-grammar-starci':
|
|
54
|
-
version: 0.12.
|
|
54
|
+
version: 0.12.14
|
|
55
55
|
group: starci
|
|
56
56
|
install: registry
|
|
57
57
|
side: fe
|
|
58
58
|
source: packages/eslint/grammar-starci/package.json
|
|
59
59
|
why: 'the StarCi Grammar component API lint, versioned with @starci/grammar; front ends compose this family package with the universal FE canon.'
|
|
60
60
|
'@starci/eslint-grammar-offset-pop':
|
|
61
|
-
version: 0.12.
|
|
61
|
+
version: 0.12.14
|
|
62
62
|
group: starci
|
|
63
63
|
install: registry
|
|
64
64
|
side: fe
|
|
@@ -98,14 +98,14 @@ pins:
|
|
|
98
98
|
source: packages/test-world/package.json
|
|
99
99
|
why: 'the shared e2e library of every back end (R47, R48), a devDependency of every back end: the warm stack behind toxiproxy, the network-edge fakes, the Nest boot, the typed useTestWorld handle, useSandbox for contract specs and the outage lock. Kafka is real own infra (the one digest-pinned apache/kafka KRaft image, a broker listener and proxy per slot, slot-prefixed topics, consumer groups and client ids) and Postgres is schema-per-context (a schema and a login role per context in a shared database). Each worker has its own data slot (<ns>_w<k>) with its own databases, Keycloak realm, leased Redis DB, bucket/collection/topic prefixes, fakes host, toxiproxy proxies and outage lock; a run provisions min(jest workers, workers cap, default 2) slots, and state file protocol 2 pairs exactly with @starci/jest-preset (TEST_WORLD_PAIR_MISMATCH otherwise). A modules world boots real peer apps beside its modules, world.apps.<name>.during(fn) is the outage of a peer app, w.keycloak.clientSecret(client) answers the run-generated secret of a confidential realm client, world.keycloak.events/sessions read the realm user events and live sessions, world.infra.postgresql.connection(name) takes one database connection down while the others serve, and world.resolve and scope.resolve take any Nest token. Every path a declaration names (`stack`, seeds, the realm, Dockerfiles) resolves from the app root (the directory of hfs.json); the globalSetup registers the path aliases as TypeScript resolves them. Its CLI main is exported at ./cli for starci app stack.'
|
|
100
100
|
'@starci/cli':
|
|
101
|
-
version: 1.7.
|
|
101
|
+
version: 1.7.47
|
|
102
102
|
group: starci
|
|
103
103
|
install: registry
|
|
104
104
|
side: both
|
|
105
105
|
source: packages/cli/package.json
|
|
106
106
|
why: 'the only StarCi command package; product repositories install it for starci app, while @starci/hfs remains its pinned transitive implementation.'
|
|
107
107
|
'@starci/hfs':
|
|
108
|
-
version: 4.7.
|
|
108
|
+
version: 4.7.47
|
|
109
109
|
group: starci
|
|
110
110
|
install: registry
|
|
111
111
|
side: both
|
|
@@ -34,7 +34,7 @@ heap:
|
|
|
34
34
|
items:
|
|
35
35
|
- id: candidate-trigger
|
|
36
36
|
title: the release CI runs on the release candidate ref
|
|
37
|
-
requires: "ci.yml runs on push of branches ['release/candidate-*'] and tags ['v*'] (and workflow_dispatch); the release flows wait for the run of the release sha there"
|
|
37
|
+
requires: "ci.yml runs on push of branches ['main', 'release/candidate-*'] and tags ['v*'] (and workflow_dispatch); the release flows wait for the run of the release sha there"
|
|
38
38
|
covers: [app-ci, runtime]
|
|
39
39
|
by: [R221 CI_TRIGGERS_RELEASE_ONLY, R251 HFS_APP_WORKFLOW_TRIGGER]
|
|
40
40
|
- id: job-shape
|
|
@@ -20,7 +20,7 @@ schema: starci/hfs-rules@3
|
|
|
20
20
|
version: 3.1.0
|
|
21
21
|
gates:
|
|
22
22
|
pre-commit: the managed L0 hook runs app hygiene, managed-file drift, ESLint per side and stylelint on staged source, and prettier on staged files; typecheck and targeted specs belong to the op gate under R225
|
|
23
|
-
pre-push: the managed app hook
|
|
23
|
+
pre-push: the managed app hook invokes the bundled push policy under R225; it starts no source check, build or test
|
|
24
24
|
settle: the op gate `starci gate run` over the op's changed files (merge guard, starci app lint --changed, codegen, tsc, the slice's specs; only findings new against the workflow's previous checkpoint block), re-read at starci kernel settle, which refuses a red done; a green settle commits the op's checkpoint on wf-<workflowId>
|
|
25
25
|
land: the workflow's finish, the only time main is touched - gate.mjs over the whole workflow branch against its merge-base with main, the merge guard, review.verify of the exact head that lands, the branch rebased onto main, then main fast-forwarded and pushed
|
|
26
26
|
ci: GitHub Actions runs the same pinned starci app lint, format:check, typecheck, unit with the per-file coverage threshold, build:be and build:fe, then the Sonar scan and gate
|
|
@@ -3850,7 +3850,7 @@ rules:
|
|
|
3850
3850
|
- {path: packages/hfs/src/hfs-supabase-secrets.spec.mjs, edition: lite}
|
|
3851
3851
|
- id: R221
|
|
3852
3852
|
code: "CI_TRIGGERS_RELEASE_ONLY"
|
|
3853
|
-
law: "
|
|
3853
|
+
law: "Workflow triggers are push filtered to v* tags or release/candidate-* branches, and workflow_dispatch. Runtime workflows and app ci.yml also admit main. App ci.yml includes the candidate branch filter for starci app release push. Other branches, events, path filters and ignore filters are refused."
|
|
3854
3854
|
scope: runtime
|
|
3855
3855
|
editions: [lite, full]
|
|
3856
3856
|
docs: [docs/git-governance.md#r221]
|
|
@@ -3894,7 +3894,7 @@ rules:
|
|
|
3894
3894
|
- {kind: runtime, id: protected-zone, at: scripts/hfs/runtime-rules/rights-policy.mjs}
|
|
3895
3895
|
- id: R225
|
|
3896
3896
|
code: "RT_HOOK_SHAPE"
|
|
3897
|
-
law: "The app hook templates keep the gate model: pre-commit is L0 only (no typecheck
|
|
3897
|
+
law: "The app hook templates keep the gate model: pre-commit is L0 only (no typecheck or test run); pre-push invokes the bundled scripts/guards/release-push-gate.mjs policy for fast-forward main, a clean outgoing secret scan and annotated v* tags. It runs no build, test, typecheck or lint."
|
|
3898
3898
|
scope: runtime
|
|
3899
3899
|
kinds: [check]
|
|
3900
3900
|
gates: [land, runtime]
|
|
@@ -4269,7 +4269,7 @@ rules:
|
|
|
4269
4269
|
editions: [lite, full]
|
|
4270
4270
|
docs:
|
|
4271
4271
|
- {path: docs/application-stacks.md#r251-deploy-workflow, editions: [lite, full]}
|
|
4272
|
-
law: "In lite and full apps, deployment jobs declare a protected environment, explicit permissions and concurrency, materialize sealed secrets through SOPS_AGE_KEY or starci app secret materialize, and reference only the age key and transport SSH key/known_hosts secrets. They never embed a dotenv blob or write a dotenv file. Every remote workflow action uses a 40-hex commit SHA (local actions are allowed and container actions require a full sha256 digest); supply-chain reports each unpinned uses reference at its source line, including disabled jobs and steps; installed tools are checksum or digest verified, or supplied by a pinned action. App workflows start only on release tags [v*], the release candidate branches release/candidate-* (required in ci.yml: starci app release push waits for that run, owner ruling candidate-ci 2026-10-18) or workflow_dispatch
|
|
4272
|
+
law: "In lite and full apps, deployment jobs declare a protected environment, explicit permissions and concurrency, materialize sealed secrets through SOPS_AGE_KEY or starci app secret materialize, and reference only the age key and transport SSH key/known_hosts secrets. They never embed a dotenv blob or write a dotenv file. Every remote workflow action uses a 40-hex commit SHA (local actions are allowed and container actions require a full sha256 digest); supply-chain reports each unpinned uses reference at its source line, including disabled jobs and steps; installed tools are checksum or digest verified, or supplied by a pinned action. App workflows start only on release tags [v*], the release candidate branches release/candidate-* (required in ci.yml: starci app release push waits for that run, owner ruling candidate-ci 2026-10-18) or workflow_dispatch; ci.yml also runs on main, and other branch pushes are refused."
|
|
4273
4273
|
kinds: [check]
|
|
4274
4274
|
gates: [settle, land, ci]
|
|
4275
4275
|
failureCodes: ["HFS_DEPLOY_WORKFLOW", "HFS_WORKFLOW_PIN", "HFS_CI_TOOL_INSTALL", "HFS_APP_WORKFLOW_TRIGGER"]
|
|
@@ -5576,7 +5576,7 @@ rules:
|
|
|
5576
5576
|
templateNa: "The app composes its shell from product destinations and identity; full and lite example shells provide the reference."
|
|
5577
5577
|
- id: R318
|
|
5578
5578
|
code: "FE_NESTED_VARIANT"
|
|
5579
|
-
law: "Apps compose Grammar with layout-only CSS; paint utilities, arbitrary paint properties and inline style paint belong to Grammar. Grammar context owns all layer-aware field variants, nested Tabs defaults and the content edge of panel lists; apps omit static field variants, do not force primary Tabs inside a painted surface, do not paint raw surfaces, and add no horizontal list-wrapper padding within the nearest painted Grammar surface. BOUNDARY-1 case-5 owns Divider full-bleed composition."
|
|
5579
|
+
law: "Apps compose Grammar with layout-only CSS; paint utilities, arbitrary paint properties and inline style paint belong to Grammar. Grammar context owns all layer-aware field variants, nested Tabs defaults and the content edge of panel lists; apps omit static field variants, do not force primary Tabs inside a painted surface, do not paint raw surfaces, and add no horizontal list-wrapper padding within the nearest painted Grammar surface. BOUNDARY-1 case-5 owns Divider full-bleed composition. Navigation-like single-select lists use fill without checks (COLLECTION-1 case-9); application styles never target Grammar internal classes (ACTION-3 case-5)."
|
|
5580
5580
|
kinds: [lint, design]
|
|
5581
5581
|
gates: [pre-commit, settle, land, ci]
|
|
5582
5582
|
failureCodes: ["FE_NESTED_VARIANT", "FE_LIST_PANEL_PADDING", "FE_GRAMMAR_LAYOUT_ONLY", "FE_DIVIDER_FULL_BLEED"]
|
|
@@ -5585,18 +5585,23 @@ rules:
|
|
|
5585
5585
|
- {kind: eslint-fe, id: no-list-panel-padding}
|
|
5586
5586
|
- {kind: eslint-fe, id: no-app-surface-paint}
|
|
5587
5587
|
- {kind: eslint-fe, id: divider-full-bleed}
|
|
5588
|
+
- {kind: eslint-fe, id: selection-fill-no-check}
|
|
5589
|
+
- {kind: eslint-fe, id: no-grammar-internal-selector}
|
|
5588
5590
|
editions: [lite, full]
|
|
5589
5591
|
docs: ["docs/code-pattern-enforcement.md#r318-app-grammar-composition"]
|
|
5590
5592
|
templateNa: "Product composition is proved by the FE canon's Grammar import and surface fixtures; a template cannot choose product slots or lists."
|
|
5591
5593
|
proves:
|
|
5592
5594
|
- {path: packages/eslint/fe/divider-full-bleed.spec.mjs, editions: [lite, full], codes: [FE_DIVIDER_FULL_BLEED]}
|
|
5593
5595
|
- {path: packages/eslint/fe/surface-rules.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_LIST_PANEL_PADDING, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5596
|
+
- {path: packages/eslint/fe/ui-rulings.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5594
5597
|
exemplifiedBy:
|
|
5595
5598
|
- {path: packages/eslint/fe/divider-full-bleed.spec.mjs, editions: [lite, full], codes: [FE_DIVIDER_FULL_BLEED]}
|
|
5596
5599
|
- {path: packages/eslint/fe/surface-rules.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_LIST_PANEL_PADDING, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5600
|
+
- {path: packages/eslint/fe/ui-rulings.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5597
5601
|
witness:
|
|
5598
5602
|
- {path: packages/eslint/fe/divider-full-bleed.spec.mjs, editions: [lite, full], codes: [FE_DIVIDER_FULL_BLEED]}
|
|
5599
5603
|
- {path: packages/eslint/fe/surface-rules.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_LIST_PANEL_PADDING, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5604
|
+
- {path: packages/eslint/fe/ui-rulings.spec.mjs, editions: [lite, full], codes: [FE_NESTED_VARIANT, FE_GRAMMAR_LAYOUT_ONLY]}
|
|
5600
5605
|
cases:
|
|
5601
5606
|
- id: case-1
|
|
5602
5607
|
date: "2026-10-25"
|
|
@@ -5633,3 +5638,29 @@ rules:
|
|
|
5633
5638
|
source: owner
|
|
5634
5639
|
quote: "Critique this carefully so the button choice is a system and not a feeling, understand? Update .claude."
|
|
5635
5640
|
ruling: "The button variant follows the declared intent (owner ruling button-variant-follows-intent): the app passes intent and step, Grammar derives the variant from them and from the placement it reads from React context. The semantics are HeroUI's, so the lint is universal in the FE canon."
|
|
5641
|
+
|
|
5642
|
+
- id: R320
|
|
5643
|
+
code: "FE_CONTROL_HEIGHT"
|
|
5644
|
+
law: "One 40px control height is the default of every standalone control (CONTROL-HEIGHT-1): an app never picks a larger size than the default outside a landing hero call to action, and controls of one row share one size."
|
|
5645
|
+
kinds: [lint, design]
|
|
5646
|
+
gates: [pre-commit, settle, land, ci]
|
|
5647
|
+
failureCodes: ["FE_CONTROL_HEIGHT"]
|
|
5648
|
+
enforcers:
|
|
5649
|
+
- {kind: eslint-fe, id: control-height}
|
|
5650
|
+
editions: [lite, full]
|
|
5651
|
+
docs:
|
|
5652
|
+
- packages/eslint/fe/docs/control-height.md
|
|
5653
|
+
- docs/code-pattern-enforcement.md#r320-control-height
|
|
5654
|
+
proves:
|
|
5655
|
+
- {path: packages/eslint/fe/control-height.spec.mjs, editions: [lite, full], codes: [FE_CONTROL_HEIGHT]}
|
|
5656
|
+
exemplifiedBy:
|
|
5657
|
+
- {path: packages/eslint/fe/control-height.spec.mjs, editions: [lite, full], codes: [FE_CONTROL_HEIGHT]}
|
|
5658
|
+
witness:
|
|
5659
|
+
- {path: packages/eslint/fe/control-height.spec.mjs, editions: [lite, full], codes: [FE_CONTROL_HEIGHT]}
|
|
5660
|
+
templateNa: "The control height is Grammar's own value; a template states no size."
|
|
5661
|
+
cases:
|
|
5662
|
+
- id: case-1
|
|
5663
|
+
date: "2026-10-26"
|
|
5664
|
+
source: owner
|
|
5665
|
+
quote: "The size of the buttons and controls is uneven; the teacher thinks height = 40px (h-10) should be fixed for every button, switch, input, tabs and so on, what do you think? (translated from Vietnamese)"
|
|
5666
|
+
ruling: "One 40px control height is the default of every standalone control (owner ruling control-height-40): Grammar draws it, an app omits size, sm is for a nested item or dense toolbar row, lg only for a landing hero call to action, and controls of one row share one size."
|
|
@@ -188,6 +188,7 @@ rules:
|
|
|
188
188
|
- BE_REALTIME_TOPIC_SCOPE
|
|
189
189
|
- BE_DEFAULT_DENY
|
|
190
190
|
- BE_SOURCE_FORM
|
|
191
|
+
- BE_PUBLIC_CONTRACT_FORM
|
|
191
192
|
- HFS_COVERAGE_SCOPE_DRIFT
|
|
192
193
|
manual:
|
|
193
194
|
- Review that the pure topic policy is exported by the owning domain and used by both the publisher and door.
|
|
@@ -80,7 +80,7 @@ op:
|
|
|
80
80
|
release:
|
|
81
81
|
verbs: [cut, publish]
|
|
82
82
|
scripts: [release:cut, release:publish]
|
|
83
|
-
use: starci release cut is owner-approved and
|
|
83
|
+
use: starci release cut is owner-approved and tags a commit already pushed; starci release publish publishes a finished package at once; starci release push sends main and is not owner-gated; starci release notes prints or writes a tag CHANGELOG section and is not owner-gated
|
|
84
84
|
# Programs that cannot change state, with any arguments.
|
|
85
85
|
read: [ls, dir, cat, type, head, tail, wc, uniq, cut, tr, diff, cmp, comm, rg, grep, egrep, fgrep, echo, printf, pwd, cd, pushd, popd, which, where, whoami, hostname,
|
|
86
86
|
stat, file, realpath, readlink, dirname, basename, date, true, false, test, '[', expr, sleep, seq, basename, md5sum, sha1sum, sha256sum, shasum, cksum, od, xxd, hexdump,
|
|
@@ -123,7 +123,7 @@ git:
|
|
|
123
123
|
add: {code: RIGHTS_GIT_COMMIT, use: starci git commit}
|
|
124
124
|
rm: {code: RIGHTS_GIT_COMMIT, use: starci git commit}
|
|
125
125
|
mv: {code: RIGHTS_GIT_COMMIT, use: starci git commit}
|
|
126
|
-
push: {code: RIGHTS_GIT_PUSH, use: 'starci git backup (refs/backup/* only); main and
|
|
126
|
+
push: {code: RIGHTS_GIT_PUSH, use: 'starci git backup (refs/backup/* only); main moves only through starci release push and a release tag through starci release cut'}
|
|
127
127
|
tag: {code: RIGHTS_GIT_TAG, use: starci release cut (the only tag maker; housekeeping marks are refs/backup/* or refs/salvage/*, never tags)}
|
|
128
128
|
merge: {code: RIGHTS_GIT_SYNC, use: starci git sync (merge main into the lane) or starci git land (coordinator)}
|
|
129
129
|
rebase: {code: RIGHTS_GIT_SYNC, use: starci git sync}
|
|
@@ -154,7 +154,7 @@ npm:
|
|
|
154
154
|
programs: [npm, pnpm, yarn, bun]
|
|
155
155
|
read: [view, v, info, show, ls, list, la, ll, outdated, explain, why, root, prefix, bin, help, search, whoami, ping, '-v', '--version', 'config get', 'config list', pack-dry]
|
|
156
156
|
deny:
|
|
157
|
-
publish: {code: RIGHTS_NPM_PUBLISH, use: starci release
|
|
157
|
+
publish: {code: RIGHTS_NPM_PUBLISH, use: starci release publish is the package-publication path and runs as soon as a package branch is done}
|
|
158
158
|
unpublish: {code: RIGHTS_NPM_PUBLISH, use: starci release publish is the only package-publication path; unpublishing is owner-only}
|
|
159
159
|
deprecate: {code: RIGHTS_NPM_PUBLISH, use: starci release publish is the only package-publication path; deprecation is owner-only}
|
|
160
160
|
dist-tag: {code: RIGHTS_NPM_PUBLISH, use: starci release publish is the only package-publication path; dist-tag mutation is owner-only}
|
|
@@ -165,8 +165,8 @@ npm:
|
|
|
165
165
|
add: {code: RIGHTS_RAW_TOOL, use: starci npm install adds exact-pinned dependencies and is limited to lead or owner}
|
|
166
166
|
update: {code: RIGHTS_RAW_TOOL, use: starci npm install is the owner-controlled dependency-change path using canon pins}
|
|
167
167
|
uninstall: {code: RIGHTS_RAW_TOOL, use: starci npm install is the owner-controlled dependency-change path using canon pins}
|
|
168
|
-
test: {code: RIGHTS_RAW_TOOL, use: starci runtime verify in the runtime (the check, package clean-test and scaffold e2e; the full proof is
|
|
169
|
-
t: {code: RIGHTS_RAW_TOOL, use: starci runtime verify in the runtime (the check, package clean-test and scaffold e2e; the full proof is
|
|
168
|
+
test: {code: RIGHTS_RAW_TOOL, use: starci runtime verify in the runtime (the check, package clean-test and scaffold e2e; the full proof is CI) or starci gate unit --root <app> in an app}
|
|
169
|
+
t: {code: RIGHTS_RAW_TOOL, use: starci runtime verify in the runtime (the check, package clean-test and scaffold e2e; the full proof is CI) or starci gate unit --root <app> in an app}
|
|
170
170
|
run: {code: RIGHTS_RAW_TOOL, use: 'starci runtime verify proves a runtime change; starci work layout-render serves the app for a layout capture; use starci release sync-runtime for package runtime copies and grammar preparation, or starci check run, starci lint run, starci typecheck run, starci app stack, or starci gate run for other scripts'}
|
|
171
171
|
run-script: {code: RIGHTS_RAW_TOOL, use: 'starci runtime verify proves a runtime change; use starci check run, starci lint run, starci typecheck run, starci app stack, or starci gate run for other scripts'}
|
|
172
172
|
start: {code: RIGHTS_RAW_TOOL, use: 'starci app stack'}
|
|
@@ -1770,13 +1770,13 @@ CI_STANDARD:
|
|
|
1770
1770
|
kind: check-finding
|
|
1771
1771
|
|
|
1772
1772
|
CI_TRIGGERS_RELEASE_ONLY:
|
|
1773
|
-
title: "Workflow trigger
|
|
1774
|
-
title_vi: "Workflow có trigger
|
|
1775
|
-
meaning_vi: "
|
|
1773
|
+
title: "Workflow trigger outside R221"
|
|
1774
|
+
title_vi: "Workflow có trigger ngoài R221"
|
|
1775
|
+
meaning_vi: "Workflow khai báo trigger ngoài R221: main được phép trong workflow runtime và ci.yml của app; các nhánh, sự kiện và bộ lọc khác phải theo R221."
|
|
1776
1776
|
causes_vi:
|
|
1777
|
-
- "
|
|
1778
|
-
- "
|
|
1779
|
-
nextStep_vi: "
|
|
1777
|
+
- "Khai báo nhánh, sự kiện hoặc bộ lọc không thuộc R221"
|
|
1778
|
+
- "Khai báo nhánh, sự kiện hoặc bộ lọc không thuộc R221"
|
|
1779
|
+
nextStep_vi: "Sửa on theo R221 rồi chạy starci app sync --write để tạo lại workflow ứng dụng."
|
|
1780
1780
|
owner: supervisor
|
|
1781
1781
|
kind: check-finding
|
|
1782
1782
|
|
|
@@ -2284,6 +2284,17 @@ FE_CONSOLE_CALL:
|
|
|
2284
2284
|
owner: op-retry
|
|
2285
2285
|
kind: check-finding
|
|
2286
2286
|
|
|
2287
|
+
FE_CONTROL_HEIGHT:
|
|
2288
|
+
title: "A control picks a larger size or mixes sizes in one row"
|
|
2289
|
+
title_vi: "Điều khiển chọn cỡ lớn hơn hoặc trộn nhiều cỡ trong một hàng"
|
|
2290
|
+
meaning_vi: "Điều khiển Grammar tại <file> truyền size lớn hơn chiều cao chuẩn 40px, hoặc đứng cạnh điều khiển khác cỡ trong cùng một hàng."
|
|
2291
|
+
causes_vi:
|
|
2292
|
+
- "Truyền size lg hoặc xl cho nút, công tắc, ô nhập ngoài khu hero của trang landing."
|
|
2293
|
+
- "Trộn size sm với cỡ mặc định trong cùng một thanh công cụ hoặc hàng."
|
|
2294
|
+
nextStep_vi: "Bỏ size để Grammar vẽ đúng một chiều cao điều khiển 40px (quy định control-height-40)."
|
|
2295
|
+
owner: op-retry
|
|
2296
|
+
kind: check-finding
|
|
2297
|
+
|
|
2287
2298
|
FE_COOKIE_ATTRIBUTES:
|
|
2288
2299
|
title: "A written cookie leaves its attributes to the defaults"
|
|
2289
2300
|
title_vi: "Cookie được ghi mà không nêu rõ thuộc tính"
|
|
@@ -3219,12 +3230,12 @@ HFS_APP_LEXICON:
|
|
|
3219
3230
|
kind: check-finding
|
|
3220
3231
|
|
|
3221
3232
|
HFS_APP_WORKFLOW_TRIGGER:
|
|
3222
|
-
title: "App
|
|
3233
|
+
title: "App workflow trigger outside R251"
|
|
3223
3234
|
title_vi: "Workflow ứng dụng có sự kiện khởi chạy không hợp lệ"
|
|
3224
|
-
meaning_vi: "Workflow
|
|
3235
|
+
meaning_vi: "Workflow ứng dụng khai báo trigger ngoài R251; ci.yml được chạy trên main và nhánh release candidate, các workflow khác giữ phạm vi trigger của R251."
|
|
3225
3236
|
causes_vi:
|
|
3226
|
-
- "
|
|
3227
|
-
nextStep_vi: "
|
|
3237
|
+
- "Khai báo trigger không thuộc R251"
|
|
3238
|
+
nextStep_vi: "Sửa trigger theo R251 và chạy starci app sync --write."
|
|
3228
3239
|
owner: op-retry
|
|
3229
3240
|
kind: check-finding
|
|
3230
3241
|
|
|
@@ -4532,7 +4543,7 @@ RIGHTS_GIT_PUSH:
|
|
|
4532
4543
|
causes_vi:
|
|
4533
4544
|
- "Agent định đẩy main, một nhánh thường, mọi thẻ hoặc một refspec quá rộng"
|
|
4534
4545
|
- "Coordinator hoặc Supervisor đẩy bản sao lưu nhưng đích không nằm trong refs/backup/* hoặc không có refspec tường minh"
|
|
4535
|
-
nextStep_vi: "Lệnh bị từ chối; để thay đổi đi qua starci release
|
|
4546
|
+
nextStep_vi: "Lệnh bị từ chối; để thay đổi đi qua starci release push, hoặc nếu là coordinator hay Supervisor thì dùng starci git backup với đích refs/backup/* tường minh."
|
|
4536
4547
|
owner: op-retry
|
|
4537
4548
|
kind: verb-refusal
|
|
4538
4549
|
|
|
@@ -4605,12 +4616,13 @@ RIGHTS_PROTECTED_ZONE:
|
|
|
4605
4616
|
RIGHTS_PUSH_NOT_RELEASE:
|
|
4606
4617
|
title: "Pre-push gate refused the push"
|
|
4607
4618
|
title_vi: "Cổng pre-push từ chối lần đẩy"
|
|
4608
|
-
meaning_vi: "Hook pre-push đã chặn một lần đẩy main hoặc thẻ v* của runtime
|
|
4619
|
+
meaning_vi: "Hook pre-push đã chặn một lần đẩy main hoặc thẻ v* của runtime hoặc app: main không phải fast-forward hoặc vùng đẩy có ứng viên bí mật; thẻ v* không phải thẻ annotated."
|
|
4609
4620
|
causes_vi:
|
|
4610
4621
|
- "Thao tác xóa main hoặc xóa thẻ phát hành"
|
|
4611
4622
|
- "Đẩy main không phải fast-forward của main trên remote (force push, rewind hoặc nhánh rẽ)"
|
|
4612
|
-
- "
|
|
4613
|
-
|
|
4623
|
+
- "Vùng đẩy chứa ứng viên bí mật (tên tệp, dòng và mẫu, không bao giờ giá trị)"
|
|
4624
|
+
- "Đẩy thẻ v* không phải thẻ annotated"
|
|
4625
|
+
nextStep_vi: "Gỡ hoặc mã hóa ứng viên bí mật, fetch main rồi đẩy lại bằng starci release push; thẻ thì tạo bằng starci release cut --tag v<version> (thêm --plan để xem trước)."
|
|
4614
4626
|
owner: supervisor
|
|
4615
4627
|
kind: verb-refusal
|
|
4616
4628
|
|
|
@@ -4628,11 +4640,11 @@ RIGHTS_RAW_TOOL:
|
|
|
4628
4640
|
RIGHTS_RELEASE_CUT:
|
|
4629
4641
|
title: "Release cut refused"
|
|
4630
4642
|
title_vi: "Từ chối cắt bản phát hành"
|
|
4631
|
-
meaning_vi: "Release cut
|
|
4643
|
+
meaning_vi: "Release cut gắn thẻ bản phát hành cho một commit đã đẩy và publish gói là quyết định phát hành của owner; worker, lead, Supervisor và coordinator không được tự khởi động chúng."
|
|
4632
4644
|
causes_vi:
|
|
4633
4645
|
- "Agent gọi starci release cut hoặc đường script tương đương"
|
|
4634
4646
|
- "Agent định publish bản phát hành mà chưa có phê duyệt của owner"
|
|
4635
|
-
nextStep_vi: "Lệnh bị từ chối;
|
|
4647
|
+
nextStep_vi: "Lệnh bị từ chối; đẩy main bằng starci release push, và báo để owner phê duyệt starci release cut hoặc publish."
|
|
4636
4648
|
owner: op-retry
|
|
4637
4649
|
kind: verb-refusal
|
|
4638
4650
|
|
|
@@ -4653,7 +4665,7 @@ RIGHTS_SUITE_RUN:
|
|
|
4653
4665
|
meaning_vi: "Toàn bộ suite chỉ chạy một lần trong mỗi release hoặc theo yêu cầu trong unit.verify hay e2e.verify; một worker chỉ chạy tệp spec vừa thay đổi hoặc để op gate chọn phạm vi."
|
|
4654
4666
|
causes_vi:
|
|
4655
4667
|
- "Agent gọi npm test, một script test toàn bộ hoặc node --test trên cả cây tests"
|
|
4656
|
-
- "Agent chạy suite ngoài
|
|
4668
|
+
- "Agent chạy suite ngoài CI và ngoài op verify được yêu cầu"
|
|
4657
4669
|
nextStep_vi: "Lệnh bị từ chối; chạy riêng tệp spec đã thay đổi, để op gate chọn spec liên quan, hoặc dùng unit.verify/e2e.verify khi owner hay mục tiêu yêu cầu."
|
|
4658
4670
|
owner: op-retry
|
|
4659
4671
|
kind: verb-refusal
|
|
@@ -5018,11 +5030,11 @@ RT_HELD_UNSURFACED:
|
|
|
5018
5030
|
RT_HOOK_SHAPE:
|
|
5019
5031
|
title: "App hook template breaks the gate model"
|
|
5020
5032
|
title_vi: "Template hook của app phá vỡ mô hình cổng"
|
|
5021
|
-
meaning_vi: "Template hook
|
|
5033
|
+
meaning_vi: "Template hook của app không đúng R225: pre-commit chạy L0; pre-push gọi chính sách push dùng chung trong gói, không chạy build, test, typecheck hay lint."
|
|
5022
5034
|
causes_vi:
|
|
5023
5035
|
- "Thêm lại npm run typecheck hoặc test:affected vào pre-commit"
|
|
5024
|
-
- "Đưa typecheck, lint hay test vào pre-push
|
|
5025
|
-
nextStep_vi: "
|
|
5036
|
+
- "Đưa build, typecheck, lint hay test vào pre-push hoặc bỏ lời gọi chính sách push dùng chung"
|
|
5037
|
+
nextStep_vi: "Khôi phục template theo R225 rồi chạy starci app sync --write để tạo lại hook."
|
|
5026
5038
|
owner: supervisor
|
|
5027
5039
|
kind: check-finding
|
|
5028
5040
|
|