@ai-content-space/loopx 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/README.zh-CN.md +5 -1
- package/package.json +1 -1
- package/plugins/loopx/.codex-plugin/plugin.json +1 -1
- package/plugins/loopx/skills/archive/SKILL.md +1 -1
- package/plugins/loopx/skills/autopilot/SKILL.md +1 -1
- package/plugins/loopx/skills/build/SKILL.md +1 -1
- package/plugins/loopx/skills/clarify/SKILL.md +1 -1
- package/plugins/loopx/skills/debug/SKILL.md +1 -1
- package/plugins/loopx/skills/go-style/SKILL.md +1 -1
- package/plugins/loopx/skills/kratos/SKILL.md +1 -1
- package/plugins/loopx/skills/plan/SKILL.md +12 -1
- package/plugins/loopx/skills/review/SKILL.md +8 -5
- package/plugins/loopx/skills/tdd/SKILL.md +1 -1
- package/plugins/loopx/skills/verify/SKILL.md +1 -1
- package/scripts/codex-workflow-hook.mjs +7 -3
- package/skills/archive/SKILL.md +1 -1
- package/skills/autopilot/SKILL.md +1 -1
- package/skills/build/SKILL.md +1 -1
- package/skills/clarify/SKILL.md +1 -1
- package/skills/debug/SKILL.md +1 -1
- package/skills/go-style/SKILL.md +1 -1
- package/skills/kratos/SKILL.md +1 -1
- package/skills/plan/SKILL.md +12 -1
- package/skills/review/SKILL.md +8 -5
- package/skills/tdd/SKILL.md +1 -1
- package/skills/verify/SKILL.md +1 -1
- package/src/cli.mjs +2 -0
- package/src/html-views.mjs +463 -35
- package/src/next-skill.mjs +7 -0
- package/src/plan-runtime.mjs +2 -1
- package/src/runtime-maintenance.mjs +55 -14
- package/src/workflow.mjs +148 -19
|
@@ -39,6 +39,8 @@ const CHANGE_ARTIFACT_FILE_MAP = {
|
|
|
39
39
|
graph: 'artifact-graph.json',
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
const PLAN_ARTIFACTS = ['plan.md', 'architecture.md', 'development-plan.md', 'test-plan.md'];
|
|
43
|
+
|
|
42
44
|
function normalizeSlug(raw) {
|
|
43
45
|
return String(raw || '')
|
|
44
46
|
.trim()
|
|
@@ -47,6 +49,44 @@ function normalizeSlug(raw) {
|
|
|
47
49
|
.replace(/^-+|-+$/g, '');
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
function containsChineseText(text) {
|
|
53
|
+
const chineseChars = text.match(/[\u3400-\u9fff]/g) || [];
|
|
54
|
+
const latinChars = text.match(/[A-Za-z]/g) || [];
|
|
55
|
+
const signalChars = chineseChars.length + latinChars.length;
|
|
56
|
+
if (signalChars === 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return chineseChars.length >= 40 || (chineseChars.length >= 8 && chineseChars.length / signalChars >= 0.2);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function legacyPlanArtifactBlockers(workflowRoot) {
|
|
63
|
+
const blockers = [];
|
|
64
|
+
for (const name of PLAN_ARTIFACTS) {
|
|
65
|
+
const path = join(workflowRoot, name);
|
|
66
|
+
const key = name
|
|
67
|
+
.replace(/\.md$/, '')
|
|
68
|
+
.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
69
|
+
if (!existsSync(path)) {
|
|
70
|
+
blockers.push(`missing_plan_artifact_${key}`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const text = await readFile(path, 'utf8');
|
|
74
|
+
if (!containsChineseText(text)) {
|
|
75
|
+
blockers.push(`plan_artifact_not_chinese_${key}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!existsSync(join(workflowRoot, 'requirement-traceability.md'))) {
|
|
79
|
+
blockers.push('missing_requirement_traceability');
|
|
80
|
+
}
|
|
81
|
+
if (!existsSync(join(workflowRoot, 'plan-delegation-decision.md'))) {
|
|
82
|
+
blockers.push('missing_plan_delegation_decision');
|
|
83
|
+
}
|
|
84
|
+
if (!existsSync(join(workflowRoot, 'plan-reviews'))) {
|
|
85
|
+
blockers.push('missing_plan_review_artifacts');
|
|
86
|
+
}
|
|
87
|
+
return blockers;
|
|
88
|
+
}
|
|
89
|
+
|
|
50
90
|
export function resolveLoopxRoot(cwd) {
|
|
51
91
|
return join(resolve(cwd), '.loopx');
|
|
52
92
|
}
|
|
@@ -332,24 +372,25 @@ async function migrateLegacyWorkflowState(cwd, slug, workflowRoot, legacyState)
|
|
|
332
372
|
const canonicalPlanPath = join(resolveLoopxRoot(cwd), 'plans', `prd-${slug}.md`);
|
|
333
373
|
const canonicalTestSpecPath = join(resolveLoopxRoot(cwd), 'plans', `test-spec-${slug}.md`);
|
|
334
374
|
const baseState = createMigratedWorkflowBaseState(slug, legacyState, change);
|
|
335
|
-
const
|
|
336
|
-
|
|
375
|
+
const planBlockers = await legacyPlanArtifactBlockers(workflowRoot);
|
|
376
|
+
const planDocsComplete = planBlockers.length === 0;
|
|
337
377
|
const executionRecordStatus = await inferExecutionStatus(workflowRoot);
|
|
338
|
-
const planState =
|
|
378
|
+
const planState = PLAN_ARTIFACTS.some((name) => existsSync(join(workflowRoot, name))) ? {
|
|
339
379
|
current_stage: STAGES.PLAN,
|
|
340
|
-
stage_status: 'awaiting-approval',
|
|
341
|
-
plan_package_status: 'complete',
|
|
380
|
+
stage_status: planDocsComplete ? 'awaiting-approval' : 'blocked',
|
|
381
|
+
plan_package_status: planDocsComplete ? 'complete' : 'partial',
|
|
342
382
|
plan_current_iteration: 1,
|
|
343
|
-
plan_principles_resolved:
|
|
344
|
-
plan_options_reviewed:
|
|
345
|
-
plan_architect_review_status: 'complete',
|
|
346
|
-
plan_critic_verdict: 'approve',
|
|
347
|
-
plan_acceptance_criteria_testable:
|
|
348
|
-
plan_verification_steps_resolved:
|
|
349
|
-
plan_execution_inputs_resolved:
|
|
350
|
-
plan_docs_status: 'complete',
|
|
383
|
+
plan_principles_resolved: planDocsComplete,
|
|
384
|
+
plan_options_reviewed: planDocsComplete,
|
|
385
|
+
plan_architect_review_status: planDocsComplete ? 'complete' : 'not-started',
|
|
386
|
+
plan_critic_verdict: planDocsComplete ? 'approve' : 'none',
|
|
387
|
+
plan_acceptance_criteria_testable: planDocsComplete,
|
|
388
|
+
plan_verification_steps_resolved: planDocsComplete,
|
|
389
|
+
plan_execution_inputs_resolved: planDocsComplete,
|
|
390
|
+
plan_docs_status: planDocsComplete ? 'complete' : 'partial',
|
|
391
|
+
plan_blockers: planBlockers,
|
|
351
392
|
approval: {
|
|
352
|
-
plan: APPROVAL_STATES.APPROVED,
|
|
393
|
+
plan: planDocsComplete ? APPROVAL_STATES.APPROVED : APPROVAL_STATES.NOT_REQUESTED,
|
|
353
394
|
build: APPROVAL_STATES.NOT_REQUESTED,
|
|
354
395
|
review: APPROVAL_STATES.NOT_REQUESTED,
|
|
355
396
|
rollback: APPROVAL_STATES.NOT_REQUESTED,
|
package/src/workflow.mjs
CHANGED
|
@@ -416,6 +416,11 @@ function createInitialState(slug, profile) {
|
|
|
416
416
|
plan_execution_inputs_resolved: false,
|
|
417
417
|
plan_docs_status: 'missing',
|
|
418
418
|
plan_docs_artifact_paths: null,
|
|
419
|
+
plan_delegation_decision_path: null,
|
|
420
|
+
plan_delegation_mode: 'local',
|
|
421
|
+
plan_delegation_score: 0,
|
|
422
|
+
plan_delegation_triggers: [],
|
|
423
|
+
plan_delegation_reason: null,
|
|
419
424
|
plan_review_artifact_paths: [],
|
|
420
425
|
plan_review_history: [],
|
|
421
426
|
plan_blockers: [],
|
|
@@ -749,6 +754,93 @@ async function writeRequirementTraceabilityArtifact({ root, sourceSpecPath, sour
|
|
|
749
754
|
};
|
|
750
755
|
}
|
|
751
756
|
|
|
757
|
+
function delegationDecisionForPlan(sourceText, plannerDraft) {
|
|
758
|
+
const source = String(sourceText || '');
|
|
759
|
+
const draft = [
|
|
760
|
+
plannerDraft.planText,
|
|
761
|
+
plannerDraft.architectureText,
|
|
762
|
+
plannerDraft.developmentPlanText,
|
|
763
|
+
plannerDraft.testPlanText,
|
|
764
|
+
].join('\n');
|
|
765
|
+
const combined = `${source}\n${draft}`;
|
|
766
|
+
const requirementCount = sourceRequirementItems(source).length;
|
|
767
|
+
const lineCount = source.split('\n').filter((line) => line.trim()).length;
|
|
768
|
+
const triggers = [];
|
|
769
|
+
let score = 0;
|
|
770
|
+
|
|
771
|
+
const addTrigger = (trigger, weight) => {
|
|
772
|
+
if (!triggers.includes(trigger)) {
|
|
773
|
+
triggers.push(trigger);
|
|
774
|
+
score += weight;
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
if (requirementCount >= 12 || lineCount >= 180) {
|
|
779
|
+
addTrigger('large_requirement_surface', 3);
|
|
780
|
+
} else if (requirementCount >= 6 || lineCount >= 90) {
|
|
781
|
+
addTrigger('medium_requirement_surface', 2);
|
|
782
|
+
}
|
|
783
|
+
if (/资金|资产|清算|结算|交易|订单|风控|权限|安全|合规|审计|corporate action|settlement|trading|order|asset|security|auth|permission|compliance|audit|financial/i.test(combined)) {
|
|
784
|
+
addTrigger('high_risk_domain', 3);
|
|
785
|
+
}
|
|
786
|
+
if (/api|接口|service|biz|data|database|schema|migration|数据库|迁移|worker|cron|frontend|后台|部署|deploy/i.test(combined)) {
|
|
787
|
+
addTrigger('cross_module_scope', 2);
|
|
788
|
+
}
|
|
789
|
+
if (/状态机|幂等|补偿|差异|回滚|并发|重试|eventual|idempot|retry|rollback|concurrency|state machine/i.test(combined)) {
|
|
790
|
+
addTrigger('state_or_integrity_complexity', 2);
|
|
791
|
+
}
|
|
792
|
+
if (/e2e|集成测试|integration|regression|回归|验收|acceptance|fixture|mock|真实数据|external/i.test(combined)) {
|
|
793
|
+
addTrigger('verification_complexity', 1);
|
|
794
|
+
}
|
|
795
|
+
if (/多个方案|备选|取舍|tradeoff|alternative|ADR|architecture/i.test(combined)) {
|
|
796
|
+
addTrigger('architectural_tradeoff', 1);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
const mode = score >= 7 ? 'parallel-review' : (score >= 4 ? 'critic-only' : 'local');
|
|
800
|
+
const reason = mode === 'parallel-review'
|
|
801
|
+
? '高风险或跨模块规划,建议独立 Planner/Architect/Critic 视角并行审查。'
|
|
802
|
+
: mode === 'critic-only'
|
|
803
|
+
? '存在中等复杂度或验证风险,建议至少引入独立 critic 复核 PRD 覆盖和风险。'
|
|
804
|
+
: '范围较小或风险较低,本地顺序 Planner/Architect/Critic 审阅足够。';
|
|
805
|
+
|
|
806
|
+
return {
|
|
807
|
+
mode,
|
|
808
|
+
score,
|
|
809
|
+
triggers,
|
|
810
|
+
reason,
|
|
811
|
+
current_runtime_execution: 'local-sequential',
|
|
812
|
+
execution_note: '当前 runtime 记录委派决策依据;是否实际启动 native subagents 仍受执行环境和用户授权约束。',
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
async function writePlanDelegationDecisionArtifact({ root, sourceText, plannerDraft }) {
|
|
817
|
+
const decision = delegationDecisionForPlan(sourceText, plannerDraft);
|
|
818
|
+
const path = artifactPath(root, 'plan-delegation-decision.md');
|
|
819
|
+
await writeText(path, [
|
|
820
|
+
'# Plan Delegation Decision',
|
|
821
|
+
'',
|
|
822
|
+
`- mode: ${decision.mode}`,
|
|
823
|
+
`- score: ${decision.score}`,
|
|
824
|
+
`- current_runtime_execution: ${decision.current_runtime_execution}`,
|
|
825
|
+
`- reason: ${decision.reason}`,
|
|
826
|
+
'',
|
|
827
|
+
'## Triggers',
|
|
828
|
+
'',
|
|
829
|
+
...(decision.triggers.length > 0 ? decision.triggers.map((item) => `- ${item}`) : ['- none']),
|
|
830
|
+
'',
|
|
831
|
+
'## Guidance',
|
|
832
|
+
'',
|
|
833
|
+
'- local: 低风险、小范围、单模块任务,本地顺序 Planner/Architect/Critic 即可。',
|
|
834
|
+
'- critic-only: 中等风险或覆盖面较宽,至少需要独立 critic 复核 PRD 覆盖、验证和遗漏风险。',
|
|
835
|
+
'- parallel-review: 高风险、多模块、状态/资产/安全相关任务,建议独立 Planner/Architect/Critic 视角并行审查。',
|
|
836
|
+
'',
|
|
837
|
+
'## Runtime Note',
|
|
838
|
+
'',
|
|
839
|
+
`- ${decision.execution_note}`,
|
|
840
|
+
].join('\n'));
|
|
841
|
+
return { path, ...decision };
|
|
842
|
+
}
|
|
843
|
+
|
|
752
844
|
function frontmatterList(text, key) {
|
|
753
845
|
if (!text.startsWith('---\n')) {
|
|
754
846
|
return [];
|
|
@@ -1522,6 +1614,31 @@ function containsChineseText(text) {
|
|
|
1522
1614
|
return chineseChars.length >= 40 || (chineseChars.length >= 8 && chineseChars.length / signalChars >= 0.2);
|
|
1523
1615
|
}
|
|
1524
1616
|
|
|
1617
|
+
async function planLanguageBlockers(pathsByKey) {
|
|
1618
|
+
const blockers = [];
|
|
1619
|
+
for (const [key, path] of Object.entries(pathsByKey)) {
|
|
1620
|
+
if (!existsSync(path)) {
|
|
1621
|
+
blockers.push(`missing_plan_artifact_${key}`);
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
const text = await readFile(path, 'utf8');
|
|
1625
|
+
if (!containsChineseText(text)) {
|
|
1626
|
+
blockers.push(`plan_artifact_not_chinese_${key}`);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
return blockers;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
function planReviewArtifactBlockers(state) {
|
|
1633
|
+
if (!Array.isArray(state.plan_review_artifact_paths) || state.plan_review_artifact_paths.length === 0) {
|
|
1634
|
+
return ['missing_plan_review_artifacts'];
|
|
1635
|
+
}
|
|
1636
|
+
const latest = state.plan_review_artifact_paths[state.plan_review_artifact_paths.length - 1] || {};
|
|
1637
|
+
return ['planner', 'architect', 'critic']
|
|
1638
|
+
.filter((key) => !latest[key] || !existsSync(latest[key]))
|
|
1639
|
+
.map((key) => `missing_plan_review_artifact_${key}`);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1525
1642
|
async function ensurePlanWorkflowFromDirectSpec(cwd, directSpecPath, explicitSlug, options = {}) {
|
|
1526
1643
|
const resolvedSpecPath = resolve(cwd, directSpecPath);
|
|
1527
1644
|
const specText = await readFile(resolvedSpecPath, 'utf8');
|
|
@@ -1681,6 +1798,10 @@ async function readPlanCompletion(cwd, root, slug, state) {
|
|
|
1681
1798
|
if (!state.requirement_traceability_path || !existsSync(state.requirement_traceability_path)) {
|
|
1682
1799
|
blockers.push('missing_requirement_traceability');
|
|
1683
1800
|
}
|
|
1801
|
+
if (!state.plan_delegation_decision_path || !existsSync(state.plan_delegation_decision_path)) {
|
|
1802
|
+
blockers.push('missing_plan_delegation_decision');
|
|
1803
|
+
}
|
|
1804
|
+
blockers.push(...planReviewArtifactBlockers(state));
|
|
1684
1805
|
if (state.source_requirements_status && state.source_requirements_status !== 'complete') {
|
|
1685
1806
|
if (state.requirement_traceability_path && existsSync(state.requirement_traceability_path)) {
|
|
1686
1807
|
const traceabilityText = await readFile(state.requirement_traceability_path, 'utf8');
|
|
@@ -1695,22 +1816,16 @@ async function readPlanCompletion(cwd, root, slug, state) {
|
|
|
1695
1816
|
blockers.push(`source_requirements_${state.source_requirements_status}`);
|
|
1696
1817
|
}
|
|
1697
1818
|
}
|
|
1698
|
-
|
|
1819
|
+
blockers.push(...await planLanguageBlockers({
|
|
1699
1820
|
plan: artifactPath(root, 'plan.md'),
|
|
1700
1821
|
architecture: artifactPath(root, 'architecture.md'),
|
|
1701
1822
|
developmentPlan: artifactPath(root, 'development-plan.md'),
|
|
1702
1823
|
testPlan: artifactPath(root, 'test-plan.md'),
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
}
|
|
1709
|
-
const text = await readFile(path, 'utf8');
|
|
1710
|
-
if (!containsChineseText(text)) {
|
|
1711
|
-
blockers.push(`plan_artifact_not_chinese_${key}`);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1824
|
+
prd: state.plan_artifact_path || join(resolvePlansRoot(cwd), `prd-${slug}.md`),
|
|
1825
|
+
testSpec: state.test_spec_artifact_path || join(resolvePlansRoot(cwd), `test-spec-${slug}.md`),
|
|
1826
|
+
traceability: state.requirement_traceability_path || artifactPath(root, 'requirement-traceability.md'),
|
|
1827
|
+
delegationDecision: state.plan_delegation_decision_path || artifactPath(root, 'plan-delegation-decision.md'),
|
|
1828
|
+
}));
|
|
1714
1829
|
const changeStatus = await readChangeArtifactStatus(state.change_artifact_paths);
|
|
1715
1830
|
blockers.push(...changeStatus.blockers);
|
|
1716
1831
|
|
|
@@ -2248,7 +2363,7 @@ function buildCurrentEvidenceChain(state, readiness = buildReadiness(state), aut
|
|
|
2248
2363
|
evidence.push(evidenceEntry(
|
|
2249
2364
|
'review_approved',
|
|
2250
2365
|
'Review verdict is approve.',
|
|
2251
|
-
authorization.done.authorized ? '
|
|
2366
|
+
authorization.done.authorized ? 'Archive can consume the approved review -> done transition before syncing specs.' : 'Completion still requires explicit review -> done authorization.',
|
|
2252
2367
|
));
|
|
2253
2368
|
}
|
|
2254
2369
|
if (state.archive_status === 'archived' && state.spec_sync_status === 'synced') {
|
|
@@ -2371,9 +2486,7 @@ function recommendedAction(state, legacy = false) {
|
|
|
2371
2486
|
: 'Approve build -> review when execution-record.md is complete.';
|
|
2372
2487
|
case STAGES.REVIEW:
|
|
2373
2488
|
if (state.review_verdict === 'approve') {
|
|
2374
|
-
return
|
|
2375
|
-
? 'Run loopx review again to consume the approved review -> done transition.'
|
|
2376
|
-
: 'Approve review -> done to complete the workflow.';
|
|
2489
|
+
return 'Run loopx archive; archive consumes the pending review -> done completion transition before syncing specs.';
|
|
2377
2490
|
}
|
|
2378
2491
|
if (state.review_verdict === 'request-changes') {
|
|
2379
2492
|
if (state.requested_transition === TRANSITIONS.REVIEW_TO_BUILD && state.approval.build === APPROVAL_STATES.APPROVED) {
|
|
@@ -2574,7 +2687,11 @@ function nextCommandForRollbackTarget(slug, target) {
|
|
|
2574
2687
|
if (target === 'none') {
|
|
2575
2688
|
return [
|
|
2576
2689
|
'Next:',
|
|
2690
|
+
`$archive ${slug}`,
|
|
2691
|
+
'',
|
|
2692
|
+
'CLI-only equivalent:',
|
|
2577
2693
|
`loopx approve ${slug} --from review --to done`,
|
|
2694
|
+
`loopx archive ${slug}`,
|
|
2578
2695
|
].join('\n');
|
|
2579
2696
|
}
|
|
2580
2697
|
return [
|
|
@@ -2587,7 +2704,7 @@ function nextCommandForRollbackTarget(slug, target) {
|
|
|
2587
2704
|
function reviewUserMessageZh({ slug, verdict, rollbackTarget, findings }) {
|
|
2588
2705
|
const label = reviewVerdictLabel(verdict);
|
|
2589
2706
|
const next = verdict === 'APPROVE'
|
|
2590
|
-
?
|
|
2707
|
+
? `下一步:直接归档;archive 会先消费 pending 的 review -> done 完成态。\n${nextCommandForRollbackTarget(slug, 'none')}`
|
|
2591
2708
|
: `下一步:按审查发现处理,并${rollbackTargetLabel(rollbackTarget)}。\n${nextCommandForRollbackTarget(slug, rollbackTarget)}`;
|
|
2592
2709
|
const findingText = Array.isArray(findings) && findings.length > 0 ? findings.join(';') : '无额外发现。';
|
|
2593
2710
|
return `Review 结果:${slug} ${label}。审查发现:${findingText} ${next}`;
|
|
@@ -2833,7 +2950,9 @@ export async function clarifyStage(cwd, slug, { profile = 'standard' } = {}) {
|
|
|
2833
2950
|
},
|
|
2834
2951
|
});
|
|
2835
2952
|
await writeState(root, state);
|
|
2836
|
-
|
|
2953
|
+
const rendered = await renderPlanReadingViews(cwd, root, state, normalized);
|
|
2954
|
+
await writeState(root, rendered);
|
|
2955
|
+
return { root, state: rendered };
|
|
2837
2956
|
}
|
|
2838
2957
|
|
|
2839
2958
|
export async function approveStage(cwd, slug, { from, to }) {
|
|
@@ -3199,6 +3318,11 @@ export async function planStage(cwd, slug, options = {}) {
|
|
|
3199
3318
|
plannerDraft,
|
|
3200
3319
|
changeArtifactPaths,
|
|
3201
3320
|
});
|
|
3321
|
+
const delegationDecision = await writePlanDelegationDecisionArtifact({
|
|
3322
|
+
root,
|
|
3323
|
+
sourceText,
|
|
3324
|
+
plannerDraft,
|
|
3325
|
+
});
|
|
3202
3326
|
|
|
3203
3327
|
architectReview = await adapter.architect({
|
|
3204
3328
|
cwd,
|
|
@@ -3247,6 +3371,11 @@ export async function planStage(cwd, slug, options = {}) {
|
|
|
3247
3371
|
requirement_traceability_path: traceability.path,
|
|
3248
3372
|
source_requirements_status: traceability.status,
|
|
3249
3373
|
source_requirements_item_count: traceability.itemCount,
|
|
3374
|
+
plan_delegation_decision_path: delegationDecision.path,
|
|
3375
|
+
plan_delegation_mode: delegationDecision.mode,
|
|
3376
|
+
plan_delegation_score: delegationDecision.score,
|
|
3377
|
+
plan_delegation_triggers: delegationDecision.triggers,
|
|
3378
|
+
plan_delegation_reason: delegationDecision.reason,
|
|
3250
3379
|
change_id: normalizeSlug(changeId),
|
|
3251
3380
|
change_artifacts_status: changeArtifactStatus.status,
|
|
3252
3381
|
change_artifact_paths: changeArtifactPaths,
|
|
@@ -3929,7 +4058,7 @@ export async function reviewStage(cwd, slug, { reviewer = 'independent-reviewer'
|
|
|
3929
4058
|
verdict: reviewInput.verdict,
|
|
3930
4059
|
reviewMessageZh: reviewMessage,
|
|
3931
4060
|
evidenceManifest: reviewInput.evidenceManifest,
|
|
3932
|
-
followUps: ['
|
|
4061
|
+
followUps: ['执行 $archive;archive 会消费 pending 的 review -> done 完成态。'],
|
|
3933
4062
|
});
|
|
3934
4063
|
} catch (error) {
|
|
3935
4064
|
journalWarning = error instanceof Error ? error.message : String(error);
|