@manhquy/flow-skill 0.1.0-rc.1
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/CHANGELOG.md +60 -0
- package/LICENSE +21 -0
- package/README.md +152 -0
- package/README_VN.md +134 -0
- package/SECURITY.md +69 -0
- package/bin/cli.mjs +382 -0
- package/package.json +52 -0
- package/skills/flow/SKILL.md +234 -0
- package/skills/flow/_templates/00-idea.md +16 -0
- package/skills/flow/_templates/00-inspect.md +42 -0
- package/skills/flow/_templates/01-research.md +59 -0
- package/skills/flow/_templates/02-scope.md +71 -0
- package/skills/flow/_templates/03-prd.md +57 -0
- package/skills/flow/_templates/04-adr.md +21 -0
- package/skills/flow/_templates/05-contract.md +59 -0
- package/skills/flow/_templates/card.md +26 -0
- package/skills/flow/_templates/constitution.md +22 -0
- package/skills/flow/eval/fixtures/f01a/flow/01-research.md +77 -0
- package/skills/flow/eval/fixtures/f01b/flow/01-research.md +75 -0
- package/skills/flow/eval/fixtures/f02a/flow/02-scope.md +56 -0
- package/skills/flow/eval/fixtures/f02b/flow/02-scope.md +65 -0
- package/skills/flow/eval/fixtures/fcda/.flow/.gitkeep +0 -0
- package/skills/flow/eval/fixtures/fcda/cards/C-001.md +46 -0
- package/skills/flow/eval/fixtures/fcdb/.flow/.gitkeep +0 -0
- package/skills/flow/eval/fixtures/fcdb/cards/C-001.md +35 -0
- package/skills/flow/eval/manifest.tsv +7 -0
- package/skills/flow/harness/README.md +117 -0
- package/skills/flow/harness/_db.py +228 -0
- package/skills/flow/harness/_domain.py +161 -0
- package/skills/flow/harness/_presence.py +109 -0
- package/skills/flow/harness/flow_harness.py +1103 -0
- package/skills/flow/harness/repo_map.py +93 -0
- package/skills/flow/harness/schema/001-init.sql +129 -0
- package/skills/flow/harness/schema/002-story-verify.sql +9 -0
- package/skills/flow/harness/schema/003-tool-registry.sql +15 -0
- package/skills/flow/harness/schema/004-intervention.sql +15 -0
- package/skills/flow/harness/schema/005-tool-extensions.sql +20 -0
- package/skills/flow/harness/schema/009-accessed-count.sql +11 -0
- package/skills/flow/harness/schema/010-usage-event.sql +42 -0
- package/skills/flow/harness/schema/011-usage-gate-reason.sql +8 -0
- package/skills/flow/harness/schema/012-usage-ephemeral.sql +10 -0
- package/skills/flow/law/CLAUDE.md +140 -0
- package/skills/flow/law/DESIGN.md +141 -0
- package/skills/flow/law/RETRO.md +13 -0
- package/skills/flow/playbooks/README.md +28 -0
- package/skills/flow/playbooks/cloudflare-ai-gateway-qwen.md +346 -0
- package/skills/flow/playbooks/docker-deploy-stale-cache.md +32 -0
- package/skills/flow/playbooks/rag-lite-postgres-cloudflare.md +192 -0
- package/skills/flow/playbooks/windows-gitbash-jsonl-telemetry.md +57 -0
- package/skills/flow/references/adversarial-review.md +197 -0
- package/skills/flow/references/agent-detection.md +88 -0
- package/skills/flow/references/agent-stage-mapping.md +114 -0
- package/skills/flow/references/antigravity-integration.md +92 -0
- package/skills/flow/references/auto-run.md +81 -0
- package/skills/flow/references/claudekit-skills.md +128 -0
- package/skills/flow/references/codex-integration.md +104 -0
- package/skills/flow/references/command-dispatch.md +54 -0
- package/skills/flow/references/debt-and-halts.md +41 -0
- package/skills/flow/references/design-review-checklist.md +42 -0
- package/skills/flow/references/gate-eval.md +186 -0
- package/skills/flow/references/gate-rules.md +171 -0
- package/skills/flow/references/ground-truth-gates.md +49 -0
- package/skills/flow/references/loop-harness-2026-principles.md +52 -0
- package/skills/flow/references/mode-work.md +37 -0
- package/skills/flow/references/project-types.md +42 -0
- package/skills/flow/references/stage-state-machine.md +47 -0
- package/skills/flow/references/ui-patterns-tcr.md +49 -0
- package/skills/flow/runner/flow.cmd +18 -0
- package/skills/flow/runner/flow.sh +3297 -0
- package/skills-manifest.json +70 -0
- package/src/constants.mjs +65 -0
- package/src/detect.mjs +36 -0
- package/src/help.mjs +42 -0
- package/src/installer.mjs +231 -0
- package/src/prompt.mjs +60 -0
- package/src/tty.mjs +11 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Tool presence probing for the inbound tool registry (stdlib only).
|
|
2
|
+
|
|
3
|
+
Ported from repository-harness crates/harness-cli/src/infrastructure.rs
|
|
4
|
+
(scan_tool_status, command_available, scan_target_resolves, http_reachable).
|
|
5
|
+
|
|
6
|
+
A probe NEVER raises: an absent tool is a fact to report (status 'missing'/'unknown'),
|
|
7
|
+
never an error that breaks a flow step. Status is one of: 'present', 'missing', 'unknown'.
|
|
8
|
+
Kind-aware so each agent runtime uses what it can orchestrate; an absent capability is a
|
|
9
|
+
clean skip. No third-party deps — only shutil / os / socket / urllib.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import shutil
|
|
14
|
+
import socket
|
|
15
|
+
from urllib.parse import urlparse
|
|
16
|
+
|
|
17
|
+
KINDS = ("cli", "binary", "mcp", "skill", "http")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _path_or_pathext_exists(p):
|
|
21
|
+
"""os.path.exists, plus Windows PATHEXT fallback so an extensionless path resolves
|
|
22
|
+
('C:/Program Files/Git/cmd/git' -> git.EXE). shutil.which does NOT apply PATHEXT to a
|
|
23
|
+
path that already contains a separator, so we check it ourselves."""
|
|
24
|
+
if os.path.exists(p):
|
|
25
|
+
return True
|
|
26
|
+
if os.name == "nt":
|
|
27
|
+
for ext in os.environ.get("PATHEXT", ".EXE;.BAT;.CMD").split(os.pathsep):
|
|
28
|
+
if ext and os.path.exists(p + ext):
|
|
29
|
+
return True
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _command_available(repo_root, command):
|
|
34
|
+
"""True if `command` resolves as a path or on PATH.
|
|
35
|
+
|
|
36
|
+
Tries the whole string first so a path containing spaces (common on Windows) resolves,
|
|
37
|
+
then the first whitespace token for the 'binary --arg' form. Each candidate is checked on
|
|
38
|
+
PATH (shutil.which, which applies PATHEXT to bare names) and as a literal/repo-relative
|
|
39
|
+
path (with a PATHEXT fallback for extensionless Windows paths)."""
|
|
40
|
+
if not command:
|
|
41
|
+
return False
|
|
42
|
+
cmd = command.strip()
|
|
43
|
+
if not cmd: # whitespace-only: a probe must never raise (no .split()[0] IndexError)
|
|
44
|
+
return False
|
|
45
|
+
candidates = [cmd]
|
|
46
|
+
first = cmd.split()[0]
|
|
47
|
+
if first != cmd:
|
|
48
|
+
candidates.append(first)
|
|
49
|
+
for cand in candidates:
|
|
50
|
+
if shutil.which(cand):
|
|
51
|
+
return True
|
|
52
|
+
if _path_or_pathext_exists(cand):
|
|
53
|
+
return True
|
|
54
|
+
if repo_root and _path_or_pathext_exists(os.path.join(repo_root, cand)):
|
|
55
|
+
return True
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _target_resolves(repo_root, target):
|
|
60
|
+
"""True if a declarative scan_target path (with ~ expansion) resolves on disk."""
|
|
61
|
+
if not target:
|
|
62
|
+
return False
|
|
63
|
+
p = os.path.expanduser(target)
|
|
64
|
+
if os.path.isabs(p):
|
|
65
|
+
return os.path.exists(p)
|
|
66
|
+
if os.path.exists(p):
|
|
67
|
+
return True
|
|
68
|
+
return bool(repo_root) and os.path.exists(os.path.join(repo_root, p))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _http_reachable(target):
|
|
72
|
+
"""True if a TCP connection to the target's host:port succeeds within 2s. Never raises.
|
|
73
|
+
|
|
74
|
+
Only http/https targets are probed (mirrors repository-harness): a non-http scheme or a
|
|
75
|
+
bare word is not a reachable-by-TCP endpoint, and probing it would trigger slow DNS/connect
|
|
76
|
+
on an unrelated host. Such targets fall through to the path-resolve fallback in scan_tool_status."""
|
|
77
|
+
if not (target.startswith("http://") or target.startswith("https://")):
|
|
78
|
+
return False
|
|
79
|
+
try:
|
|
80
|
+
u = urlparse(target, scheme="http")
|
|
81
|
+
host = u.hostname
|
|
82
|
+
if not host:
|
|
83
|
+
return False
|
|
84
|
+
port = u.port or (443 if u.scheme == "https" else 80)
|
|
85
|
+
with socket.create_connection((host, port), timeout=2):
|
|
86
|
+
return True
|
|
87
|
+
except Exception:
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def scan_tool_status(repo_root, kind, command, scan_target):
|
|
92
|
+
"""Kind-aware presence probe. Returns (status, detail); status in present/missing/unknown."""
|
|
93
|
+
kind = (kind or "cli").lower()
|
|
94
|
+
if kind in ("cli", "binary"):
|
|
95
|
+
return ("present", command or "") if _command_available(repo_root, command) \
|
|
96
|
+
else ("missing", command or "")
|
|
97
|
+
if kind in ("mcp", "skill"):
|
|
98
|
+
t = (scan_target or "").strip()
|
|
99
|
+
if not t:
|
|
100
|
+
return "unknown", "no scan target; agent confirms availability"
|
|
101
|
+
return ("present", t) if _target_resolves(repo_root, t) else ("missing", t)
|
|
102
|
+
if kind == "http":
|
|
103
|
+
t = (scan_target or "").strip()
|
|
104
|
+
if not t:
|
|
105
|
+
return "unknown", "no scan target"
|
|
106
|
+
if _http_reachable(t) or _target_resolves(repo_root, t):
|
|
107
|
+
return "present", t
|
|
108
|
+
return "missing", t
|
|
109
|
+
return "unknown", ""
|