@ai-content-space/loopx 0.2.1 → 0.2.3

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.
Files changed (48) hide show
  1. package/README.md +6 -1
  2. package/README.zh-CN.md +6 -1
  3. package/docs/loopx/design/loopx-skill-suite-v1-design.md +4 -3
  4. package/package.json +1 -1
  5. package/plugins/loopx/.codex-plugin/plugin.json +1 -1
  6. package/plugins/loopx/skills/clarify/SKILL.md +1 -1
  7. package/plugins/loopx/skills/debug/SKILL.md +1 -1
  8. package/plugins/loopx/skills/exec/SKILL.md +7 -2
  9. package/plugins/loopx/skills/final-review/SKILL.md +89 -0
  10. package/plugins/loopx/skills/final-review/final-reviewer.md +135 -0
  11. package/plugins/loopx/skills/finish/SKILL.md +8 -1
  12. package/plugins/loopx/skills/fix-review/SKILL.md +1 -1
  13. package/plugins/loopx/skills/go-style/SKILL.md +8 -2
  14. package/plugins/loopx/skills/kratos/SKILL.md +7 -1
  15. package/plugins/loopx/skills/plan/SKILL.md +3 -3
  16. package/plugins/loopx/skills/refactor-plan/SKILL.md +1 -1
  17. package/plugins/loopx/skills/review/SKILL.md +1 -1
  18. package/plugins/loopx/skills/spec/SKILL.md +1 -1
  19. package/plugins/loopx/skills/subagent-exec/SKILL.md +7 -6
  20. package/plugins/loopx/skills/subagent-exec/agents/openai.yaml +2 -2
  21. package/plugins/loopx/skills/subagent-exec/codex-subagents.md +1 -1
  22. package/plugins/loopx/skills/tdd/SKILL.md +1 -1
  23. package/plugins/loopx/skills/verify/SKILL.md +1 -1
  24. package/scripts/codex-workflow-hook.mjs +36 -5
  25. package/skills/RESOLVER.md +7 -4
  26. package/skills/clarify/SKILL.md +1 -1
  27. package/skills/debug/SKILL.md +1 -1
  28. package/skills/exec/SKILL.md +7 -2
  29. package/skills/final-review/SKILL.md +89 -0
  30. package/skills/final-review/final-reviewer.md +135 -0
  31. package/skills/finish/SKILL.md +8 -1
  32. package/skills/fix-review/SKILL.md +1 -1
  33. package/skills/go-style/SKILL.md +8 -2
  34. package/skills/kratos/SKILL.md +7 -1
  35. package/skills/plan/SKILL.md +3 -3
  36. package/skills/refactor-plan/SKILL.md +1 -1
  37. package/skills/review/SKILL.md +1 -1
  38. package/skills/spec/SKILL.md +1 -1
  39. package/skills/subagent-exec/SKILL.md +7 -6
  40. package/skills/subagent-exec/agents/openai.yaml +2 -2
  41. package/skills/subagent-exec/codex-subagents.md +1 -1
  42. package/skills/tdd/SKILL.md +1 -1
  43. package/skills/verify/SKILL.md +1 -1
  44. package/src/build-stop-gate.mjs +1 -1
  45. package/src/cli.mjs +5 -1
  46. package/src/install-discovery.mjs +1 -28
  47. package/src/next-skill.mjs +46 -5
  48. package/src/workflow.mjs +4 -4
@@ -21,6 +21,7 @@ const LOOPX_SKILLS = [
21
21
  'subagent-exec',
22
22
  'exec',
23
23
  'review',
24
+ 'final-review',
24
25
  'fix-review',
25
26
  'finish',
26
27
  'refactor-plan',
@@ -30,18 +31,6 @@ const LOOPX_SKILLS = [
30
31
  'go-style',
31
32
  'kratos',
32
33
  ];
33
- const LOOPX_LEGACY_SKILLS = [
34
- 'build',
35
- 'autopilot',
36
- 'archive',
37
- 'writing-plans',
38
- 'executing-plans',
39
- 'subagent-driven-development',
40
- 'requesting-code-review',
41
- 'receiving-code-review',
42
- 'finishing-a-development-branch',
43
- 'request-refactor-plan',
44
- ];
45
34
  const LOOPX_INSTALLATION_IDENTITY = 'loopx';
46
35
  const LOOPX_MANAGED_SCRIPT_ITEMS = [
47
36
  {
@@ -452,20 +441,6 @@ async function removeStaleOwnedInstall(currentRow) {
452
441
  await removeInstalledSkill(currentRow.installedPath);
453
442
  }
454
443
 
455
- async function pruneLegacyLoopxOwnedSkills(nextData, env = process.env) {
456
- const pruned = [];
457
- for (const skillName of LOOPX_LEGACY_SKILLS) {
458
- const row = nextData.skills?.[skillName];
459
- if (!isLoopxOwnedIdentity(skillName, row, env)) {
460
- continue;
461
- }
462
- await removeStaleOwnedInstall(row);
463
- delete nextData.skills[skillName];
464
- pruned.push({ skillName, installedPath: row.installedPath });
465
- }
466
- return pruned;
467
- }
468
-
469
444
  async function removeInstalledFile(path) {
470
445
  if (!existsSync(path)) {
471
446
  return;
@@ -667,7 +642,6 @@ export async function installBundledSkills(env = process.env, options = {}) {
667
642
  const nextData = jsonClone(data);
668
643
  nextData.version = nextData.version || 3;
669
644
  nextData.skills = nextData.skills || {};
670
- const pruned = await pruneLegacyLoopxOwnedSkills(nextData, env);
671
645
  const baselinePath = getTemplateBaselinePath(env);
672
646
  const existingBaseline = await readTemplateBaseline(baselinePath);
673
647
  const baselineItemsByPath = new Map((existingBaseline?.items || []).map((item) => [templateItemKey(item), item]));
@@ -766,7 +740,6 @@ export async function installBundledSkills(env = process.env, options = {}) {
766
740
  installed,
767
741
  conflicts,
768
742
  skipped,
769
- pruned,
770
743
  templateGovernance,
771
744
  inspection: await inspectInstallState(env),
772
745
  };
@@ -2,7 +2,6 @@ export function nextSkillCommand(state) {
2
2
  if (!state || !state.slug) {
3
3
  return null;
4
4
  }
5
- const reviewBuildCommand = `$build --from-review .loopx/workflows/${state.slug}/review-report.md`;
6
5
  if (state.current_stage === 'clarify'
7
6
  && state.clarify_current_round > 0
8
7
  && state.unresolved_ambiguity_count === 0
@@ -28,7 +27,7 @@ export function nextSkillCommand(state) {
28
27
  return null;
29
28
  }
30
29
  if (state.current_stage === 'plan' && Array.isArray(state.plan_blockers) && state.plan_blockers.length === 0) {
31
- return `$build .loopx/plans/requirements-snapshot-${state.slug}.md`;
30
+ return `$subagent-exec .loopx/plans/requirements-snapshot-${state.slug}.md`;
32
31
  }
33
32
  if (state.current_stage === 'build'
34
33
  && state.stage_status === 'awaiting-approval'
@@ -48,13 +47,13 @@ export function nextSkillCommand(state) {
48
47
  || state.approval?.build === 'requested'
49
48
  || state.approval?.build === 'approved'
50
49
  )) {
51
- return reviewBuildCommand;
50
+ return null;
52
51
  }
53
52
  if (state.current_stage === 'review'
54
53
  && state.review_verdict === 'request-changes'
55
54
  && state.requested_transition === 'review->build'
56
55
  && state.approval?.build === 'approved') {
57
- return reviewBuildCommand;
56
+ return null;
58
57
  }
59
58
  if (state.current_stage === 'review'
60
59
  && state.review_verdict === 'request-changes'
@@ -71,20 +70,62 @@ export function nextSkillCommand(state) {
71
70
  return null;
72
71
  }
73
72
 
73
+ export function nextCliCommand(state) {
74
+ if (!state || !state.slug) {
75
+ return null;
76
+ }
77
+ if (state.stage_status === 'awaiting-approval'
78
+ && state.current_stage === 'plan'
79
+ && Array.isArray(state.plan_blockers)
80
+ && state.plan_blockers.length === 0) {
81
+ return `loopx build .loopx/plans/requirements-snapshot-${state.slug}.md`;
82
+ }
83
+ if (state.current_stage === 'review'
84
+ && state.review_verdict === 'request-changes'
85
+ && state.rollback_target === 'build'
86
+ && (
87
+ state.pending_user_decision === 'review->build'
88
+ || state.requested_transition === 'review->build'
89
+ || state.approval?.build === 'requested'
90
+ || state.approval?.build === 'approved'
91
+ )) {
92
+ return `loopx build --from-review .loopx/workflows/${state.slug}/review-report.md`;
93
+ }
94
+ if (state.current_stage === 'review'
95
+ && state.review_verdict === 'request-changes'
96
+ && state.requested_transition === 'review->build'
97
+ && state.approval?.build === 'approved') {
98
+ return `loopx build --from-review .loopx/workflows/${state.slug}/review-report.md`;
99
+ }
100
+ return null;
101
+ }
102
+
74
103
  export function nextSkillHint(state) {
75
104
  const command = nextSkillCommand(state);
76
105
  if (!command) {
77
106
  return null;
78
107
  }
79
- return `Next: ${command}`;
108
+ return `Next skill: ${command}`;
109
+ }
110
+
111
+ export function nextCliHint(state) {
112
+ const command = nextCliCommand(state);
113
+ if (!command) {
114
+ return null;
115
+ }
116
+ return `Next CLI: ${command}`;
80
117
  }
81
118
 
82
119
  export function withNextSkill(payload, state) {
83
120
  const nextCommand = nextSkillCommand(state);
84
121
  const nextHint = nextSkillHint(state);
122
+ const cliCommand = nextCliCommand(state);
123
+ const cliHint = nextCliHint(state);
85
124
  return {
86
125
  ...payload,
87
126
  next_skill_command: nextCommand,
88
127
  next_skill_hint: nextHint,
128
+ next_cli_command: cliCommand,
129
+ next_cli_hint: cliHint,
89
130
  };
90
131
  }
package/src/workflow.mjs CHANGED
@@ -118,7 +118,7 @@ function reviewReportArtifactPath(slug) {
118
118
  }
119
119
 
120
120
  function reviewReworkBuildCommand(slug) {
121
- return `$build --from-review ${reviewReportArtifactPath(slug)}`;
121
+ return `loopx build --from-review ${reviewReportArtifactPath(slug)}`;
122
122
  }
123
123
 
124
124
  function nowIso() {
@@ -4203,7 +4203,7 @@ export async function buildStage(cwd, slug, options = {}) {
4203
4203
  active_delegation_count: delegationLedger?.active_blocking_count || 0,
4204
4204
  completion_audit_path: displayPath(cwd, completionAuditPath),
4205
4205
  completion_audit_status: completionAudit?.status || 'pending',
4206
- next_action: 'Continue $build execution and gather fresh implementation evidence.',
4206
+ next_action: 'Continue loopx build execution and gather fresh implementation evidence.',
4207
4207
  completion_signal: 'Build may stop only after execution-record.md is complete and build -> review handoff readiness is reached, or after a real blocker is recorded.',
4208
4208
  });
4209
4209
  current = await adapter.executeLanes({
@@ -4271,7 +4271,7 @@ export async function buildStage(cwd, slug, options = {}) {
4271
4271
  completion_audit_status: completionAudit.status,
4272
4272
  next_action: blockers.length === 0
4273
4273
  ? 'Verify execution evidence and prepare build -> review handoff.'
4274
- : 'Continue $build to resolve blockers before review handoff.',
4274
+ : 'Continue loopx build to resolve blockers before review handoff.',
4275
4275
  completion_signal: 'Build may stop only after execution-record.md is complete and build -> review handoff readiness is reached, or after a real blocker is recorded.',
4276
4276
  });
4277
4277
  const writtenSupportPaths = await writeBuildSupportArtifacts(root, current, noDeslop, {
@@ -4373,7 +4373,7 @@ export async function buildStage(cwd, slug, options = {}) {
4373
4373
  active_delegation_count: delegationLedger?.active_blocking_count || 0,
4374
4374
  completion_audit_path: displayPath(cwd, completionAuditPath),
4375
4375
  completion_audit_status: completionAudit?.status || (finalBlocked ? 'blocked' : 'passed'),
4376
- next_action: finalBlocked ? 'Run $build again after resolving recorded blockers.' : 'Approve build -> review and run $review.',
4376
+ next_action: finalBlocked ? 'Run loopx build again after resolving recorded blockers.' : 'Approve build -> review and run $review.',
4377
4377
  completion_signal: finalBlocked ? 'Build is stopped because real blockers remain recorded.' : 'execution-record.md is complete and build -> review handoff is ready.',
4378
4378
  execution_record_status: next.execution_record_status,
4379
4379
  execution_record_path: artifactPath(root, 'execution-record.md'),