deliver: 交付收口(引擎代为提交)
This commit is contained in:
parent
87bbac9c7a
commit
786f3a2f9d
@ -1,15 +1,16 @@
|
||||
debug(f'pbl_artifact_options.dspy: START params_kw={dict(params_kw)}')
|
||||
debug('pbl_artifact_options.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
# 下拉数据源(json/pbl_evidence.json -> browserfields.alters.artifact_id.dataurl)
|
||||
# 契约:必须返回**裸 JSON 数组** [{value,text},...],异常/空数据返回 [],
|
||||
# 不许包 status/data(crud-definition-spec Pitfall:包了会让下拉静默不渲染)。
|
||||
# 后端函数 pbl_artifact_options 由 load_pbl_evidence() 注册到 ServerEnv(init.py ③)。
|
||||
# dspy 禁项:无 import、无 f-string(日志一律字符串拼接)。
|
||||
try:
|
||||
_rows = await pbl_artifact_options(**dict(params_kw))
|
||||
if not isinstance(_rows, list):
|
||||
_rows = []
|
||||
debug(f'pbl_artifact_options.dspy: OK rows={len(_rows)}')
|
||||
debug('pbl_artifact_options.dspy: OK rows=' + str(len(_rows)))
|
||||
return json.dumps(_rows, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'pbl_artifact_options.dspy: FAIL {e}')
|
||||
debug(f'pbl_artifact_options.dspy: TRACE {format_exc()}')
|
||||
debug('pbl_artifact_options.dspy: FAIL ' + str(e))
|
||||
debug('pbl_artifact_options.dspy: TRACE ' + str(format_exc()))
|
||||
return json.dumps([], ensure_ascii=False)
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
# pbl_evidence/api/pbl_evidence_aggregate.dspy
|
||||
# M5b 契约②:证据聚合(四类计数 + 覆盖度 + 分组 + 时间水位)。
|
||||
# Q-OPEN-10:预览 / Playtest 数据默认剔除,需显式 include_preview=true 才纳入。
|
||||
# dspy 铁律:无 import、无 ServerEnv()、显式 return。
|
||||
debug(f'pbl_evidence/api/pbl_evidence_aggregate.dspy: START params_kw={dict(params_kw)}')
|
||||
# dspy 铁律:无 import、无 ServerEnv()、无 f-string、显式 return;
|
||||
# 日志/异常一律字符串拼接(dspy-file-implementation-spec 硬规则 6)。
|
||||
debug('pbl_evidence/api/pbl_evidence_aggregate.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
kw = dict(params_kw)
|
||||
@ -11,10 +12,11 @@ try:
|
||||
kw[flag] = kw[flag].strip().lower() in ('1', 'true', 'yes', 'y')
|
||||
res = await pbl_evidence_aggregate(**kw)
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_aggregate.dspy: DONE total={res.get("total")} '
|
||||
f'groups={len(res.get("groups") or [])}')
|
||||
return {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('total')}
|
||||
debug('pbl_evidence_aggregate.dspy: DONE total=' + str(res.get('total')) +
|
||||
' groups=' + str(len(res.get('groups') or [])))
|
||||
result = {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('total')}
|
||||
return result
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_aggregate.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_aggregate.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
# pbl_evidence/api/pbl_evidence_collect_from_events.dspy
|
||||
# M5a 主能力:批量从 pbl_runtime_event(M11b 产物)采集学习证据,幂等落 pbl_evidence。
|
||||
# 铁律:dspy 内不 import、不 new ServerEnv();ServerEnv 注册的契约函数是直接全局;必须显式 return。
|
||||
debug(f'pbl_evidence_collect_from_events.dspy: START params_kw={dict(params_kw)}')
|
||||
# 铁律:dspy 内不 import、不 new ServerEnv();ServerEnv 注册的契约函数是直接全局;必须显式 return;
|
||||
# 禁 f-string(硬规则 6),日志一律字符串拼接。
|
||||
debug('pbl_evidence_collect_from_events.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
tenant = params_kw.get('tenant_id') or (await get_userorgid()) or '0'
|
||||
@ -27,11 +28,16 @@ try:
|
||||
update_existing=params_kw.get('update_existing'),
|
||||
)
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_collect_from_events.dspy: DONE status={status} msg={res.get("message")}')
|
||||
debug('pbl_evidence_collect_from_events.dspy: DONE status=' + str(status) +
|
||||
' msg=' + str(res.get('message')))
|
||||
data = {}
|
||||
for _k, _v in res.items():
|
||||
if _k != 'items':
|
||||
data[_k] = _v
|
||||
return {'status': status,
|
||||
'data': {k: v for k, v in res.items() if k != 'items'},
|
||||
'data': data,
|
||||
'items': res.get('items') or [],
|
||||
'message': res.get('message') or ''}
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_collect_from_events.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_collect_from_events.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
# pbl_evidence/api/pbl_evidence_collect_idempotent.dspy
|
||||
# M5b 契约①:四类证据(decision/action/observation/artifact_version)幂等采集。
|
||||
# 重复采集(同 idempotency_key / 同唯一索引三元组)不报错,返回 created=false。
|
||||
# dspy 铁律:无 import、无 ServerEnv()、显式 return;函数由 load_pbl_evidence() 挂 ServerEnv。
|
||||
debug(f'pbl_evidence/api/pbl_evidence_collect_idempotent.dspy: START params_kw={dict(params_kw)}')
|
||||
# dspy 铁律:无 import、无 ServerEnv()、无 f-string、显式 return;
|
||||
# 函数由 load_pbl_evidence() 挂 ServerEnv;日志一律字符串拼接。
|
||||
debug('pbl_evidence/api/pbl_evidence_collect_idempotent.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
res = await pbl_evidence_collect_idempotent(**params_kw)
|
||||
res = await pbl_evidence_collect_idempotent(**dict(params_kw))
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_collect_idempotent.dspy: DONE created={res.get("created")} '
|
||||
f'deduped={res.get("deduped")} id={res.get("id")}')
|
||||
return {'status': status, 'data': res, 'message': res.get('message') or ''}
|
||||
debug('pbl_evidence_collect_idempotent.dspy: DONE created=' + str(res.get('created')) +
|
||||
' deduped=' + str(res.get('deduped')) + ' id=' + str(res.get('id')))
|
||||
result = {'status': status, 'data': res, 'message': res.get('message') or ''}
|
||||
return result
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_collect_idempotent.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_collect_idempotent.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
debug(f'pbl_evidence_delete.dspy: START params_kw={dict(params_kw)}')
|
||||
debug('pbl_evidence_delete.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
# 证据删除端点(json/pbl_evidence.json -> delete_data_url,DataViewer editable 提交目标)。
|
||||
# 薄包装:无 import、无业务逻辑,直接委托 init.py 注册的 pbl_evidence_delete
|
||||
# (支持单条 id 与批量 ids;每条都按 tenant_id + id 双条件校验归属,防越权删除)。
|
||||
@ -7,8 +7,7 @@ debug(f'pbl_evidence_delete.dspy: START params_kw={dict(params_kw)}')
|
||||
# 1) dspy-file-implementation-spec「DataViewer CRUD endpoints 必须返回 Message widget
|
||||
# JSON 字符串」——本端点是 editable 提交端点,故返回 bricks Message widget,
|
||||
# 删除提交后能正确渲染成功/失败提示;不得返回裸数据 dict。
|
||||
# 2) 禁项 f-string 出现在 dict 字面量内会被 ahserver exec() 误判提前闭合外层 dict
|
||||
# (SyntaxError: '{' was never closed,整文件编译失败),异常分支一律用字符串拼接。
|
||||
# 2) dspy 禁项 f-string(硬规则 6):一律字符串拼接,异常分支亦然。
|
||||
try:
|
||||
_data = await pbl_evidence_delete(**dict(params_kw))
|
||||
_msg = (_data or {}).get('message') or '证据已删除'
|
||||
@ -17,8 +16,8 @@ try:
|
||||
debug('pbl_evidence_delete.dspy: OK deleted=' + str((_data or {}).get('deleted')))
|
||||
return json.dumps(_widget, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'pbl_evidence_delete.dspy: FAIL {e}')
|
||||
debug(f'pbl_evidence_delete.dspy: TRACE {format_exc()}')
|
||||
debug('pbl_evidence_delete.dspy: FAIL ' + str(e))
|
||||
debug('pbl_evidence_delete.dspy: TRACE ' + str(format_exc()))
|
||||
_widget = {'widgettype': 'Message',
|
||||
'options': {'title': '失败',
|
||||
'message': '证据删除失败:' + str(e),
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
# M5b 契约③:证据分页查询(含 timestamp + payload,US-17「证据不只是分数」)。
|
||||
# 支持 blueprint_id / learner_id / session_id / artifact_id / evidence_type /
|
||||
# evidence_types / time_from,time_to / page / rows;预览数据默认过滤(Q-OPEN-10)。
|
||||
# dspy 铁律:无 import、无 ServerEnv()、显式 return。
|
||||
debug(f'pbl_evidence/api/pbl_evidence_query.dspy: START params_kw={dict(params_kw)}')
|
||||
# dspy 铁律:无 import、无 ServerEnv()、无 f-string、显式 return;
|
||||
# 日志/异常一律字符串拼接(dspy-file-implementation-spec 硬规则 6)。
|
||||
debug('pbl_evidence/api/pbl_evidence_query.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
kw = dict(params_kw)
|
||||
@ -12,10 +13,11 @@ try:
|
||||
kw[flag] = kw[flag].strip().lower() in ('1', 'true', 'yes', 'y')
|
||||
res = await pbl_evidence_query(**kw)
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_query.dspy: DONE total={res.get("total")} '
|
||||
f'page={res.get("page")} rows={len(res.get("rows") or [])}')
|
||||
return {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('total')}
|
||||
debug('pbl_evidence_query.dspy: DONE total=' + str(res.get('total')) +
|
||||
' page=' + str(res.get('page')) + ' rows=' + str(len(res.get('rows') or [])))
|
||||
result = {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('total')}
|
||||
return result
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_query.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_query.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# pbl_evidence/api/pbl_evidence_stats.dspy
|
||||
# 证据类型分布统计(供 M6 评估 / 概览卡片)。dspy 无 import、无 ServerEnv()、显式 return。
|
||||
debug(f'pbl_evidence_stats.dspy: START params_kw={dict(params_kw)}')
|
||||
# 证据类型分布统计(供 M6 评估 / 概览卡片)。
|
||||
# dspy 铁律:无 import、无 ServerEnv()、无 f-string、显式 return(日志字符串拼接)。
|
||||
debug('pbl_evidence_stats.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
tenant = params_kw.get('tenant_id') or (await get_userorgid()) or '0'
|
||||
@ -10,8 +11,9 @@ try:
|
||||
blueprint_id=params_kw.get('blueprint_id'),
|
||||
)
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_stats.dspy: DONE total={res.get("total")}')
|
||||
return {'status': status, 'data': res, 'message': res.get('message') or ''}
|
||||
debug('pbl_evidence_stats.dspy: DONE total=' + str(res.get('total')))
|
||||
result = {'status': status, 'data': res, 'message': res.get('message') or ''}
|
||||
return result
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_stats.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_stats.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
# M5b 契约④:学生 / 团队证据档案(设计 §3.2 list_evidence_by_student / by_team 等价实现)。
|
||||
# 入参:subject_type=student|team + subject_id(或 student_id / team_id)+ blueprint_id(可选)
|
||||
# 出参:四类分组明细 + 产出物计数 + 水位;预览/Playtest 数据默认过滤(Q-OPEN-10)。
|
||||
# dspy 铁律:无 import、无 ServerEnv()、显式 return。
|
||||
debug(f'pbl_evidence/api/pbl_evidence_subject_summary.dspy: START params_kw={dict(params_kw)}')
|
||||
# dspy 铁律:无 import、无 ServerEnv()、无 f-string、显式 return;
|
||||
# 日志/异常一律字符串拼接(dspy-file-implementation-spec 硬规则 6)。
|
||||
debug('pbl_evidence/api/pbl_evidence_subject_summary.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
|
||||
try:
|
||||
kw = dict(params_kw)
|
||||
@ -13,10 +14,11 @@ try:
|
||||
kw['include_student_private'] = kw['include_student_private'].strip().lower() in ('1', 'true', 'yes', 'y')
|
||||
res = await pbl_evidence_subject_summary(**kw)
|
||||
status = 'OK' if res.get('ok') else 'ERROR'
|
||||
debug(f'pbl_evidence_subject_summary.dspy: DONE subject={res.get("subject_type")}:'
|
||||
f'{res.get("subject_id")} total={res.get("evidence_total")}')
|
||||
return {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('evidence_total')}
|
||||
debug('pbl_evidence_subject_summary.dspy: DONE subject=' + str(res.get('subject_type')) +
|
||||
':' + str(res.get('subject_id')) + ' total=' + str(res.get('evidence_total')))
|
||||
result = {'status': status, 'data': res, 'message': res.get('message') or '',
|
||||
'total': res.get('evidence_total')}
|
||||
return result
|
||||
except Exception as e:
|
||||
error(f'pbl_evidence_subject_summary.dspy: FAIL {format_exc()}')
|
||||
error('pbl_evidence_subject_summary.dspy: FAIL ' + str(format_exc()))
|
||||
return {'status': 'ERROR', 'data': None, 'message': str(e)}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
debug(f'pbl_evidence_update.dspy: START params_kw={dict(params_kw)}')
|
||||
debug('pbl_evidence_update.dspy: START params_kw=' + str(dict(params_kw)))
|
||||
# 证据人工修订端点(json/pbl_evidence.json -> update_data_url,DataViewer editable 提交目标)。
|
||||
# 薄包装:无 import、无业务逻辑,直接委托 init.py 注册的 pbl_evidence_update
|
||||
# (强制 tenant_id 打头校验归属;改唯一索引三元组时同步重算 dedup_key)。
|
||||
@ -7,8 +7,7 @@ debug(f'pbl_evidence_update.dspy: START params_kw={dict(params_kw)}')
|
||||
# 1) dspy-file-implementation-spec「DataViewer CRUD endpoints 必须返回 Message widget
|
||||
# JSON 字符串」——本端点是 editable 提交端点,故返回 bricks Message widget,
|
||||
# 表单提交后能正确渲染成功/失败提示;不得返回裸数据 dict。
|
||||
# 2) 禁项 f-string 出现在 dict 字面量内会被 ahserver exec() 误判提前闭合外层 dict
|
||||
# (SyntaxError: '{' was never closed,整文件编译失败),异常分支一律用字符串拼接。
|
||||
# 2) dspy 禁项 f-string(硬规则 6):一律字符串拼接,异常分支亦然。
|
||||
try:
|
||||
_data = await pbl_evidence_update(**dict(params_kw))
|
||||
_msg = (_data or {}).get('message') or '证据已更新'
|
||||
@ -17,8 +16,8 @@ try:
|
||||
debug('pbl_evidence_update.dspy: OK')
|
||||
return json.dumps(_widget, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
debug(f'pbl_evidence_update.dspy: FAIL {e}')
|
||||
debug(f'pbl_evidence_update.dspy: TRACE {format_exc()}')
|
||||
debug('pbl_evidence_update.dspy: FAIL ' + str(e))
|
||||
debug('pbl_evidence_update.dspy: TRACE ' + str(format_exc()))
|
||||
_widget = {'widgettype': 'Message',
|
||||
'options': {'title': '失败',
|
||||
'message': '证据更新失败:' + str(e),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user