feat(events): a dry run carries a module's advice (MODULE_API 1.16.0)
An action answering verify: true with { ok: true, detail: { warnings } } has
each line shown as a warning finding (code `advice`) that never fails the
dry run. Strings only, at most ten per step, each cut at 500 characters;
anything else under warnings is ignored, and a refused step carries none.
Rust PLAN_REDESIGNS §11.4, D391: a raid base's spot is checked against the
world as it stands now (a player on it, a rock beside it), which may change
before the run, so the editor shows it as advice. One optional reading of an
existing member, so minor; Module-uo's ^1.10.0 still resolves and says no
warnings. STEAM_SIGNIN.md's claim moves to 1.17.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -36,6 +36,26 @@ const authorize = require('./authorize')
|
||||
const settingsDb = require('../model/events/eventActionSettings.db')
|
||||
const registries = require('../modules/registries')
|
||||
|
||||
/** The most advice lines one step's dry run carries, and the longest one. */
|
||||
const ADVICE_MAX = 10
|
||||
const ADVICE_CHARS = 500
|
||||
|
||||
/**
|
||||
* A dry run's `detail.warnings`, as the lines a dry run shows: strings only,
|
||||
* trimmed, the empty dropped, at most ten, each cut at 500 characters. Anything
|
||||
* else a module put there is ignored rather than refused — advice that cannot be
|
||||
* read is not a reason to fail a plan that would run.
|
||||
*/
|
||||
function adviceOf(detail) {
|
||||
if (!detail || typeof detail !== 'object' || !Array.isArray(detail.warnings)) return []
|
||||
return detail.warnings
|
||||
.filter((w) => typeof w === 'string')
|
||||
.map((w) => w.trim())
|
||||
.filter(Boolean)
|
||||
.slice(0, ADVICE_MAX)
|
||||
.map((w) => (w.length > ADVICE_CHARS ? `${w.slice(0, ADVICE_CHARS - 1)}…` : w))
|
||||
}
|
||||
|
||||
/**
|
||||
* Dry-run a spec.
|
||||
*
|
||||
@@ -108,13 +128,21 @@ async function verifySpec(spec, { user = null, scope = '' } = {}) {
|
||||
)
|
||||
if (result.outcome === 'retry' || result.outcome === 'terminal') {
|
||||
findings.push({ ...where, level: 'error', code: 'refused', message: result.error })
|
||||
} else if (result.actionVersionDrift) {
|
||||
findings.push({
|
||||
...where,
|
||||
level: 'warning',
|
||||
code: 'version-drift',
|
||||
message: `authored against version ${result.actionVersionDrift.authored}; ${step.actionId} is now version ${result.actionVersionDrift.registered}`,
|
||||
})
|
||||
} else {
|
||||
if (result.actionVersionDrift) {
|
||||
findings.push({
|
||||
...where,
|
||||
level: 'warning',
|
||||
code: 'version-drift',
|
||||
message: `authored against version ${result.actionVersionDrift.authored}; ${step.actionId} is now version ${result.actionVersionDrift.registered}`,
|
||||
})
|
||||
}
|
||||
// MODULE_API 1.16.0: a module's ADVICE on a step that would run — the
|
||||
// world as it stands now, which may change before the run does (Rust
|
||||
// PLAN_REDESIGNS §11.4, D391). A warning, so it never fails the dry run.
|
||||
for (const message of adviceOf(result.detail)) {
|
||||
findings.push({ ...where, level: 'warning', code: 'advice', message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,4 +178,4 @@ async function verifySpec(spec, { user = null, scope = '' } = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { verifySpec }
|
||||
module.exports = { verifySpec, adviceOf }
|
||||
|
||||
Reference in New Issue
Block a user