You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2d2bc74
Browse filesBrowse the repository at this point in the historyBrowse files
The CLI SHALL exit with code 0 when no error-severity matches are found (including when only warnings, info, or hints exist). The CLI SHALL exit with code 1 when at least one error-severity match is found.
116
+
The CLI SHALL exit with code 0 when no error-severity matches are found (including when only warnings, info, or hints exist) and no runtime rule was withheld for entitlement. The CLI SHALL exit with code 1 when at least one error-severity match is found. The CLI SHALL also exit with code 1 when reconciliation completed and the response's `entitlement.withheld` is non-empty, whatever the findings, in both human and `--json` modes.
117
117
118
118
#### Scenario: Exit 0 when clean
119
119
@@ -130,6 +130,17 @@ The CLI SHALL exit with code 0 when no error-severity matches are found (includi
130
130
-**WHEN** the scanner produces at least one result with severity "error"
131
131
-**THEN** the process SHALL exit with code 1
132
132
133
+
#### Scenario: Exit 1 when a runtime rule is withheld for entitlement
134
+
135
+
-**WHEN** reconciliation returns a non-empty `entitlement.withheld` and the scan produces zero results
136
+
-**THEN** the process SHALL exit with code 1
137
+
-**AND** under `--json`, `success` SHALL be `false`
138
+
139
+
#### Scenario: Entitlement without a withheld file does not fail
140
+
141
+
-**WHEN** reconciliation returns `entitlement.runtimeSignatures: false` with an empty or absent `withheld`, and the scan produces zero results
142
+
-**THEN** the process SHALL exit with code 0
143
+
133
144
### Requirement: Check subcommand respects global working directory flag
134
145
135
146
The `check` subcommand SHALL use the resolved working directory from the global `-d` flag (or `process.cwd()` if not specified) as the target directory for `.taskless/` validation and scanner execution.
@@ -493,3 +504,35 @@ A notice SHALL NOT affect the exit code.
493
504
-**WHEN** a `check` run produces no notices
494
505
-**THEN** human output SHALL print no `Notice: ` line
495
506
-**AND**`--json` SHALL omit the `notices` field
507
+
508
+
### Requirement: Check reports runtime rules withheld for entitlement as a plan outcome
509
+
510
+
When reconciliation completes and returns a non-empty `entitlement.withheld`, `taskless check` SHALL NOT execute any withheld rule, SHALL report each local runtime rule whose reported `check.ts` path appears in `withheld` as skipped with a reason stating that runtime rules are not included in the organization's plan, and SHALL NOT describe it as unsafe, unknown, drifted, or tampered. The human output SHALL include one notice naming the withheld rules, the `entitlement.reason`, and the `entitlement.upgradeUrl` when present. Under `--json`, the output SHALL carry an additive, optional `entitlement` object with `runtimeSignatures`, `reason`, `upgradeUrl`, and `withheld` (the local rule names), present only when reconciliation returned `runtimeSignatures: false`. This is a verified outcome and SHALL NOT be treated as one of the unverified paths that leave the exit code unchanged.
511
+
512
+
#### Scenario: Withheld rule is named with its cause
513
+
514
+
-**WHEN** an authenticated `check` reconciles and `entitlement.withheld` lists the reported `check.ts` of runtime rule `no-env-leak`
515
+
-**THEN**`no-env-leak` SHALL NOT execute
516
+
-**AND** its skip reason SHALL state that runtime rules are not included in the plan
517
+
-**AND** its skip reason SHALL NOT mention unsafe, unknown, or drift
518
+
519
+
#### Scenario: Upgrade URL is shown once
520
+
521
+
-**WHEN** two runtime rules are withheld and `entitlement.upgradeUrl` is present
522
+
-**THEN** the human output SHALL print the upgrade URL exactly once, in one notice naming both rules and the reason
523
+
524
+
#### Scenario: Entitlement appears under --json
525
+
526
+
-**WHEN** a runtime rule is withheld and `--json` is set
527
+
-**THEN** stdout SHALL include `entitlement` with `runtimeSignatures: false`, `reason`, `upgradeUrl`, and `withheld` naming the rule
528
+
-**AND**`skipped` SHALL still list the rule with its plan reason
529
+
530
+
#### Scenario: A server without the entitlement object is unchanged
531
+
532
+
-**WHEN** reconciliation returns the four arrays and no `entitlement` object
533
+
-**THEN**`check` SHALL behave exactly as before this change, including its exit code and skip reasons
534
+
535
+
#### Scenario: Degrade paths still never fail
536
+
537
+
-**WHEN**`check` runs logged out, with `--anonymous`, or reconciliation cannot complete
538
+
-**THEN** the exit code SHALL NOT change because runtime rules were skipped, as before this change
Copy file name to clipboardExpand all lines: openspec/specs/cli-generated-rule-delivery/spec.md
+27Lines changed: 27 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,3 +46,30 @@ whose destination the client computed itself.
46
46
-**WHEN** a delivered file declares a path containing `..` or an absolute path
47
47
-**THEN** the CLI SHALL refuse the entire rule
48
48
-**AND** SHALL NOT have created any file or directory for it
49
+
50
+
### Requirement: A runtime rule written under a plan without runtime signatures says it will not run
51
+
52
+
When the CLI writes a runtime rule from a response whose `entitlement.runtimeSignatures` is exactly `false` (from `rule create`, `rule improve`, or a restore during `check`), it SHALL still write the rule, and SHALL emit a warning that the rule is on disk but will not run on the organization's current plan, including the `upgradeUrl` when it is an absolute `https:` URL. The warning SHALL be carried in the command's existing notices, so it appears in human output and under `--json`. A restore under such a response SHALL NOT state or imply that the next `check` will bless or run the rule. A response with no `entitlement` object, or with `runtimeSignatures: true`, SHALL produce no such warning.
53
+
54
+
#### Scenario: Created runtime rule under an unentitled plan
55
+
56
+
-**WHEN**`rule create` receives a generated runtime rule with `entitlement.runtimeSignatures: false`
57
+
-**THEN** the CLI SHALL write the rule
58
+
-**AND** SHALL warn that it will not run on the current plan
59
+
-**AND** under `--json` the warning SHALL appear in `notices`
60
+
61
+
#### Scenario: Restore under an unentitled plan does not promise blessing
62
+
63
+
-**WHEN** a restore during `check` writes a runtime rule and the restore response carries `entitlement.runtimeSignatures: false`
64
+
-**THEN** the restore notice SHALL say the rule's bytes were restored but will not run on the current plan
65
+
-**AND** SHALL NOT say the next `check` blesses it
66
+
67
+
#### Scenario: Entitled or legacy responses do not warn
68
+
69
+
-**WHEN** a runtime rule is written from a response with no `entitlement` object or with `runtimeSignatures: true`
70
+
-**THEN** the CLI SHALL emit no entitlement warning
71
+
72
+
#### Scenario: Static rules never warn
73
+
74
+
-**WHEN**`rule create` writes an `sg` or `vale` rule
75
+
-**THEN** the CLI SHALL emit no entitlement warning
Copy file name to clipboardExpand all lines: openspec/specs/cli-rule-reconciliation/spec.md
+31Lines changed: 31 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -278,3 +278,34 @@ upgrading is regeneration and SHALL remain an explicit action.
278
278
279
279
-**WHEN** a newer generation of the same rule exists server-side
280
280
-**THEN** re-fetch SHALL still return the bytes matching the signature the client reported
281
+
282
+
### Requirement: The CLI reads the reconcile entitlement object
283
+
284
+
The CLI SHALL read the optional `entitlement` object on a successful reconcile response. It SHALL treat the organization as unentitled only when `entitlement.runtimeSignatures` is exactly `false`; an absent, malformed, or `true` value SHALL be treated as no entitlement outcome, leaving the four buckets to drive execution exactly as before. For an unentitled response the CLI SHALL read `reason`, `upgradeUrl`, and `withheld` (a list of `{ ruleId, file }`), SHALL drop a `withheld` entry without a string `file`, and SHALL surface `upgradeUrl` only when it is an absolute `https:` URL.
285
+
286
+
`entitlement.withheld` SHALL be a disposition distinct from the four buckets: a withheld file SHALL NOT be executed, SHALL NOT be surfaced as tamper, drift, or never-issued, and SHALL NOT be sent to restore. The CLI SHALL match a withheld entry to a local runtime rule by the `file` it reported, since the entry carries no signature. A withheld entry that matches no reported file SHALL still count as withheld for the purpose of the exit code.
287
+
288
+
#### Scenario: Absent entitlement changes nothing
289
+
290
+
-**WHEN** a reconcile response carries no `entitlement` object
291
+
-**THEN** the CLI SHALL drive execution from `run`, `unsafe`, `unknown`, and `missing` exactly as before
292
+
293
+
#### Scenario: Entitled response changes nothing
294
+
295
+
-**WHEN** a reconcile response carries `entitlement: { runtimeSignatures: true }`
296
+
-**THEN** the CLI SHALL drive execution from the four buckets exactly as before
297
+
298
+
#### Scenario: Withheld is matched by reported path
299
+
300
+
-**WHEN**`entitlement.withheld` lists `{ ruleId, file }` and `file` equals the path the CLI reported for a runtime rule's `check.ts`
301
+
-**THEN** the CLI SHALL classify that rule as withheld for entitlement and SHALL NOT execute it
302
+
303
+
#### Scenario: Withheld is not repaired
304
+
305
+
-**WHEN** a runtime rule is withheld for entitlement
306
+
-**THEN** the CLI SHALL NOT request a restore for it
307
+
308
+
#### Scenario: A malformed upgrade URL is not shown
309
+
310
+
-**WHEN**`entitlement.upgradeUrl` is not an absolute `https:` URL
311
+
-**THEN** the CLI SHALL omit it from human and `--json` output
0 commit comments