@khoavu882/doflow 2.0.0-beta.4 → 2.0.0-beta.5

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 (101) hide show
  1. package/core/.antigravity-plugin/plugin.json +0 -1
  2. package/core/.claude-plugin/plugin.json +1 -1
  3. package/core/.codex-plugin/plugin.json +1 -1
  4. package/core/.plugin/plugin.json +1 -1
  5. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
  6. package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
  7. package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
  8. package/core/harnesses/claude/hooks/session-start.sh +5 -3
  9. package/core/harnesses/claude/hooks/stop-check.sh +5 -3
  10. package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
  11. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
  12. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
  13. package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
  14. package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
  15. package/core/harnesses/codex/hooks/session-start.sh +5 -3
  16. package/core/harnesses/codex/hooks/stop-check.sh +6 -5
  17. package/core/harnesses/codex/hooks/subagent-audit.sh +17 -6
  18. package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
  19. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +7 -18
  20. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +7 -18
  21. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +7 -19
  22. package/core/harnesses/gemini/hooks/session-start.sh +5 -3
  23. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +20 -5
  24. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +20 -5
  25. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +20 -5
  26. package/core/harnesses/kiro/hooks/session-start.sh +11 -5
  27. package/core/harnesses/kiro/hooks/stop-check.sh +21 -30
  28. package/core/harnesses/pi/extensions/doflow-guard.js +159 -0
  29. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -11
  30. package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
  31. package/core/harnesses/shared/hooks/bridge/bridge.sh +184 -0
  32. package/core/harnesses/shared/hooks/bridge/envelope.jq +60 -0
  33. package/core/harnesses/shared/hooks/bridge/respond.sh +62 -0
  34. package/core/harnesses/shared/hooks/policies/capture-failure.sh +4 -2
  35. package/core/harnesses/shared/hooks/policies/contract.sh +75 -0
  36. package/core/harnesses/shared/hooks/policies/deny-json.sh +39 -4
  37. package/core/harnesses/shared/hooks/policies/lib.sh +4 -2
  38. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +46 -34
  39. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +75 -25
  40. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +67 -73
  41. package/core/harnesses/shared/hooks/policies/session-context.sh +37 -7
  42. package/core/harnesses/shared/hooks/policies/stop-check.sh +42 -15
  43. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +35 -5
  44. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +40 -7
  45. package/core/harnesses/shared/hooks/stream-hook-runner.js +69 -181
  46. package/core/registry/assets.json +19 -0
  47. package/core/registry/contracts.json +2 -2
  48. package/core/registry/harnesses.json +196 -10
  49. package/core/registry/lifecycle.json +2626 -7
  50. package/core/registry/storage.json +24 -1
  51. package/core/shared/scripts/doflow/bin/doflow-run +10 -6
  52. package/core/shared/skills/do-design/SKILL.md +6 -6
  53. package/core/shared/skills/do-execute-plan/SKILL.md +11 -10
  54. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +2 -0
  55. package/core/shared/skills/do-implement/SKILL.md +3 -2
  56. package/core/shared/skills/do-plan/SKILL.md +7 -8
  57. package/package.json +1 -1
  58. package/src/adapters/antigravity/index.js +83 -47
  59. package/src/adapters/claude/index.js +15 -1
  60. package/src/adapters/codex/hooks.js +40 -5
  61. package/src/adapters/codex/index.js +52 -9
  62. package/src/adapters/copy-tree.js +4 -4
  63. package/src/adapters/gemini/hooks.js +57 -16
  64. package/src/adapters/gemini/index.js +57 -18
  65. package/src/adapters/kiro/index.js +15 -1
  66. package/src/adapters/pi/hooks.js +119 -0
  67. package/src/adapters/pi/index.js +34 -9
  68. package/src/cli/commands/install.js +1 -1
  69. package/src/cli/commands/update.js +1 -1
  70. package/src/cli/index.js +17 -5
  71. package/src/cli/runtime-commands.js +51 -12
  72. package/src/lifecycle/coverage.js +57 -0
  73. package/src/lifecycle/hook-step.js +61 -0
  74. package/src/lifecycle/index.js +28 -14
  75. package/src/registry/index.js +136 -7
  76. package/src/runtime/candidate.js +505 -0
  77. package/src/runtime/claims.js +14 -5
  78. package/src/runtime/cli-result.js +11 -4
  79. package/src/runtime/cli.js +35 -268
  80. package/src/runtime/context/budget.js +203 -0
  81. package/src/runtime/context/compose.js +1367 -0
  82. package/src/runtime/context/delivery-store.js +102 -0
  83. package/src/runtime/context/mandatory.js +594 -0
  84. package/src/runtime/context/pointer.js +142 -0
  85. package/src/runtime/context-pack.js +1029 -244
  86. package/src/runtime/evidence-fields.js +39 -0
  87. package/src/runtime/evidence-ledger.js +7 -0
  88. package/src/runtime/freshness.js +44 -7
  89. package/src/runtime/outcome.js +1 -1
  90. package/src/runtime/readiness.js +83 -13
  91. package/src/runtime/retrieval-plan.js +422 -73
  92. package/src/runtime/retrieval-record.js +223 -0
  93. package/src/runtime/scaffold/artifacts.js +3 -0
  94. package/src/runtime/source-version.js +289 -0
  95. package/src/runtime/task-attempts.js +1 -1
  96. package/src/runtime/task-scope.js +28 -3
  97. package/src/runtime/task-state.js +72 -7
  98. package/core/.antigravity-plugin/hooks.json +0 -39
  99. package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
  100. package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
  101. package/core/harnesses/shared/hooks/hooks.json +0 -47
@@ -0,0 +1,142 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration: run directly by Node native type-stripping.
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const crypto = require('node:crypto');
7
+
8
+ function sha256(text ) {
9
+ return `sha256:${crypto.createHash('sha256').update(text, 'utf8').digest('hex')}`;
10
+ }
11
+
12
+ function inside(root , file , fsImpl = fs) {
13
+ const absolute = path.resolve(file);
14
+ let realRoot ;
15
+ let realFile ;
16
+ try {
17
+ realRoot = fsImpl.realpathSync(path.resolve(root));
18
+ realFile = fsImpl.realpathSync(absolute);
19
+ } catch { return null; }
20
+ const relative = path.relative(realRoot, realFile);
21
+ if (!relative || relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) return null;
22
+ const normalized = relative.split(path.sep).join('/');
23
+ if (normalized.split('/').includes('state')) return null;
24
+ return normalized;
25
+ }
26
+
27
+ function lineSlice(lines , startLine , endLine ) {
28
+ return lines.slice(startLine - 1, endLine).join('\n') + '\n';
29
+ }
30
+
31
+ function rangesFor(file , text , requirement ) {
32
+ const lines = text.split(/\r?\n/);
33
+ const result = [];
34
+ if (requirement) {
35
+ let section = '';
36
+ for (let i = 0; i < lines.length; i++) {
37
+ const heading = lines[i].match(/^##\s+(.*)$/);
38
+ if (heading) section = heading[1];
39
+ if (!/^##\s+[34](?:[.)]|\s|$)/.test(lines[i])) continue;
40
+ let end = i + 1;
41
+ while (end < lines.length && !/^##\s+/.test(lines[end])) end++;
42
+ for (let j = i + 1; j < end; j++) {
43
+ if (!/^\s*\*\*Detail:?\*\*/i.test(lines[j])) continue;
44
+ let blockEnd = j + 1;
45
+ while (blockEnd < end && !/^\s*\*\*[A-Za-z][^*]*:?\*\*/.test(lines[blockEnd])) blockEnd++;
46
+ result.push({ startLine: j + 1, endLine: blockEnd, heading: section || null });
47
+ j = blockEnd - 1;
48
+ }
49
+ i = end - 1;
50
+ }
51
+ return result;
52
+ }
53
+ let start = -1;
54
+ let title = null;
55
+ const flush = (end ) => {
56
+ if (start >= 0 && end >= start) result.push({ startLine: start + 1, endLine: end, heading: title });
57
+ };
58
+ for (let i = 0; i < lines.length; i++) {
59
+ const heading = lines[i].match(/^##\s+(.+)$/);
60
+ if (heading) {
61
+ flush(i);
62
+ start = i;
63
+ title = heading[1].trim();
64
+ }
65
+ }
66
+ flush(lines.length);
67
+ return result;
68
+ }
69
+
70
+ function createPointer({ path: rel, heading, range, slice } ) {
71
+ const bytes = Buffer.byteLength(slice, 'utf8');
72
+ return {
73
+ id: `ptr:${rel}:${range.startLine}-${range.endLine}`,
74
+ path: rel,
75
+ heading,
76
+ range,
77
+ digest: sha256(slice),
78
+ bytes,
79
+ tokensEst: { value: Math.ceil(bytes / 4), basis: 'estimated:bytes/4' },
80
+ inlineBytes: Buffer.byteLength(`- ptr:${rel}:${range.startLine}-${range.endLine} ${rel}:${range.startLine}-${range.endLine} ${bytes} B\n`, 'utf8'),
81
+ load: `read ${rel} lines ${range.startLine}-${range.endLine}`,
82
+ };
83
+ }
84
+
85
+ function sourceFiles({ projectRoot, feature, fsImpl = fs } ) {
86
+ const root = path.resolve(projectRoot);
87
+ const featureDir = feature?.featureDir ? path.resolve(feature.featureDir) : null;
88
+ const candidates = [];
89
+ const add = (file , requirement = false) => {
90
+ if (!file) return;
91
+ const absolute = path.isAbsolute(file) ? file : path.resolve(feature?.repoRoot || root, file);
92
+ let stat ;
93
+ try { stat = fsImpl.statSync(absolute); } catch { return; }
94
+ if (!inside(root, absolute, fsImpl) || !stat.isFile()) return;
95
+ if (!candidates.some((item) => item.absolute === absolute)) candidates.push({ absolute, requirement });
96
+ };
97
+ if (featureDir) {
98
+ add(feature.paths?.requirement || path.join(featureDir, 'intention', 'requirement.md'), true);
99
+ for (const file of [
100
+ feature.paths?.design,
101
+ feature.paths?.plan,
102
+ path.join(featureDir, 'design', 'design.md'),
103
+ path.join(featureDir, 'design', 'specs.md'),
104
+ path.join(featureDir, 'design', 'data-model.md'),
105
+ path.join(featureDir, 'plan', 'plan.md'),
106
+ path.join(featureDir, 'design.md'),
107
+ path.join(featureDir, 'plan.md'),
108
+ ]) add(file);
109
+ }
110
+ return candidates;
111
+ }
112
+
113
+ function collectPointers({ projectRoot, feature, fsImpl = fs } ) {
114
+ const root = path.resolve(projectRoot);
115
+ const pointers = [];
116
+ for (const source of sourceFiles({ projectRoot: root, feature, fsImpl })) {
117
+ const rel = inside(root, source.absolute, fsImpl);
118
+ if (!rel) continue;
119
+ let text ;
120
+ try { text = fsImpl.readFileSync(source.absolute, 'utf8'); } catch { continue; }
121
+ const lines = text.split(/\r?\n/);
122
+ for (const range of rangesFor(rel, text, source.requirement)) {
123
+ const slice = lineSlice(lines, range.startLine, range.endLine);
124
+ if (!slice.trim()) continue;
125
+ pointers.push(createPointer({ path: rel, heading: range.heading, range: { startLine: range.startLine, endLine: range.endLine }, slice }));
126
+ }
127
+ }
128
+ return pointers;
129
+ }
130
+
131
+ function readPointerSlice({ projectRoot, pointer, fsImpl = fs } ) {
132
+ const rel = inside(projectRoot, path.resolve(projectRoot, pointer.path), fsImpl);
133
+ if (!rel || rel !== pointer.path) return null;
134
+ const file = path.resolve(projectRoot, rel);
135
+ try {
136
+ const lines = fsImpl.readFileSync(file, 'utf8').split(/\r?\n/);
137
+ const slice = lineSlice(lines, pointer.range.startLine, pointer.range.endLine);
138
+ return { slice, digest: sha256(slice) };
139
+ } catch { return null; }
140
+ }
141
+
142
+ module.exports = { collectPointers, createPointer, readPointerSlice, sha256 };