packages/core/block-contract
the uniform block contract: { id, writes, declaredScope, actions, run }.
Core engine, next. Source: packages/core/block-contract.mjs.
Type Aliases#
ActionRule#
ActionRule =
object
Defined in: packages/core/block-contract.mjs:73
One row of an action rule table. applies decides whether the action is offered at all in this state (default: yes);
blockedBy returns the reason it is offered but disabled, or a falsy value when it is available.
Type Parameters#
Type Declaration#
applies?
optionalapplies?: (state) =>boolean
Parameters
state
any
Returns
boolean
blockedBy?
optionalblockedBy?: (state) =>string|null|undefined
Parameters
state
any
Returns
string | null | undefined
blockId?
optionalblockId?:string
id
id:
string
kind
kind:
"mechanical"|"ai"|"free"
label
label:
string
requires?
optionalrequires?:string[]
Block#
Block =
object
Defined in: packages/core/block-contract.mjs:70
The uniform block contract.
Type Parameters#
Type Declaration#
actions
actions: (
state,ctx?) =>BlockAction[]
Parameters
state
any
ctx?
any
Returns
declaredScope
declaredScope: (
args,ctx?) =>DeclaredScope|null
Parameters
args
any
ctx?
any
Returns
DeclaredScope | null
id
id:
string
label?
optionallabel?:string
meta?
optionalmeta?:object
run
run: (
scope,args,ctx?) => {changedFiles:string[]; } |Promise<{changedFiles:string[]; }>
Parameters
scope
DeclaredScope | null
args
any
ctx?
any
Returns
{ changedFiles: string[]; } | Promise<{ changedFiles: string[]; }>
summary?
optionalsummary?:string
writes
writes:
boolean
BlockAction#
BlockAction =
object
Defined in: packages/core/block-contract.mjs:66
One legal next action. enabled: false is an action shown disabled, with why (the rule that forbids it here);
blockId names the block it hands over to; gates lists the guardrails an ai or free action passes through.
Type Parameters#
Type Declaration#
blockId?
optionalblockId?:string
enabled
enabled:
boolean
gates?
optionalgates?:string[]
id
id:
string
kind
kind:
"mechanical"|"ai"|"free"
label
label:
string
requires?
optionalrequires?:string[]
why?
optionalwhy?:string
DeclaredScope#
DeclaredScope =
object
Defined in: packages/core/block-contract.mjs:63
A block's declared scope; the same shape as a plan step's touches (packages/core/plan.mjs).
Type Parameters#
Type Declaration#
features?
optionalfeatures?:string[]
files?
optionalfiles?:object[]
Variables#
ACTION_KINDS#
constACTION_KINDS: readonlystring[]
Defined in: packages/core/block-contract.mjs:30
The three kinds of action a block can offer.
BLOCK_ERROR_CODES#
constBLOCK_ERROR_CODES:Readonly<{ACTION_FIELD_INVALID:"ACTION_FIELD_INVALID";ACTION_GATES_MISSING:"ACTION_GATES_MISSING";ACTION_ID_DUPLICATE:"ACTION_ID_DUPLICATE";ACTION_ID_INVALID:"ACTION_ID_INVALID";ACTION_KIND_INVALID:"ACTION_KIND_INVALID";ACTION_LABEL_INVALID:"ACTION_LABEL_INVALID";ACTION_NOT_OBJECT:"ACTION_NOT_OBJECT";ACTION_WHY_MISSING:"ACTION_WHY_MISSING";BLOCK_ACTIONS_INVALID:"BLOCK_ACTIONS_INVALID";BLOCK_FIELD_NOT_FUNCTION:"BLOCK_FIELD_NOT_FUNCTION";BLOCK_ID_INVALID:"BLOCK_ID_INVALID";BLOCK_NOT_OBJECT:"BLOCK_NOT_OBJECT";BLOCK_SCOPE_INVALID:"BLOCK_SCOPE_INVALID";BLOCK_SCOPE_NOT_EMPTY:"BLOCK_SCOPE_NOT_EMPTY";BLOCK_SCOPE_NULL:"BLOCK_SCOPE_NULL";BLOCK_WRITES_INVALID:"BLOCK_WRITES_INVALID";RUN_READONLY_WROTE:"RUN_READONLY_WROTE";RUN_RESULT_INVALID:"RUN_RESULT_INVALID"; }>
Defined in: packages/core/block-contract.mjs:41
Every rejection the contract validator can produce, by name, so callers and tests match on a code, not on text.
BLOCK_ID_RE#
constBLOCK_ID_RE:RegExp
Defined in: packages/core/block-contract.mjs:81
The shape of a dotted block id (create.unit, process.lifecycle); choosers reuse it.
GUARDRAILS#
constGUARDRAILS: readonlystring[]
Defined in: packages/core/block-contract.mjs:38
The guardrails that never switch off, by the name each has in the code:
containment (paths stay inside the project root), approval (per-diff approval, approvalGate.mjs), sessionGate
(the Cockpit server's session check in front of every route) and checks (deterministic validation of the staged
tree before AI or free output lands).
Functions#
defineBlock()#
defineBlock(
spec):Block
Defined in: packages/core/block-contract.mjs:281
Build a block: validate the spec, freeze it and return it. The only constructor, so a malformed block fails where it is defined rather than where a screen first tries to read its menu.
Parameters#
spec
{ id, writes, declaredScope, actions, run } plus optional label, summary, meta.
Returns#
The frozen block.
Throws#
Listing every problem, when the spec does not satisfy the contract.
Example#
const block = defineBlock({ id: 'validate', writes: false, declaredScope: () => emptyScope(), actions: () => [], run: () => ({ changedFiles: [] }) });
deriveActions()#
deriveActions(
rules,state?):BlockAction[]
Defined in: packages/core/block-contract.mjs:195
Turn a rule table and a state into the legal next actions -- the only way a block's menu is produced. A rule whose
applies(state) is false is not offered; one whose blockedBy(state) returns a reason is offered disabled with that
reason as why; ai and free actions are stamped with every guardrail in gates. Pure and order-preserving.
Parameters#
rules
The block's rule table.
state?
any = {}
Whatever state the rules read (a process state, a step, a plan, ...).
Returns#
The actions, in rule order.
Example#
deriveActions([{ id: 'run', kind: 'mechanical', label: 'Run', blockedBy: (s) => (s.ok ? null : 'Fix the arguments first.') }], { ok: false });
// => [{ id: 'run', kind: 'mechanical', label: 'Run', enabled: false, why: 'Fix the arguments first.' }]
emptyScope()#
emptyScope():
DeclaredScope
Defined in: packages/core/block-contract.mjs:92
The scope of a read-only block: no features, no files.
Returns#
A fresh empty scope, { features: [], files: [] }.
Example#
emptyScope(); // => { features: [], files: [] }
isEmptyScope()#
isEmptyScope(
scope):boolean
Defined in: packages/core/block-contract.mjs:105
True when a scope names nothing at all (what a read-only block declares).
Parameters#
scope
A declared scope.
Returns#
boolean
true for an object with no features and no files; false for null (an unknown scope is not an empty one).
Example#
isEmptyScope({ features: [], files: [] }); // => true
runBlock()#
runBlock(
block,args?,ctx?):Promise<{changedFiles:string[];scope:DeclaredScope; }>
Defined in: packages/core/block-contract.mjs:301
Run a block through the contract: derive its scope from args, call run(scope, args, ctx), and check the result is
{ changedFiles: string[] } of project-relative paths (a read-only block that reports a changed file is refused).
The changed files come back sorted and de-duplicated, so the same run yields the same list.
Parameters#
block
A block from defineBlock.
args?
any = {}
The arguments (a plan step's args).
ctx?
any = {}
Caller context passed to declaredScope and run (e.g. { root, exec }).
Returns#
Promise<{ changedFiles: string[]; scope: DeclaredScope; }>
The scope the block declared and the files it reports changed.
Throws#
With a code from BLOCK_ERROR_CODES when the result breaks the contract.
Example#
const { scope, changedFiles } = await runBlock(block, { name: 'cart' }, { root });
validateAction()#
validateAction(
action,at?):object
Defined in: packages/core/block-contract.mjs:136
Validate one action. An ai or free action must list every guardrail in gates, and a disabled action must say why.
Parameters#
action
any
The action to check.
at?
string = 'action'
Path prefix for error paths.
Returns#
object
Every problem found; never throws.
errors
errors:
object[]
valid
valid:
boolean
Example#
validateAction({ id: 'run', kind: 'mechanical', label: 'Run', enabled: true }).valid; // => true
validateActions()#
validateActions(
actions,at?):object
Defined in: packages/core/block-contract.mjs:168
Validate a list of actions: each one, plus unique ids.
Parameters#
actions
any
The value block.actions(state) returned.
at?
string = 'actions'
Path prefix for error paths.
Returns#
object
Every problem found; never throws.
errors
errors:
object[]
valid
valid:
boolean
Example#
validateActions([{ id: 'run', kind: 'mechanical', label: 'Run', enabled: true }]).valid; // => true
validateBlock()#
validateBlock(
block,options?):object
Defined in: packages/core/block-contract.mjs:223
Validate a block's static shape: id, writes, the three functions. With options.state, also calls
block.actions(state) and validates what comes back (unique ids, kinds, disabled-with-why, guardrails on ai/free).
With options.args, also calls declaredScope(args) and checks it: valid touches shape, empty for a read-only
block, never null for one.
Parameters#
block
any
The candidate block.
options?
Optional state/args to exercise actions and declaredScope with.
args?
any
ctx?
any
state?
any
Returns#
object
Every problem found; never throws (a throwing function is reported).
errors
errors:
object[]
valid
valid:
boolean
Example#
validateBlock(block, { state: { processState: 'queued' } }).errors;
validateScope()#
validateScope(
scope,at?):object
Defined in: packages/core/block-contract.mjs:120
Validate a declared scope with the plan validator's own touches rules (unknown keys, relative paths, known change
kinds), so a scope that passes here is accepted as a step's touches by validatePlan.
Parameters#
scope
any
The value to check.
at?
string = 'scope'
Path prefix for error paths.
Returns#
object
Every problem found; never throws.
errors
errors:
object[]
valid
valid:
boolean
Example#
validateScope({ features: ['cart'], files: [{ path: 'features/cart/types.ts', change: 'create' }] }).valid; // => true