@b00dea/cockpit 0.1.0 → 0.1.1
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 +99 -0
- package/README.md +3 -0
- package/cockpit.schema.json +73 -3
- package/dist/autonomy.d.ts +3 -2
- package/dist/autonomy.js +30 -13
- package/dist/browser/commands.d.ts +57 -2
- package/dist/browser/commands.js +114 -10
- package/dist/browser/runtime.d.ts +1 -0
- package/dist/browser/runtime.js +4 -1
- package/dist/browser/surfaces.d.ts +7 -7
- package/dist/browser/surfaces.js +5 -0
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +5 -0
- package/dist/cli-main.d.ts +40 -3
- package/dist/cli-main.js +241 -62
- package/dist/command-table.d.ts +19 -11
- package/dist/command-table.js +190 -38
- package/dist/config/load.d.ts +16 -4
- package/dist/config/load.js +25 -3
- package/dist/config/unconfirmed-toml.d.ts +9 -0
- package/dist/config/unconfirmed-toml.js +29 -0
- package/dist/diagnostics.js +10 -1
- package/dist/docs/check.d.ts +16 -0
- package/dist/docs/check.js +197 -0
- package/dist/docs/decision-record.d.ts +34 -0
- package/dist/docs/decision-record.js +135 -0
- package/dist/docs/decisions.d.ts +16 -0
- package/dist/docs/decisions.js +103 -0
- package/dist/docs/markdown.d.ts +36 -0
- package/dist/docs/markdown.js +88 -0
- package/dist/docs/references.d.ts +32 -0
- package/dist/docs/references.js +148 -0
- package/dist/environment/application/confirm.d.ts +35 -0
- package/dist/environment/application/confirm.js +122 -0
- package/dist/environment/application/destructive.js +6 -2
- package/dist/environment/application/doctor.d.ts +12 -7
- package/dist/environment/application/doctor.js +20 -8
- package/dist/environment/application/guard.d.ts +12 -6
- package/dist/environment/application/guard.js +87 -32
- package/dist/environment/application/health.d.ts +14 -5
- package/dist/environment/application/health.js +8 -2
- package/dist/environment/application/lifecycle-context.d.ts +10 -3
- package/dist/environment/application/lifecycle-state.js +4 -3
- package/dist/environment/application/lifecycle.d.ts +2 -1
- package/dist/environment/application/lifecycle.js +11 -3
- package/dist/environment/application/services.d.ts +60 -0
- package/dist/environment/application/services.js +89 -0
- package/dist/environment/application/siblings.d.ts +43 -0
- package/dist/environment/application/siblings.js +269 -0
- package/dist/environment/claims.d.ts +10 -10
- package/dist/environment/claims.js +3 -11
- package/dist/environment/compose-topology.d.ts +15 -7
- package/dist/environment/compose-topology.js +100 -23
- package/dist/environment/contract.d.ts +42 -9
- package/dist/environment/contract.js +33 -0
- package/dist/environment/executable.d.ts +12 -0
- package/dist/environment/executable.js +46 -23
- package/dist/environment/generated-application/check.js +2 -0
- package/dist/environment/generated-application/prepare.js +2 -0
- package/dist/environment/generated-application/shared.d.ts +10 -2
- package/dist/environment/generated-application/shared.js +6 -1
- package/dist/environment/generated-application/surface-outputs.js +23 -12
- package/dist/environment/generated-application/surfaces.js +16 -11
- package/dist/environment/generated-application/sync.js +19 -4
- package/dist/environment/git-observation.d.ts +25 -6
- package/dist/environment/git-observation.js +37 -28
- package/dist/environment/health-composition.d.ts +3 -2
- package/dist/environment/health-composition.js +19 -2
- package/dist/environment/init-application.d.ts +39 -14
- package/dist/environment/init-application.js +39 -10
- package/dist/environment/lifecycle-composition.d.ts +4 -2
- package/dist/environment/lifecycle-composition.js +84 -17
- package/dist/environment/lifecycle-stage.d.ts +8 -3
- package/dist/environment/lifecycle-stage.js +11 -1
- package/dist/environment/logs.d.ts +1 -1
- package/dist/environment/map-limit.d.ts +2 -0
- package/dist/environment/map-limit.js +13 -0
- package/dist/environment/mcp-observation.d.ts +9 -0
- package/dist/environment/mcp-observation.js +46 -0
- package/dist/environment/observations.d.ts +1 -1
- package/dist/environment/observations.js +2 -0
- package/dist/environment/operator-application.d.ts +35 -6
- package/dist/environment/operator-application.js +42 -0
- package/dist/environment/presence.d.ts +4 -0
- package/dist/environment/presence.js +26 -0
- package/dist/environment/read-composition.d.ts +8 -3
- package/dist/environment/read-composition.js +53 -8
- package/dist/environment/readiness-composition.d.ts +20 -1
- package/dist/environment/readiness-composition.js +23 -2
- package/dist/environment/reclaim.d.ts +56 -19
- package/dist/environment/reclaim.js +147 -42
- package/dist/environment/runtime.d.ts +64 -18
- package/dist/environment/runtime.js +73 -3
- package/dist/environment/served-checkout-grants.d.ts +53 -0
- package/dist/environment/served-checkout-grants.js +182 -0
- package/dist/environment/sibling-checkouts.d.ts +119 -0
- package/dist/environment/sibling-checkouts.js +254 -0
- package/dist/environment/sibling-observation.d.ts +27 -0
- package/dist/environment/sibling-observation.js +45 -0
- package/dist/environment/sibling-pull.d.ts +23 -0
- package/dist/environment/sibling-pull.js +95 -0
- package/dist/environment/stack-inputs.d.ts +18 -0
- package/dist/environment/stack-inputs.js +210 -0
- package/dist/environment/stack-inventory-prune.d.ts +31 -0
- package/dist/environment/stack-inventory-prune.js +129 -0
- package/dist/environment/stack-inventory-report.d.ts +44 -0
- package/dist/environment/stack-inventory-report.js +78 -0
- package/dist/environment/stack-inventory.d.ts +94 -0
- package/dist/environment/stack-inventory.js +418 -0
- package/dist/environment/state.d.ts +48 -9
- package/dist/environment/state.js +142 -2
- package/dist/environment/tool-registration.js +3 -7
- package/dist/environment-exec/execute.d.ts +6 -3
- package/dist/environment-exec/execute.js +4 -0
- package/dist/fix-catalogue.d.ts +1 -1
- package/dist/generated-environment/adopt.js +4 -8
- package/dist/guards/answer-confirmation.d.ts +41 -0
- package/dist/guards/answer-confirmation.js +109 -0
- package/dist/guards/evaluator.d.ts +20 -3
- package/dist/guards/evaluator.js +39 -7
- package/dist/guards/local-identity.d.ts +6 -2
- package/dist/guards/local-identity.js +10 -4
- package/dist/guards/policy-change.d.ts +43 -0
- package/dist/guards/policy-change.js +159 -0
- package/dist/guards/policy-pin.d.ts +1 -1
- package/dist/guards/policy-pin.js +14 -12
- package/dist/init/command.d.ts +4 -3
- package/dist/init/command.js +36 -16
- package/dist/init/derive.d.ts +8 -6
- package/dist/init/derive.js +140 -36
- package/dist/init/draft.d.ts +13 -11
- package/dist/init/draft.js +54 -31
- package/dist/init/render.d.ts +18 -6
- package/dist/init/render.js +31 -9
- package/dist/repository-path.d.ts +9 -0
- package/dist/repository-path.js +16 -0
- package/dist/schema.d.ts +42 -75
- package/dist/schema.js +62 -11
- package/dist/surfaces/harness-registry.d.ts +80 -0
- package/dist/surfaces/harness-registry.js +29 -0
- package/dist/surfaces/mcp.d.ts +67 -17
- package/dist/surfaces/mcp.js +194 -31
- package/dist/surfaces/projection.d.ts +7 -7
- package/dist/surfaces/projection.js +41 -6
- package/dist/surfaces/render.d.ts +5 -44
- package/dist/surfaces/render.js +5 -2
- package/dist/team-metadata.js +2 -1
- package/dist/testing/test-protection.d.ts +34 -0
- package/dist/testing/test-protection.js +137 -0
- package/dist/testing/weakening.d.ts +15 -0
- package/dist/testing/weakening.js +30 -0
- package/dist/work-orders/application-closure.d.ts +7 -0
- package/dist/work-orders/application-closure.js +76 -0
- package/dist/work-orders/application-context.d.ts +162 -0
- package/dist/work-orders/application-context.js +137 -0
- package/dist/work-orders/application-decisions.d.ts +27 -0
- package/dist/work-orders/application-decisions.js +121 -0
- package/dist/work-orders/application-grading.d.ts +11 -0
- package/dist/work-orders/application-grading.js +212 -0
- package/dist/work-orders/application.d.ts +4 -97
- package/dist/work-orders/application.js +94 -254
- package/dist/work-orders/composition.d.ts +35 -58
- package/dist/work-orders/composition.js +216 -24
- package/dist/work-orders/contract.d.ts +22 -6
- package/dist/work-orders/contract.js +34 -16
- package/dist/work-orders/decisions.d.ts +23 -0
- package/dist/work-orders/decisions.js +55 -0
- package/dist/work-orders/store.d.ts +54 -5
- package/dist/work-orders/store.js +118 -24
- package/docs/README.md +6 -3
- package/docs/capability-matrix.md +17 -9
- package/docs/cli-reference.md +209 -1
- package/docs/command-list.md +12 -1
- package/docs/concepts.md +6 -4
- package/docs/configuration-essentials.md +7 -2
- package/docs/configuration-reference.md +18 -3
- package/docs/docs-check.md +76 -0
- package/docs/environment.md +194 -6
- package/docs/faq.md +5 -3
- package/docs/getting-started.md +109 -25
- package/docs/harness-surfaces.md +69 -2
- package/docs/safety-and-autonomy.md +56 -12
- package/docs/troubleshooting.md +29 -8
- package/docs/tutorial.md +3 -2
- package/docs/work-and-browser.md +180 -14
- package/libexec/browser-operation.cjs +86 -2
- package/package.json +2 -2
- package/surfaces/skills/cockpit-browser.skill.md +7 -2
- package/surfaces/skills/cockpit-explain.skill.md +1 -1
- package/surfaces/skills/cockpit-fix.skill.md +1 -1
- package/surfaces/skills/cockpit-setup.skill.md +3 -3
- package/surfaces/skills/cockpit-work.skill.md +1 -1
- package/surfaces/skills/procedures/explain.md +9 -4
- package/surfaces/skills/procedures/fix.md +25 -11
- package/surfaces/skills/procedures/setup.md +113 -40
- package/surfaces/skills/procedures/work.md +45 -16
package/dist/init/render.d.ts
CHANGED
|
@@ -2,24 +2,36 @@ import type { CockpitConfig, configurationDefaults, UNCONFIRMABLE_ANSWERS } from
|
|
|
2
2
|
import type { DocumentedSibling, Gap } from '../registry-resolve/registry.js';
|
|
3
3
|
/**
|
|
4
4
|
* Who gave an interview answer: a person, the setup agent choosing a default it was allowed to
|
|
5
|
-
* choose,
|
|
6
|
-
*
|
|
5
|
+
* choose, no one said (an answers file that does not attribute a value cockpit never proposes), or
|
|
6
|
+
* the setup agent accepting the value init read from exact sources, which init checks against what
|
|
7
|
+
* it reads. A person's answer is written as stated and a derived one with its source; the others
|
|
8
|
+
* are listed under `unconfirmed`.
|
|
7
9
|
*/
|
|
8
|
-
export declare const ANSWER_PROVENANCES: readonly ['operator-confirmed', 'agent-default', 'unattributed'];
|
|
10
|
+
export declare const ANSWER_PROVENANCES: readonly ['operator-confirmed', 'agent-default', 'unattributed', 'derived'];
|
|
9
11
|
export type AnswerProvenance = typeof ANSWER_PROVENANCES[number];
|
|
10
12
|
export type UnconfirmableAnswer = typeof UNCONFIRMABLE_ANSWERS[number];
|
|
11
13
|
export type UnconfirmedAnswer = Readonly<{
|
|
12
14
|
field: UnconfirmableAnswer;
|
|
13
|
-
provenance:
|
|
15
|
+
provenance: 'agent-default' | 'unattributed';
|
|
16
|
+
}>;
|
|
17
|
+
/** An answer accepted as read: the field and the file, as file:line where one line holds it, it was read from. */
|
|
18
|
+
export type DerivedAnswer = Readonly<{
|
|
19
|
+
field: UnconfirmableAnswer;
|
|
20
|
+
source: string;
|
|
14
21
|
}>;
|
|
15
22
|
export declare function unconfirmedReason(row: UnconfirmedAnswer): string;
|
|
16
|
-
export declare const UNCONFIRMED_FIX = "confirm the value with whoever owns the product and correct it in cockpit.toml if it is wrong, then delete its entry from unconfirmed and run npx --no cockpit sync --config <your cockpit.toml>";
|
|
17
23
|
export interface Attribution {
|
|
18
24
|
target: string;
|
|
19
25
|
value: unknown;
|
|
20
26
|
from: 'inferred' | 'default';
|
|
21
27
|
because: string;
|
|
22
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Who confirms a surfaced value: the setup agent for a schema default or the cockpit's own layout,
|
|
31
|
+
* which bring-up proves, and a person for a security boundary or a value a registry dialect left
|
|
32
|
+
* to a guess.
|
|
33
|
+
*/
|
|
34
|
+
export declare function confirmedBy(attribution: Attribution): 'agent' | 'person';
|
|
23
35
|
export interface DocumentModel {
|
|
24
36
|
name?: string;
|
|
25
37
|
defaults: ReturnType<typeof configurationDefaults>;
|
|
@@ -32,4 +44,4 @@ export interface DocumentModel {
|
|
|
32
44
|
}
|
|
33
45
|
export declare function renderIncompleteDocument(model: DocumentModel, schemaDirective: string, configuration?: CockpitConfig): string;
|
|
34
46
|
/** Decisions are comments: the schema has no field for them, and the reader of the file needs them. */
|
|
35
|
-
export declare function renderCompleteDocument(config: CockpitConfig, schemaDirective: string, decisions?: readonly string[], unconfirmed?: readonly UnconfirmedAnswer[]): string;
|
|
47
|
+
export declare function renderCompleteDocument(config: CockpitConfig, schemaDirective: string, decisions?: readonly string[], unconfirmed?: readonly UnconfirmedAnswer[], derived?: readonly DerivedAnswer[]): string;
|
package/dist/init/render.js
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import { AUTONOMY_DEFAULTS, GATE_DEFAULTS } from '../autonomy.js';
|
|
2
|
+
import { unconfirmedFix } from '../guards/answer-confirmation.js';
|
|
2
3
|
import { emitGaps, emitToml, toSiblingRows } from '../emit.js';
|
|
3
4
|
/**
|
|
4
5
|
* Who gave an interview answer: a person, the setup agent choosing a default it was allowed to
|
|
5
|
-
* choose,
|
|
6
|
-
*
|
|
6
|
+
* choose, no one said (an answers file that does not attribute a value cockpit never proposes), or
|
|
7
|
+
* the setup agent accepting the value init read from exact sources, which init checks against what
|
|
8
|
+
* it reads. A person's answer is written as stated and a derived one with its source; the others
|
|
9
|
+
* are listed under `unconfirmed`.
|
|
7
10
|
*/
|
|
8
|
-
export const ANSWER_PROVENANCES = ['operator-confirmed', 'agent-default', 'unattributed'];
|
|
11
|
+
export const ANSWER_PROVENANCES = ['operator-confirmed', 'agent-default', 'unattributed', 'derived'];
|
|
9
12
|
export function unconfirmedReason(row) {
|
|
10
13
|
return row.provenance === 'agent-default'
|
|
11
14
|
? `${row.field} was chosen by the setup agent as a default; no person stated it`
|
|
12
15
|
: `${row.field} came from an answers file that did not say who chose it; no person is known to have stated it`;
|
|
13
16
|
}
|
|
14
|
-
export const UNCONFIRMED_FIX = 'confirm the value with whoever owns the product and correct it in cockpit.toml if it is wrong, then delete its entry from unconfirmed and run npx --no cockpit sync --config <your cockpit.toml>';
|
|
15
17
|
function renderUnconfirmed(rows = []) {
|
|
16
18
|
if (rows.length === 0)
|
|
17
19
|
return '';
|
|
18
|
-
return `${rows.map(row => `# Unconfirmed: ${unconfirmedReason(row)}.\n`).join('')}# To confirm: ${
|
|
20
|
+
return `${rows.map(row => `# Unconfirmed: ${unconfirmedReason(row)}.\n`).join('')}# To confirm: ${unconfirmedFix(rows.map(row => row.field))}; until then doctor warns.\n`;
|
|
21
|
+
}
|
|
22
|
+
function renderDerived(rows) {
|
|
23
|
+
return rows.map(row => `# Derived: ${row.field} was read from ${row.source} and accepted by the setup agent; bring-up proves it.\n`).join('');
|
|
19
24
|
}
|
|
20
25
|
/** Every decision with its default, commented out: flip one to "person" to take that decision yourself. */
|
|
21
26
|
function renderDecisionDefaults() {
|
|
@@ -27,12 +32,29 @@ function renderDecisionDefaults() {
|
|
|
27
32
|
...table('work.gates', GATE_DEFAULTS), ...table('autonomy', AUTONOMY_DEFAULTS),
|
|
28
33
|
].join('\n')}\n`;
|
|
29
34
|
}
|
|
35
|
+
// A wrong value in one of these widens what an agent may do or delete, so a person confirms it.
|
|
36
|
+
const PERSON_CONFIRMED_TARGETS = new Set(['guards.protected_branches', 'guards.allow', 'guards.deny',
|
|
37
|
+
'mcp.approved', 'environment.resettable_volumes', 'environment.generated_host_paths']);
|
|
38
|
+
/**
|
|
39
|
+
* Who confirms a surfaced value: the setup agent for a schema default or the cockpit's own layout,
|
|
40
|
+
* which bring-up proves, and a person for a security boundary or a value a registry dialect left
|
|
41
|
+
* to a guess.
|
|
42
|
+
*/
|
|
43
|
+
export function confirmedBy(attribution) {
|
|
44
|
+
if (PERSON_CONFIRMED_TARGETS.has(attribution.target))
|
|
45
|
+
return 'person';
|
|
46
|
+
return attribution.from === 'default' || attribution.target === 'cockpit.siblings_root' ? 'agent' : 'person';
|
|
47
|
+
}
|
|
30
48
|
function renderAttributions(attributions) {
|
|
31
49
|
if (attributions.length === 0)
|
|
32
50
|
return '';
|
|
33
51
|
const lines = ['# Provenance — every unread value names its source and reason.'];
|
|
34
|
-
for (const
|
|
35
|
-
|
|
52
|
+
for (const [by, heading] of [['agent', '# The setup agent accepts these: schema defaults and the cockpit\'s own layout, which bring-up proves.'],
|
|
53
|
+
['person', '# A person confirms these, and the defaults digest covers only them: each bounds what an agent may do.']]) {
|
|
54
|
+
const rows = attributions.filter(row => confirmedBy(row) === by);
|
|
55
|
+
if (rows.length === 0)
|
|
56
|
+
continue;
|
|
57
|
+
lines.push(heading, ...rows.map(row => `# [${row.from}] ${row.target} = ${JSON.stringify(row.value)}: ${row.because}`));
|
|
36
58
|
}
|
|
37
59
|
return `${lines.join('\n')}\n`;
|
|
38
60
|
}
|
|
@@ -77,6 +99,6 @@ export function renderIncompleteDocument(model, schemaDirective, configuration)
|
|
|
77
99
|
].join('');
|
|
78
100
|
}
|
|
79
101
|
/** Decisions are comments: the schema has no field for them, and the reader of the file needs them. */
|
|
80
|
-
export function renderCompleteDocument(config, schemaDirective, decisions = [], unconfirmed = []) {
|
|
81
|
-
return `#:schema ${schemaDirective}\n${decisions.map(decision => `# Decision: ${decision}\n`).join('')}${renderUnconfirmed(unconfirmed)}${emitToml(config)}${renderDecisionDefaults()}`;
|
|
102
|
+
export function renderCompleteDocument(config, schemaDirective, decisions = [], unconfirmed = [], derived = []) {
|
|
103
|
+
return `#:schema ${schemaDirective}\n${decisions.map(decision => `# Decision: ${decision}\n`).join('')}${renderDerived(derived)}${renderUnconfirmed(unconfirmed)}${emitToml(config)}${renderDecisionDefaults()}`;
|
|
82
104
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A path or glob (`*`, `?`, `**`), optionally `<slug>:`-prefixed, without `..` segments or a leading `/`. */
|
|
2
|
+
export declare const REPOSITORY_PATH: RegExp;
|
|
3
|
+
/** One file or directory, optionally `<slug>:`-prefixed: no wildcards, no `.` or `..` segments, no leading or trailing `/`. */
|
|
4
|
+
export declare const REPOSITORY_FILE: RegExp;
|
|
5
|
+
/** The sibling a reference names, if any, and the path inside that repository. */
|
|
6
|
+
export declare function splitRepositoryPath(reference: string): Readonly<{
|
|
7
|
+
slug?: string;
|
|
8
|
+
path: string;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// A path in one of a cockpit's repositories: `path` in the cockpit's own, or `<sibling slug>:path` in a
|
|
2
|
+
// sibling. Work-order scopes and sources, the [docs] declarations and every reader of them spell and
|
|
3
|
+
// split it here, so a reference one admits is the reference the other resolves.
|
|
4
|
+
const SLUG = '[a-z0-9][a-z0-9-]{0,63}';
|
|
5
|
+
// Never absolute or climbing. The climbing check looks past the sibling prefix, which would otherwise
|
|
6
|
+
// consume the `:` before `..`.
|
|
7
|
+
/** A path or glob (`*`, `?`, `**`), optionally `<slug>:`-prefixed, without `..` segments or a leading `/`. */
|
|
8
|
+
export const REPOSITORY_PATH = new RegExp(`^(?!(?:${SLUG}:)?(?:.*/)?\\.\\.(?:/|$))(?:${SLUG}:)?(?![/])[A-Za-z0-9._@+\\-/*?]+$`);
|
|
9
|
+
/** One file or directory, optionally `<slug>:`-prefixed: no wildcards, no `.` or `..` segments, no leading or trailing `/`. */
|
|
10
|
+
export const REPOSITORY_FILE = new RegExp(`^(?!(?:${SLUG}:)?(?:.*/)?\\.\\.?(?:/|$))(?:${SLUG}:)?(?![/])[A-Za-z0-9._@+\\-/]*[A-Za-z0-9._@+-]$`);
|
|
11
|
+
const PREFIXED = new RegExp(`^(${SLUG}):(.*)$`);
|
|
12
|
+
/** The sibling a reference names, if any, and the path inside that repository. */
|
|
13
|
+
export function splitRepositoryPath(reference) {
|
|
14
|
+
const match = PREFIXED.exec(reference);
|
|
15
|
+
return match ? { slug: match[1], path: match[2] } : { path: reference };
|
|
16
|
+
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -16,15 +16,6 @@ export declare const AuthPosture: z.ZodEnum<{
|
|
|
16
16
|
none: "none";
|
|
17
17
|
real: "real";
|
|
18
18
|
}>;
|
|
19
|
-
declare const Toolchain: z.ZodEnum<{
|
|
20
|
-
dotnet: "dotnet";
|
|
21
|
-
go: "go";
|
|
22
|
-
node: "node";
|
|
23
|
-
none: "none";
|
|
24
|
-
python: "python";
|
|
25
|
-
ruby: "ruby";
|
|
26
|
-
rust: "rust";
|
|
27
|
-
}>;
|
|
28
19
|
export declare const EnvironmentFile: z.ZodObject<{
|
|
29
20
|
template: z.ZodString;
|
|
30
21
|
instance: z.ZodString;
|
|
@@ -37,6 +28,8 @@ export declare const MachineFloor: z.ZodObject<{
|
|
|
37
28
|
cold_start_seconds: z.ZodNumber;
|
|
38
29
|
}, z.core.$strict>;
|
|
39
30
|
export declare const ResettableVolumeId: z.ZodString;
|
|
31
|
+
/** A Compose profile name, in the lowercase spelling every stack command and state record shares. */
|
|
32
|
+
export declare const ComposeProfileName: z.ZodString;
|
|
40
33
|
export declare const GeneratedHostPath: z.ZodString;
|
|
41
34
|
export declare function parseBrowserNetworkExposure(value: string | undefined, reason: string | undefined): Readonly<{
|
|
42
35
|
value: string;
|
|
@@ -116,6 +109,7 @@ export declare const Environment: z.ZodObject<{
|
|
|
116
109
|
resettable_volumes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
117
110
|
generated_host_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
118
111
|
compose_files: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
112
|
+
profiles: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
119
113
|
entrypoint_derivatives: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
120
114
|
name: z.ZodString;
|
|
121
115
|
kind: z.ZodEnum<{
|
|
@@ -191,6 +185,7 @@ export declare const Sibling: z.ZodObject<{
|
|
|
191
185
|
template: z.ZodString;
|
|
192
186
|
instance: z.ZodString;
|
|
193
187
|
}, z.core.$strict>>>;
|
|
188
|
+
rebuild_inputs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
194
189
|
derives: z.ZodOptional<z.ZodObject<{
|
|
195
190
|
mcp_sources: z.ZodArray<z.ZodObject<{
|
|
196
191
|
path: z.ZodString;
|
|
@@ -275,6 +270,11 @@ export declare const Work: z.ZodObject<{
|
|
|
275
270
|
ci: "ci";
|
|
276
271
|
person: "person";
|
|
277
272
|
}>>;
|
|
273
|
+
acknowledge: z.ZodOptional<z.ZodEnum<{
|
|
274
|
+
agent: "agent";
|
|
275
|
+
ci: "ci";
|
|
276
|
+
person: "person";
|
|
277
|
+
}>>;
|
|
278
278
|
}, z.core.$strict>>;
|
|
279
279
|
}, z.core.$strict>;
|
|
280
280
|
export declare const Autonomy: z.ZodObject<{
|
|
@@ -301,6 +301,12 @@ export declare const Autonomy: z.ZodObject<{
|
|
|
301
301
|
export declare const BROWSER_DRIVER_VERSION: RegExp;
|
|
302
302
|
/** Playwright refuses a client and server whose major.minor differ, so only that much must agree. */
|
|
303
303
|
export declare function browserDriversCompatible(left: string, right: string): boolean;
|
|
304
|
+
/** The data posture that lets browser tools run without prompts: isolated, not restored, not reaching production. */
|
|
305
|
+
export declare const browserDataQualifies: (data: Readonly<{
|
|
306
|
+
mode: string;
|
|
307
|
+
isolated: boolean;
|
|
308
|
+
reaches_production: boolean;
|
|
309
|
+
}>) => boolean;
|
|
304
310
|
export declare const Browser: z.ZodObject<{
|
|
305
311
|
engine: z.ZodDefault<z.ZodEnum<{
|
|
306
312
|
chromium: "chromium";
|
|
@@ -366,7 +372,7 @@ export declare const Browser: z.ZodObject<{
|
|
|
366
372
|
isolated: z.ZodBoolean;
|
|
367
373
|
reaches_production: z.ZodBoolean;
|
|
368
374
|
}, z.core.$strict>;
|
|
369
|
-
request_preapproval: z.
|
|
375
|
+
request_preapproval: z.ZodOptional<z.ZodBoolean>;
|
|
370
376
|
artifacts: z.ZodObject<{
|
|
371
377
|
mcp: z.ZodString;
|
|
372
378
|
cli: z.ZodString;
|
|
@@ -375,6 +381,7 @@ export declare const Browser: z.ZodObject<{
|
|
|
375
381
|
}, z.core.$strict>;
|
|
376
382
|
export declare const TestingName: z.ZodString;
|
|
377
383
|
export declare const Testing: z.ZodObject<{
|
|
384
|
+
test_files: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
378
385
|
stages: z.ZodArray<z.ZodObject<{
|
|
379
386
|
id: z.ZodString;
|
|
380
387
|
command: z.ZodArray<z.ZodString>;
|
|
@@ -407,14 +414,6 @@ export declare const Testing: z.ZodObject<{
|
|
|
407
414
|
sha256: z.ZodString;
|
|
408
415
|
}, z.core.$strict>>;
|
|
409
416
|
}, z.core.$strict>;
|
|
410
|
-
declare const SurfaceSource: z.ZodObject<{
|
|
411
|
-
path: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
412
|
-
bytes: z.ZodString;
|
|
413
|
-
}, z.core.$strict>;
|
|
414
|
-
declare const SurfaceOverrideReference: z.ZodObject<{
|
|
415
|
-
name: z.ZodString;
|
|
416
|
-
sha256: z.ZodString;
|
|
417
|
-
}, z.core.$strict>;
|
|
418
417
|
export declare const SurfaceDeclaration: z.ZodObject<{
|
|
419
418
|
name: z.ZodString;
|
|
420
419
|
feature: z.ZodEnum<{
|
|
@@ -474,57 +473,6 @@ export declare const SurfaceAdoption: z.ZodObject<{
|
|
|
474
473
|
confirmed: z.ZodOptional<z.ZodBoolean>;
|
|
475
474
|
}, z.core.$strict>;
|
|
476
475
|
}, z.core.$strict>;
|
|
477
|
-
declare const CustomHarnessCapability: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
478
|
-
feature: z.ZodEnum<{
|
|
479
|
-
hooks: "hooks";
|
|
480
|
-
mcp: "mcp";
|
|
481
|
-
permissions: "permissions";
|
|
482
|
-
rules: "rules";
|
|
483
|
-
skills: "skills";
|
|
484
|
-
subagents: "subagents";
|
|
485
|
-
}>;
|
|
486
|
-
measured_on: z.ZodString;
|
|
487
|
-
spelling: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
488
|
-
control: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
489
|
-
mechanism: z.ZodObject<{
|
|
490
|
-
module: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
491
|
-
export: z.ZodString;
|
|
492
|
-
}, z.core.$strict>;
|
|
493
|
-
state: z.ZodLiteral<"enforced">;
|
|
494
|
-
evidence: z.ZodObject<{
|
|
495
|
-
reference: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
496
|
-
sha256: z.ZodString;
|
|
497
|
-
}, z.core.$strict>;
|
|
498
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
499
|
-
feature: z.ZodEnum<{
|
|
500
|
-
hooks: "hooks";
|
|
501
|
-
mcp: "mcp";
|
|
502
|
-
permissions: "permissions";
|
|
503
|
-
rules: "rules";
|
|
504
|
-
skills: "skills";
|
|
505
|
-
subagents: "subagents";
|
|
506
|
-
}>;
|
|
507
|
-
measured_on: z.ZodString;
|
|
508
|
-
spelling: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
509
|
-
control: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
510
|
-
mechanism: z.ZodObject<{
|
|
511
|
-
module: z.ZodIntersection<z.ZodString, z.ZodString>;
|
|
512
|
-
export: z.ZodString;
|
|
513
|
-
}, z.core.$strict>;
|
|
514
|
-
state: z.ZodLiteral<"instructed">;
|
|
515
|
-
}, z.core.$strict>, z.ZodObject<{
|
|
516
|
-
feature: z.ZodEnum<{
|
|
517
|
-
hooks: "hooks";
|
|
518
|
-
mcp: "mcp";
|
|
519
|
-
permissions: "permissions";
|
|
520
|
-
rules: "rules";
|
|
521
|
-
skills: "skills";
|
|
522
|
-
subagents: "subagents";
|
|
523
|
-
}>;
|
|
524
|
-
measured_on: z.ZodString;
|
|
525
|
-
state: z.ZodLiteral<"unavailable">;
|
|
526
|
-
reason: z.ZodString;
|
|
527
|
-
}, z.core.$strict>], "state">;
|
|
528
476
|
export declare const CustomHarness: z.ZodObject<{
|
|
529
477
|
name: z.ZodString;
|
|
530
478
|
capabilities: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -732,6 +680,7 @@ export declare function configurationDefaults(): {
|
|
|
732
680
|
amend?: "agent" | "ci" | "person" | undefined;
|
|
733
681
|
answer?: "agent" | "ci" | "person" | undefined;
|
|
734
682
|
signoff?: "agent" | "ci" | "person" | undefined;
|
|
683
|
+
acknowledge?: "agent" | "ci" | "person" | undefined;
|
|
735
684
|
};
|
|
736
685
|
};
|
|
737
686
|
autonomy: {
|
|
@@ -757,6 +706,7 @@ export declare function configurationDefaults(): {
|
|
|
757
706
|
resettable_volumes: string[];
|
|
758
707
|
generated_host_paths: string[];
|
|
759
708
|
compose_files: string[];
|
|
709
|
+
profiles: string[];
|
|
760
710
|
entrypoint_derivatives: {
|
|
761
711
|
name: string;
|
|
762
712
|
kind: "advertised_listener" | "callback_url" | "cors_origin" | "entrypoint" | "origin" | "public_base_url";
|
|
@@ -847,6 +797,11 @@ export declare function configurationDefaults(): {
|
|
|
847
797
|
* stated but were guessed is the failure cockpit exists to prevent.
|
|
848
798
|
*/
|
|
849
799
|
export declare const UNCONFIRMABLE_ANSWERS: readonly ['cockpit.name', 'sibling', 'estate.runnable', 'ports.bases', 'environment.install_policies', 'environment.test_data', 'environment.compose_files', 'environment.machine', 'environment.posture', 'testing', 'guards'];
|
|
800
|
+
export declare const Docs: z.ZodObject<{
|
|
801
|
+
living: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
802
|
+
decisions: z.ZodOptional<z.ZodString>;
|
|
803
|
+
decisions_index: z.ZodOptional<z.ZodString>;
|
|
804
|
+
}, z.core.$strict>;
|
|
850
805
|
export declare const CockpitConfig: z.ZodObject<{
|
|
851
806
|
unconfirmed: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
852
807
|
"cockpit.name": "cockpit.name";
|
|
@@ -898,6 +853,7 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
898
853
|
template: z.ZodString;
|
|
899
854
|
instance: z.ZodString;
|
|
900
855
|
}, z.core.$strict>>>;
|
|
856
|
+
rebuild_inputs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
901
857
|
derives: z.ZodOptional<z.ZodObject<{
|
|
902
858
|
mcp_sources: z.ZodArray<z.ZodObject<{
|
|
903
859
|
path: z.ZodString;
|
|
@@ -978,6 +934,11 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
978
934
|
ci: "ci";
|
|
979
935
|
person: "person";
|
|
980
936
|
}>>;
|
|
937
|
+
acknowledge: z.ZodOptional<z.ZodEnum<{
|
|
938
|
+
agent: "agent";
|
|
939
|
+
ci: "ci";
|
|
940
|
+
person: "person";
|
|
941
|
+
}>>;
|
|
981
942
|
}, z.core.$strict>>;
|
|
982
943
|
}, z.core.$strict>>;
|
|
983
944
|
autonomy: z.ZodPrefault<z.ZodObject<{
|
|
@@ -1066,7 +1027,7 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
1066
1027
|
isolated: z.ZodBoolean;
|
|
1067
1028
|
reaches_production: z.ZodBoolean;
|
|
1068
1029
|
}, z.core.$strict>;
|
|
1069
|
-
request_preapproval: z.
|
|
1030
|
+
request_preapproval: z.ZodOptional<z.ZodBoolean>;
|
|
1070
1031
|
artifacts: z.ZodObject<{
|
|
1071
1032
|
mcp: z.ZodString;
|
|
1072
1033
|
cli: z.ZodString;
|
|
@@ -1074,6 +1035,7 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
1074
1035
|
}, z.core.$strict>;
|
|
1075
1036
|
}, z.core.$strict>>;
|
|
1076
1037
|
testing: z.ZodOptional<z.ZodObject<{
|
|
1038
|
+
test_files: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1077
1039
|
stages: z.ZodArray<z.ZodObject<{
|
|
1078
1040
|
id: z.ZodString;
|
|
1079
1041
|
command: z.ZodArray<z.ZodString>;
|
|
@@ -1137,6 +1099,7 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
1137
1099
|
resettable_volumes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1138
1100
|
generated_host_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1139
1101
|
compose_files: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1102
|
+
profiles: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1140
1103
|
entrypoint_derivatives: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1141
1104
|
name: z.ZodString;
|
|
1142
1105
|
kind: z.ZodEnum<{
|
|
@@ -1278,11 +1241,15 @@ export declare const CockpitConfig: z.ZodObject<{
|
|
|
1278
1241
|
}, z.core.$strict>;
|
|
1279
1242
|
}, z.core.$strict>>>;
|
|
1280
1243
|
}, z.core.$strict>>;
|
|
1244
|
+
docs: z.ZodOptional<z.ZodObject<{
|
|
1245
|
+
living: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1246
|
+
decisions: z.ZodOptional<z.ZodString>;
|
|
1247
|
+
decisions_index: z.ZodOptional<z.ZodString>;
|
|
1248
|
+
}, z.core.$strict>>;
|
|
1281
1249
|
}, z.core.$strict>;
|
|
1282
1250
|
export type CockpitConfig = z.infer<typeof CockpitConfig>;
|
|
1283
1251
|
export type Sibling = z.infer<typeof Sibling>;
|
|
1284
1252
|
export type Acquire = z.infer<typeof Acquire>;
|
|
1285
|
-
export type Toolchain = z.infer<typeof Toolchain>;
|
|
1286
1253
|
export type AddressingPosture = z.infer<typeof AddressingPosture>;
|
|
1287
1254
|
export type AuthPosture = z.infer<typeof AuthPosture>;
|
|
1288
1255
|
export type EnvironmentFile = z.infer<typeof EnvironmentFile>;
|
|
@@ -1293,17 +1260,17 @@ export type EntrypointDerivative = z.infer<typeof EntrypointDerivative>;
|
|
|
1293
1260
|
export type InstallPolicy = z.infer<typeof InstallPolicy>;
|
|
1294
1261
|
export type Browser = z.infer<typeof Browser>;
|
|
1295
1262
|
export type Testing = z.infer<typeof Testing>;
|
|
1263
|
+
export type Docs = z.infer<typeof Docs>;
|
|
1296
1264
|
export type Provenance = z.infer<typeof Provenance>;
|
|
1297
|
-
export type SurfaceSource = z.infer<typeof SurfaceSource>;
|
|
1298
|
-
export type SurfaceOverrideReference = z.infer<typeof SurfaceOverrideReference>;
|
|
1299
1265
|
export type SurfaceDeclaration = z.infer<typeof SurfaceDeclaration>;
|
|
1300
1266
|
export type SurfaceOverlay = z.infer<typeof SurfaceOverlay>;
|
|
1301
1267
|
export type SurfaceAdoption = z.infer<typeof SurfaceAdoption>;
|
|
1302
|
-
export type CustomHarnessCapability = z.infer<typeof CustomHarnessCapability>;
|
|
1303
1268
|
export type CustomHarness = z.infer<typeof CustomHarness>;
|
|
1304
1269
|
export type Surfaces = z.infer<typeof Surfaces>;
|
|
1305
1270
|
/** Rows the stack bind-mounts under the given profile set — the projection's import list. */
|
|
1306
|
-
export declare function mounted
|
|
1271
|
+
export declare function mounted<Row extends Readonly<Pick<Sibling, 'mount'>>>(cfg: Readonly<{
|
|
1272
|
+
sibling: readonly Row[];
|
|
1273
|
+
}>, profiles: readonly string[]): Row[];
|
|
1307
1274
|
/**
|
|
1308
1275
|
* The SHA-256 that identifies a running stack: ownership labels, the generation, saved progress and
|
|
1309
1276
|
* data history are keyed by it rather than by the bytes of cockpit.toml. Keying them by the file
|
package/dist/schema.js
CHANGED
|
@@ -8,6 +8,7 @@ import { GUARD_HOST_LIMITS, GUARD_HOST_PATTERN, normalizeGuardHost } from './gua
|
|
|
8
8
|
import { ADOPTABLE_SURFACE_PATHS, ADOPTED_SURFACE_ROOT, SURFACE_BUNDLE_FORMATS, SURFACE_FEATURES, SURFACE_TARGETS, surfaceSourcesMatchFeature } from './surfaces/contract.js';
|
|
9
9
|
import { DEFAULT_SURFACE_TOOLS, GUARD_SURFACE_TARGETS } from './surfaces/harness-registry.js';
|
|
10
10
|
import { RefusalError, errorCause } from './environment/contract.js';
|
|
11
|
+
import { REPOSITORY_FILE, REPOSITORY_PATH, splitRepositoryPath } from './repository-path.js';
|
|
11
12
|
export const STRUCTURED_INPUT_ENTRY_LIMIT = 4_096;
|
|
12
13
|
// Zod cannot reflect a regex in a string type; successful parses satisfy this narrower output.
|
|
13
14
|
export const Mount = z
|
|
@@ -57,6 +58,8 @@ export const MachineFloor = z
|
|
|
57
58
|
})
|
|
58
59
|
.strict();
|
|
59
60
|
export const ResettableVolumeId = z.string().regex(/^[a-z0-9][a-z0-9_.-]*$/);
|
|
61
|
+
/** A Compose profile name, in the lowercase spelling every stack command and state record shares. */
|
|
62
|
+
export const ComposeProfileName = z.string().max(64).regex(/^[a-z0-9][a-z0-9_.-]*$/, 'expected a lowercase Compose profile name');
|
|
60
63
|
export const GeneratedHostPath = SafeRelativePath;
|
|
61
64
|
export function parseBrowserNetworkExposure(value, reason) {
|
|
62
65
|
const exposure = value ?? '<loopback>';
|
|
@@ -151,6 +154,7 @@ export const Environment = z
|
|
|
151
154
|
resettable_volumes: z.array(ResettableVolumeId).default([]).describe('Compose volumes that reset may delete and recreate, named by their Compose key.'),
|
|
152
155
|
generated_host_paths: z.array(GeneratedHostPath).default([]).describe('Host paths cockpit generates and owns, relative to the cockpit.'),
|
|
153
156
|
compose_files: z.array(LocalComposePath).default([]).describe('Compose files, relative to the cockpit, that make up the stack; cockpit runs them as written.'),
|
|
157
|
+
profiles: z.array(ComposeProfileName).max(64).default([]).describe('Compose profiles every up and session activates; up --profile adds more for one run.'),
|
|
154
158
|
entrypoint_derivatives: z.array(EntrypointDerivative).default([]).describe('Addresses derived from leased ports, such as application origins and callback URLs.'),
|
|
155
159
|
install_policies: z.array(InstallPolicy).default([]).describe('The build and test commands the guard admits for each toolchain and lockfile.'),
|
|
156
160
|
// Product data lives in the resettable volumes, so the seed reruns exactly when one of them is
|
|
@@ -166,6 +170,7 @@ export const Environment = z
|
|
|
166
170
|
resettable_volumes: environment.resettable_volumes,
|
|
167
171
|
generated_host_paths: environment.generated_host_paths,
|
|
168
172
|
compose_files: environment.compose_files,
|
|
173
|
+
profiles: environment.profiles,
|
|
169
174
|
entrypoint_derivatives: environment.entrypoint_derivatives.map((row) => row.name),
|
|
170
175
|
posture_requirements: environment.posture_requirements?.map((row) => row.requirement) ?? [],
|
|
171
176
|
};
|
|
@@ -256,6 +261,9 @@ export const Sibling = z
|
|
|
256
261
|
// Printed when the checkout is missing, so it says what the absence costs.
|
|
257
262
|
purpose: z.string().min(1).describe('What the sibling is for; printed when its checkout is missing.'),
|
|
258
263
|
environment_files: z.array(EnvironmentFile).optional().describe('Template and instance environment file pairs the sibling needs.'),
|
|
264
|
+
// A running stack keeps the dependencies and schema it started with; a pulled lockfile or a new
|
|
265
|
+
// migration behind it fails like a product bug. Lockfiles are watched without this list.
|
|
266
|
+
rebuild_inputs: z.array(SafeRelativePath).max(64).optional().describe('Files or directories in the sibling, beyond its lockfiles, whose change leaves a running stack stale, such as a migrations directory.'),
|
|
259
267
|
derives: SiblingDerives.optional().describe('Facts about the sibling that cockpit derives rows or MCP servers from.'),
|
|
260
268
|
})
|
|
261
269
|
.strict()
|
|
@@ -388,9 +396,10 @@ export const WORK_GRADING = ['independent', 'checks', 'self'];
|
|
|
388
396
|
const WorkGates = z
|
|
389
397
|
.object({
|
|
390
398
|
accept: Decider.optional().describe('Who accepts a draft work order: agent, person or ci. Default agent.'),
|
|
391
|
-
amend: Decider.optional().describe('Who accepts a changed contract. Default agent. Removing
|
|
399
|
+
amend: Decider.optional().describe('Who accepts a changed contract. Default agent. Removing an accepted criterion or gate always needs a person or ci; an agent\'s rewrite of a criterion, scope, non-goal or objective is judged at the next grade, and needs a person under checks grading.'),
|
|
392
400
|
answer: Decider.optional().describe('Who answers an open question on an order. Default agent.'),
|
|
393
401
|
signoff: Decider.optional().describe('Who closes a graded order. Default agent.'),
|
|
402
|
+
acknowledge: Decider.optional().describe('Who acknowledges that an order weakened tests, which checks grading otherwise fails; under independent and self grading the acknowledgement is context for the verdict. Default agent.'),
|
|
394
403
|
})
|
|
395
404
|
.strict();
|
|
396
405
|
export const Work = z
|
|
@@ -446,6 +455,8 @@ const BrowserArtifactRoots = z.object({
|
|
|
446
455
|
}
|
|
447
456
|
}
|
|
448
457
|
});
|
|
458
|
+
/** The data posture that lets browser tools run without prompts: isolated, not restored, not reaching production. */
|
|
459
|
+
export const browserDataQualifies = (data) => data.mode !== 'restored' && data.isolated && !data.reaches_production;
|
|
449
460
|
export const Browser = z.object({
|
|
450
461
|
engine: z.enum(['chromium', 'firefox', 'webkit']).default('chromium').describe('Browser engine to drive.'),
|
|
451
462
|
network_exposure: z.string().min(1).max(512).regex(/^[a-z0-9.*:<>\[\],-]+$/).refine((value) => {
|
|
@@ -494,7 +505,7 @@ export const Browser = z.object({
|
|
|
494
505
|
isolated: z.boolean().describe('True when the data is separate from anyone else\'s.'),
|
|
495
506
|
reaches_production: z.boolean().describe('True when browser actions can affect production.'),
|
|
496
507
|
}).strict().describe('Statement about the data the browser touches; cockpit cannot observe it.'),
|
|
497
|
-
request_preapproval: z.boolean().
|
|
508
|
+
request_preapproval: z.boolean().optional().describe('Run browser tools without prompts; allowed only on isolated, non-production, non-restored data. Defaults to true when data qualifies and false otherwise.'),
|
|
498
509
|
artifacts: BrowserArtifactRoots.describe('Generated host paths for browser output.'),
|
|
499
510
|
}).strict().superRefine((browser, ctx) => {
|
|
500
511
|
try {
|
|
@@ -538,7 +549,7 @@ export const Browser = z.object({
|
|
|
538
549
|
if (paths.some((path) => !path.startsWith(`${browser.artifacts.auth}/`))) {
|
|
539
550
|
ctx.addIssue({ code: 'custom', path: ['authentication', 'states'], message: 'browser authentication state must stay inside the auth artifact root' });
|
|
540
551
|
}
|
|
541
|
-
if (browser.request_preapproval && (browser.data
|
|
552
|
+
if (browser.request_preapproval && !browserDataQualifies(browser.data)) {
|
|
542
553
|
ctx.addIssue({ code: 'custom', path: ['request_preapproval'], message: 'browser preapproval requires isolated empty or seeded data without production reach' });
|
|
543
554
|
}
|
|
544
555
|
});
|
|
@@ -555,6 +566,8 @@ const TestingSelect = z.object({
|
|
|
555
566
|
route: TestingSelectArguments.optional().describe('Arguments that select tests by route; {value} becomes the selection.'),
|
|
556
567
|
}).strict();
|
|
557
568
|
export const Testing = z.object({
|
|
569
|
+
test_files: z.array(z.string().min(1).max(512).regex(/^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._@+\-/*?]+$/, 'a relative path or glob, without .. or a leading /')).min(1).max(64).optional()
|
|
570
|
+
.describe('Paths and globs, relative to each checkout, that hold tests. Grading fails an order that deletes, skips or loosens what they match. Defaults to common layouts.'),
|
|
558
571
|
stages: z.array(z.object({
|
|
559
572
|
id: TestingName.describe('Name of the stage.'),
|
|
560
573
|
command: TestingCommand.describe('Command to run, as an argument list.'),
|
|
@@ -777,6 +790,27 @@ export function configurationDefaults() {
|
|
|
777
790
|
export const UNCONFIRMABLE_ANSWERS = ['cockpit.name', 'sibling', 'estate.runnable', 'ports.bases', 'environment.install_policies',
|
|
778
791
|
'environment.test_data', 'environment.compose_files', 'environment.machine', 'environment.posture',
|
|
779
792
|
'testing', 'guards'];
|
|
793
|
+
// `path` in the cockpit's own repository, or `<sibling slug>:path` in a sibling, spelt as a work
|
|
794
|
+
// order's scope is. Living documents may be globs; the decision paths name one file or directory.
|
|
795
|
+
const DocsGlob = z.string().max(1_024).regex(REPOSITORY_PATH, 'a relative path, optionally <sibling slug>:path, without .. or a leading /');
|
|
796
|
+
const DocsFile = z.string().max(1_024).regex(REPOSITORY_FILE, 'one relative path without wildcards, optionally <sibling slug>:path, without . or .. segments or a leading or trailing /');
|
|
797
|
+
const repositoryOf = (path) => splitRepositoryPath(path).slug ?? '.';
|
|
798
|
+
export const Docs = z.object({
|
|
799
|
+
living: z.array(DocsGlob).max(64).default([])
|
|
800
|
+
.describe('Globs of the Markdown documents that must stay true; docs check reports the paths and make targets they cite that the repository has since removed.'),
|
|
801
|
+
decisions: DocsFile.optional().describe('Directory of decision records, such as docs/adr. Work orders record their lasting decisions there, and docs check reports duplicate numbers, missing statuses and broken supersedes links.'),
|
|
802
|
+
decisions_index: DocsFile.optional().describe('Index file that links every decision record; a record cockpit writes is appended to it, and docs check reports records it omits and links to records that do not exist.'),
|
|
803
|
+
}).strict().superRefine((docs, ctx) => {
|
|
804
|
+
// A [docs] table that names nothing would parse and do nothing.
|
|
805
|
+
if (docs.living.length === 0 && docs.decisions === undefined)
|
|
806
|
+
ctx.addIssue({ code: 'custom', path: [], message: '[docs] declares neither living documents nor decisions' });
|
|
807
|
+
// An index with no records directory, or of another repository's records, would check nothing.
|
|
808
|
+
if (docs.decisions_index !== undefined && docs.decisions === undefined)
|
|
809
|
+
ctx.addIssue({ code: 'custom', path: ['decisions_index'], message: 'decisions_index needs decisions, the directory it indexes' });
|
|
810
|
+
else if (docs.decisions_index !== undefined && repositoryOf(docs.decisions_index) !== repositoryOf(docs.decisions)) {
|
|
811
|
+
ctx.addIssue({ code: 'custom', path: ['decisions_index'], message: 'decisions_index must be in the same repository as decisions, so its links resolve' });
|
|
812
|
+
}
|
|
813
|
+
});
|
|
780
814
|
export const CockpitConfig = z
|
|
781
815
|
.object({
|
|
782
816
|
unconfirmed: z.array(z.enum(UNCONFIRMABLE_ANSWERS)).min(1).max(UNCONFIRMABLE_ANSWERS.length)
|
|
@@ -792,6 +826,7 @@ export const CockpitConfig = z
|
|
|
792
826
|
testing: Testing.optional().describe('Test stages and gates.'),
|
|
793
827
|
environment: Environment.prefault({}).describe('How the stack is reached, signed in to, built and kept.'),
|
|
794
828
|
surfaces: Surfaces.prefault({}).describe('Instructions, skills and settings generated for agent tools.'),
|
|
829
|
+
docs: Docs.optional().describe('Living documents and decision records: docs check keeps them true, and work orders record their decisions there.'),
|
|
795
830
|
})
|
|
796
831
|
.strict()
|
|
797
832
|
.superRefine((cfg, ctx) => {
|
|
@@ -872,20 +907,36 @@ export const CockpitConfig = z
|
|
|
872
907
|
message: `resettable volume ${JSON.stringify(name)} names no volume: the environment declares no compose_files`,
|
|
873
908
|
});
|
|
874
909
|
});
|
|
910
|
+
cfg.environment.profiles.forEach((name, index) => {
|
|
911
|
+
ctx.addIssue({
|
|
912
|
+
code: 'custom', path: ['environment', 'profiles', index],
|
|
913
|
+
message: `profile ${JSON.stringify(name)} activates nothing: the environment declares no compose_files`,
|
|
914
|
+
});
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
if (cfg.docs) {
|
|
918
|
+
const paths = [...cfg.docs.living.map((path, index) => ({ path, at: ['docs', 'living', index] })),
|
|
919
|
+
...cfg.docs.decisions === undefined ? [] : [{ path: cfg.docs.decisions, at: ['docs', 'decisions'] }],
|
|
920
|
+
...cfg.docs.decisions_index === undefined ? [] : [{ path: cfg.docs.decisions_index, at: ['docs', 'decisions_index'] }]];
|
|
921
|
+
for (const { path, at } of paths) {
|
|
922
|
+
const slug = repositoryOf(path);
|
|
923
|
+
if (slug !== '.' && !cfg.sibling.some(row => row.slug === slug)) {
|
|
924
|
+
ctx.addIssue({ code: 'custom', path: at, message: `${JSON.stringify(path)} names sibling "${slug}", which no [[sibling]] declares` });
|
|
925
|
+
}
|
|
926
|
+
}
|
|
875
927
|
}
|
|
876
|
-
//
|
|
877
|
-
//
|
|
878
|
-
//
|
|
879
|
-
// normal case
|
|
880
|
-
// which preflight reads and a schema cannot.
|
|
928
|
+
// Not checked here: that `environment.profiles` and each `profile:<name>` mount name a
|
|
929
|
+
// profile the Compose files define. Those names live in the Compose files, which `check`
|
|
930
|
+
// and every stack command read and a schema cannot. A profile mount outside
|
|
931
|
+
// `environment.profiles` is the normal case: it stays off until `up --profile` turns it on.
|
|
881
932
|
});
|
|
882
933
|
/** Rows the stack bind-mounts under the given profile set — the projection's import list. */
|
|
883
934
|
export function mounted(cfg, profiles) {
|
|
884
935
|
return cfg.sibling.filter((s) => s.mount === 'always' || (s.mount.startsWith('profile:') && profiles.includes(s.mount.slice(8))));
|
|
885
936
|
}
|
|
886
|
-
// How a sibling is described, fetched, gated for agents
|
|
887
|
-
// a container, so editing it must leave a running stack alone.
|
|
888
|
-
const SIBLING_NON_RUNTIME_FIELDS = new Set(['purpose', 'guides', 'instruction_pointer', 'remote', 'branch', 'acquire', 'host_reason', 'gate']);
|
|
937
|
+
// How a sibling is described, fetched, gated for agents, projected into guides or watched for a stale
|
|
938
|
+
// stack. None of it reaches a container, so editing it must leave a running stack alone.
|
|
939
|
+
const SIBLING_NON_RUNTIME_FIELDS = new Set(['purpose', 'guides', 'instruction_pointer', 'remote', 'branch', 'acquire', 'host_reason', 'gate', 'rebuild_inputs']);
|
|
889
940
|
// What the host checks or reports around the containers: the machine floor and cold-start budget
|
|
890
941
|
// `up` and preflight hold the host to, the posture preflight reads, the volumes `reset` may delete,
|
|
891
942
|
// the host command that seeds them, and the URLs derived from leased ports. Hashing them made raising cold_start_seconds strand a
|