v0.11.2
This commit is contained in:
@@ -10,4 +10,4 @@ e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./network-debu
|
||||
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./service.sh
|
||||
fec8b0362e763bbc115b5cc5c56f9ebe815730cee161632d81c5dc0ee1475f80 ./smoke.sh
|
||||
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./update.sh
|
||||
b70f2a66f39ed050f9030ed499f74e8e899e224d6d7c47ed2a1389ce1be11421 ./verify_flow_logic.py
|
||||
4877f9e8217b6a77fb416722c3778373edac874ed3a583bb016ea76d4ffee7d4 ./verify_flow_logic.py
|
||||
|
||||
@@ -421,6 +421,21 @@ def main():
|
||||
check('if !item.enabled { continue; }' in engine and 'if !ready || !should_fire { continue; }' in engine, 'Flow runtime may be skipped during action cooldown')
|
||||
check('rate-limit block must be placed directly before an action' in api, 'rate-limit placement guard missing')
|
||||
check('on-change value mode needs one direct source/condition input' in api, 'on-change value-source guard missing')
|
||||
models=(ROOT/'src/models/flow.rs').read_text()
|
||||
core=(ROOT/'web/js/core.js').read_text()
|
||||
settings_api=(ROOT/'src/api/settings.rs').read_text()
|
||||
check('pub draft: bool' in models and '#[serde(default)]' in models, 'Flow draft persistence field missing')
|
||||
check('fn validate_flow_draft_graph' in api, 'draft structural validator missing')
|
||||
check(api.count('if input.draft { validate_flow_draft_graph(&input)?; } else { validate_flow_graph(&input)?; }') >= 3, 'draft create/update/import validation split missing')
|
||||
check('enabled: if draft { false } else { input.enabled }' in api, 'draft does not force Flow disabled')
|
||||
check(api.count('(prepare_draft_flow(flow), vec![], vec![])') >= 3, 'draft save/import may compile executable outputs')
|
||||
check('flow.compiled_schedule_ids.clear()' in api and 'flow.compiled_automation_ids.clear()' in api, 'draft output clearing missing')
|
||||
check('"draft": flow.draft' in api, 'draft state missing from Flow export')
|
||||
check('import contains an executable Flow draft' in settings_api, 'configuration import does not enforce draft safety invariant')
|
||||
check('error.status = response.status' in core, 'frontend API errors do not expose HTTP validation status')
|
||||
check("error.status !== 400" in js and "draft:true" in js and "enabled:false" in js, 'save-as-draft retry flow missing')
|
||||
check("if (flow.draft) return toast(tr('flow.draftCannotEnable')" in js, 'draft quick-enable guard missing')
|
||||
check("draft: app.flowDraft.draft === true" in js, 'draft portability state missing from source payload')
|
||||
runtime_leaf=engine.split('async fn flow_leaf_observation',1)[1].split('pub async fn evaluate_flow_conditions_trace',1)[0]
|
||||
for kind in CONDITIONS - {'stable_for','delay','state_duration','on_change','rate_limit','rolling_stat','oscillates'}:
|
||||
check(f'\"{kind}\" =>' in runtime_leaf or (kind == 'shared_input' and 'condition.kind == \"shared_input\"' in runtime_leaf), f'{kind}: runtime leaf implementation missing')
|
||||
@@ -430,14 +445,14 @@ def main():
|
||||
for category in ('trigger','time','timeop','sensor','logic','action','haaction'):
|
||||
check(f'flow-palette-{category}' in html, f'palette category {category} missing')
|
||||
css=(ROOT/'web/styles.css').read_text()
|
||||
for marker in ('.flow-palette-group button', 'min-height:30px', 'padding:6px 8px', '.flow-palette-timeop', '.flow-palette-haaction'):
|
||||
for marker in ('.flow-palette-group button', 'min-height:30px', 'padding:6px 8px', '.flow-palette-timeop', '.flow-palette-haaction', '.flow-editor-title input:hover', '.flow-editor-title input:focus', '.flow-draft-badge'):
|
||||
check(marker in css, f'compact/color Flow CSS missing: {marker}')
|
||||
|
||||
# Translation pack correctness: all new keys must be inside translations, not root.
|
||||
for lang in ('pl','en'):
|
||||
pack=json.loads((ROOT/f'lang/{lang}.json').read_text())
|
||||
check(not any(k.startswith('flow.') for k in pack), f'{lang}: flow translations leaked to root')
|
||||
for key in ('flow.triggers','flow.timeOps','flow.haActions','flow.node.cronTrigger','flow.node.stableFor','flow.node.stateDuration','flow.node.onChange','flow.node.rateLimit','flow.node.delay','flow.node.rollingStat','flow.node.oscillates','flow.node.haServiceAction'):
|
||||
for key in ('flow.triggers','flow.timeOps','flow.haActions','flow.node.cronTrigger','flow.node.stableFor','flow.node.stateDuration','flow.node.onChange','flow.node.rateLimit','flow.node.delay','flow.node.rollingStat','flow.node.oscillates','flow.node.haServiceAction','flow.draft','flow.draftStatus','flow.draftNoExecution','flow.draftDisabledHint','flow.draftCannotEnable','flow.saveAsDraftConfirm','flow.savedAsDraft'):
|
||||
check(bool(pack.get('translations',{}).get(key)), f'{lang}: missing {key}')
|
||||
title_keys=set(re.findall(r"titleKey: '([^']+)'", meta_block))
|
||||
missing_titles=sorted(key for key in title_keys if not pack.get('translations',{}).get(key))
|
||||
|
||||
Reference in New Issue
Block a user