Updating mechanics for OS protocols
Validate and deploy production / validate (push) Canceled after 0s
Validate and deploy production / deploy (push) Canceled after 0s
Validate and deploy staging / validate (push) Successful in 33s
Validate and deploy staging / deploy (push) Successful in 1m9s

This commit is contained in:
jb
2026-08-03 16:12:20 -04:00
parent 57068b61cd
commit 7ca6cb8458
27 changed files with 1272 additions and 280 deletions
+13 -14
View File
@@ -97,6 +97,11 @@ export const MECHANIC_EVENT_REGISTRY: Readonly<
description:
'The Agent deploys or activates a specialization ability. An assigned-ability deployment may supply its active duration.',
fields: [
{
path: 'values.abilityId',
label: 'Deployed ability ID',
type: 'string',
},
{
path: 'values.assignedAbilityDurationSeconds',
label: 'Assigned ability duration',
@@ -123,8 +128,9 @@ export const MECHANIC_EVENT_REGISTRY: Readonly<
key: 'skill_hit',
label: 'Skill hit',
description:
'A deployed skill connects with a target. Critical and distance details belong in event values.',
'A deployed skill connects with a target. Critical and distance details belong in event values. An optional area-target sample lists valid entities by distance from the hit target.',
fields: [
{ path: 'values.abilityId', label: 'Source ability ID', type: 'string' },
{ path: 'values.critical', label: 'Critical hit', type: 'boolean' },
{
path: 'values.assignedAbilityActive',
@@ -1892,15 +1898,8 @@ function validateReference(
}
if (reference.source === 'event' && !reference.path.trim())
errors.push(`${path} requires an event path.`);
if (reference.source === 'combat') {
if (!reference.path.trim()) errors.push(`${path} requires a combat path.`);
if (
reference.path === 'currentHealthPercent' &&
reference.timing === 'pre_event'
) {
errors.push(`${path} current Health percentage must use current timing.`);
}
}
if (reference.source === 'combat' && !reference.path.trim())
errors.push(`${path} requires a combat path.`);
if (reference.source === 'attribute' && !reference.attributeId.trim())
errors.push(`${path} requires an Attribute ID.`);
if (reference.source === 'equipment' && !reference.path.trim())
@@ -2067,7 +2066,7 @@ function validateMechanicEvents(events: MechanicEvent[]) {
if (sample === undefined) continue;
const samplePath = `Event ${index + 1} (${definition.label}) area-target sample`;
if (
event.kind !== 'weapon_hit' ||
!['weapon_hit', 'skill_hit'].includes(event.kind) ||
!objectValue(sample) ||
sample.center !== 'event_target' ||
!Array.isArray(sample.validTargets) ||
@@ -2075,7 +2074,7 @@ function validateMechanicEvents(events: MechanicEvent[]) {
!event.targetId.trim()
) {
errors.push(
`${samplePath} requires a weapon-hit event target and event-target-centered valid targets.`,
`${samplePath} requires a weapon-hit or skill-hit event target and event-target-centered valid targets.`,
);
continue;
}
@@ -2769,10 +2768,10 @@ export function validateMechanicProgram(
if (targetingError) errors.push(`${outcomePath} ${targetingError}`);
if (
outcome.targeting?.kind === 'event_target_area' &&
clause.when !== 'weapon_hit'
!['weapon_hit', 'skill_hit'].includes(clause.when)
) {
errors.push(
`${outcomePath} event-target area damage requires a weapon-hit clause.`,
`${outcomePath} event-target area damage requires a weapon-hit or skill-hit clause.`,
);
}
if (