@techierathore/techieflow 1.0.1 → 1.0.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.
- package/.claude/commands/TechieFlow/agents/analyst.md +0 -5
- package/.claude/commands/TechieFlow/agents/architect.md +0 -6
- package/.claude/commands/TechieFlow/agents/flow-master.md +41 -215
- package/.claude/commands/TechieFlow/agents/verifier.md +23 -64
- package/.claude/commands/TechieFlow/tasks/_metrics-emit-gate.md +24 -117
- package/.claude/commands/TechieFlow/tasks/_smoke-test-policy.md +20 -84
- package/.claude/commands/TechieFlow/tasks/_status-update-gate.md +10 -74
- package/.claude/commands/TechieFlow/tasks/_yolo-mode.md +20 -58
- package/.claude/commands/TechieFlow/tasks/amend-docs.md +20 -143
- package/.claude/commands/TechieFlow/tasks/build-phase.md +14 -224
- package/.claude/commands/TechieFlow/tasks/day1-brownfield.md +31 -505
- package/.claude/commands/TechieFlow/tasks/day1-greenfield.md +28 -213
- package/.claude/commands/TechieFlow/tasks/deploy-checklist.md +19 -0
- package/.claude/commands/TechieFlow/tasks/devguide.md +10 -219
- package/.claude/commands/TechieFlow/tasks/fix-issues.md +10 -129
- package/.claude/commands/TechieFlow/tasks/log-miss.md +19 -158
- package/.claude/commands/TechieFlow/tasks/metrics-report.md +1 -1
- package/.claude/commands/TechieFlow/tasks/mockups.md +12 -117
- package/.claude/commands/TechieFlow/tasks/refresh-status.md +9 -130
- package/.claude/commands/TechieFlow/tasks/split-brd.md +10 -126
- package/.claude/commands/TechieFlow/tasks/triage-and-fix.md +14 -0
- package/.claude/commands/TechieFlow/tasks/triage-issues.md +11 -152
- package/.claude/commands/TechieFlow/tasks/verify-phase.md +36 -572
- package/.opencode/plugin/techieflow.js +39 -12
- package/.tfcore/agents/analyst.md +0 -5
- package/.tfcore/agents/architect.md +0 -6
- package/.tfcore/agents/flow-master.md +41 -215
- package/.tfcore/agents/verifier.md +23 -64
- package/.tfcore/core-config.yaml +10 -0
- package/.tfcore/hooks/block-git.sh +4 -4
- package/.tfcore/hooks/guard-artifacts.sh +2 -2
- package/.tfcore/hooks/guard-build.sh +76 -0
- package/.tfcore/hooks/guard-db.sh +90 -0
- package/.tfcore/hooks/guard-metrics.sh +56 -0
- package/.tfcore/hooks/guard-status-html.sh +116 -71
- package/.tfcore/hooks/guard-status.sh +43 -16
- package/.tfcore/hooks/guard-verify.sh +70 -48
- package/.tfcore/hooks/sweep-artifacts.sh +2 -2
- package/.tfcore/install-manifest.yaml +0 -18
- package/.tfcore/routing.yaml +25 -14
- package/.tfcore/standards/coding-standards-core.md +61 -0
- package/.tfcore/standards/coding-standards-dotnet.md +93 -0
- package/.tfcore/tasks/_metrics-emit-gate.md +24 -117
- package/.tfcore/tasks/_smoke-test-policy.md +20 -84
- package/.tfcore/tasks/_status-update-gate.md +10 -74
- package/.tfcore/tasks/_yolo-mode.md +20 -58
- package/.tfcore/tasks/amend-docs.md +20 -143
- package/.tfcore/tasks/build-phase.md +14 -224
- package/.tfcore/tasks/day1-brownfield.md +31 -505
- package/.tfcore/tasks/day1-greenfield.md +28 -213
- package/.tfcore/tasks/deploy-checklist.md +19 -0
- package/.tfcore/tasks/devguide.md +10 -219
- package/.tfcore/tasks/fix-issues.md +10 -129
- package/.tfcore/tasks/log-miss.md +19 -158
- package/.tfcore/tasks/metrics-report.md +1 -1
- package/.tfcore/tasks/mockups.md +12 -117
- package/.tfcore/tasks/refresh-status.md +9 -130
- package/.tfcore/tasks/split-brd.md +10 -126
- package/.tfcore/tasks/triage-and-fix.md +14 -0
- package/.tfcore/tasks/triage-issues.md +11 -152
- package/.tfcore/tasks/verify-phase.md +36 -572
- package/.tfcore/telemetry/SCHEMA.md +43 -7
- package/.tfcore/telemetry/tf-metrics.sh +152 -17
- package/.tfcore/templates/project-brief-tmpl.yaml +1 -1
- package/.tfcore/templates/stack-defaults/dotnet.md +35 -0
- package/.tfcore/templates/stack-questions.md +77 -0
- package/.tfcore/templates/v4custom/app-agents-md-tmpl.md +3 -4
- package/.tfcore/templates/v4custom/app-architecture-tmpl.md +107 -115
- package/.tfcore/templates/v4custom/app-brd-tmpl.md +108 -184
- package/.tfcore/templates/v4custom/app-checklist-tmpl.md +48 -73
- package/.tfcore/templates/v4custom/app-claude-md-tmpl.md +1 -1
- package/.tfcore/templates/v4custom/app-coding-standards-tmpl.md +52 -0
- package/.tfcore/templates/v4custom/app-deployment-checklist-tmpl.md +86 -0
- package/.tfcore/templates/v4custom/app-devguide-tmpl.md +69 -146
- package/.tfcore/templates/v4custom/app-phases-tmpl.md +35 -0
- package/.tfcore/templates/v4custom/app-productguide-tmpl.md +38 -35
- package/.tfcore/templates/v4custom/app-project-status-tmpl.md +63 -73
- package/.tfcore/templates/v4custom/app-uidesign-tmpl.md +62 -37
- package/.tfcore/templates/v4custom/app-usageguide-tmpl.md +69 -54
- package/.tfcore/templates/v4custom/build-invocation-ladder.md +17 -180
- package/.tfcore/templates/v4custom/build-subagent-prompt.md +17 -0
- package/.tfcore/templates/v4custom/metrics-report-template.md +2 -2
- package/.tfcore/user-guide.md +0 -23
- package/.tfcore/utils/__pycache__/tf-brd-status.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-checklist-edit.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-codex-bind.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-codex-telemetry.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-day1-files.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-devguide-list.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-doc-check.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-log-miss.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-misses-md.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-mockups-locate.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-opencode-audit.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-perf-grade.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-render-html.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-split-brd.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-status-facts.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-triage.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-verify-list.cpython-312.pyc +0 -0
- package/.tfcore/utils/__pycache__/tf-verify-verdict.cpython-312.pyc +0 -0
- package/.tfcore/utils/tf-brd-status.py +176 -0
- package/.tfcore/utils/tf-brd-status.sh +19 -0
- package/.tfcore/utils/tf-build-list.py +191 -0
- package/.tfcore/utils/tf-build-list.sh +20 -0
- package/.tfcore/utils/tf-build.sh +143 -0
- package/.tfcore/utils/tf-cdp-relay.ps1 +64 -0
- package/.tfcore/utils/tf-checklist-edit.py +133 -0
- package/.tfcore/utils/tf-day1-files.py +208 -0
- package/.tfcore/utils/tf-day1-files.sh +20 -0
- package/.tfcore/utils/tf-devguide-list.py +249 -0
- package/.tfcore/utils/tf-devguide-list.sh +18 -0
- package/.tfcore/utils/tf-doc-check.py +1267 -0
- package/.tfcore/utils/tf-doc-check.sh +29 -0
- package/.tfcore/utils/tf-emit.sh +203 -13
- package/.tfcore/utils/tf-fix-close.sh +83 -0
- package/.tfcore/utils/tf-goal.sh +193 -62
- package/.tfcore/utils/tf-harness.sh +4 -9
- package/.tfcore/utils/tf-log-miss.py +197 -0
- package/.tfcore/utils/tf-log-miss.sh +14 -0
- package/.tfcore/utils/tf-misses-md.py +211 -0
- package/.tfcore/utils/tf-misses-md.sh +13 -0
- package/.tfcore/utils/tf-mockups-locate.py +66 -0
- package/.tfcore/utils/tf-mockups-locate.sh +18 -0
- package/.tfcore/utils/tf-opencode-audit.py +23 -7
- package/.tfcore/utils/tf-perf-grade.py +97 -0
- package/.tfcore/utils/tf-perf-grade.sh +12 -0
- package/.tfcore/utils/tf-phase.sh +74 -0
- package/.tfcore/utils/tf-routing-bind.sh +10 -5
- package/.tfcore/utils/tf-routing.sh +6 -7
- package/.tfcore/utils/tf-split-brd.py +304 -0
- package/.tfcore/utils/tf-split-brd.sh +22 -0
- package/.tfcore/utils/tf-status-evidence.sh +68 -0
- package/.tfcore/utils/tf-status-facts.py +309 -0
- package/.tfcore/utils/tf-status-facts.sh +20 -0
- package/.tfcore/utils/tf-triage.py +243 -0
- package/.tfcore/utils/tf-triage.sh +16 -0
- package/.tfcore/utils/tf-verify-boot.sh +250 -0
- package/.tfcore/utils/tf-verify-emit.sh +110 -0
- package/.tfcore/utils/tf-verify-env.sh +88 -0
- package/.tfcore/utils/tf-verify-list.py +270 -0
- package/.tfcore/utils/tf-verify-list.sh +13 -0
- package/.tfcore/utils/tf-verify-screens.mjs +283 -0
- package/.tfcore/utils/tf-verify-screens.sh +22 -0
- package/.tfcore/utils/tf-verify-tests.sh +123 -0
- package/.tfcore/utils/tf-verify-verdict.py +283 -0
- package/.tfcore/utils/tf-verify-verdict.sh +15 -0
- package/.tfcore/utils/tf-yolo.sh +59 -0
- package/README.md +114 -1149
- package/docs/TechieFlow-Installation.md +27 -7
- package/opencode.jsonc +13 -33
- package/package.json +4 -7
- package/scripts/install.mjs +73 -46
- package/scripts/npm-cleanup.mjs +137 -0
- package/scripts/npm-postinstall.mjs +49 -0
- package/.claude/commands/TechieFlow/tasks/advanced-elicitation.md +0 -117
- package/.claude/commands/TechieFlow/tasks/author-brd.md +0 -79
- package/.claude/commands/TechieFlow/tasks/document-project.md +0 -343
- package/.claude/commands/TechieFlow/tasks/execute-checklist.md +0 -86
- package/.claude/commands/TechieFlow/tasks/index-docs.md +0 -173
- package/.claude/commands/TechieFlow/tasks/kb-mode-interaction.md +0 -75
- package/.claude/commands/TechieFlow/tasks/shard-doc.md +0 -185
- package/.codex/config.toml +0 -46
- package/.codex/hooks.json +0 -63
- package/.codex/rules/techieflow.rules +0 -8
- package/.tfcore/hooks/codex-adapter.py +0 -248
- package/.tfcore/tasks/advanced-elicitation.md +0 -117
- package/.tfcore/tasks/author-brd.md +0 -79
- package/.tfcore/tasks/document-project.md +0 -343
- package/.tfcore/tasks/execute-checklist.md +0 -86
- package/.tfcore/tasks/index-docs.md +0 -173
- package/.tfcore/tasks/kb-mode-interaction.md +0 -75
- package/.tfcore/tasks/shard-doc.md +0 -185
- package/.tfcore/utils/tf-codex-bind.py +0 -196
- package/.tfcore/utils/tf-codex-telemetry.py +0 -60
- package/WORKFLOW.html +0 -1986
- package/scripts/test-install.mjs +0 -505
- package/scripts/validate.mjs +0 -163
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Translate Codex hooks to TechieFlow's existing guard and telemetry contracts.
|
|
3
|
-
|
|
4
|
-
Modes (see .codex/hooks.json):
|
|
5
|
-
pre-tool Bash -> block-git.sh + guard-artifacts.sh
|
|
6
|
-
Edit/Write/apply_patch -> guard-status.sh + guard-verify.sh
|
|
7
|
-
stop guard-status-html.sh (PROJECT-STATUS.html must not be stale)
|
|
8
|
-
session-start session pointer + sweep-artifacts.sh (expired run material)
|
|
9
|
-
session-start write the .tfcore/.session/codex.json pointer
|
|
10
|
-
session-end pointer + session telemetry
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
import json
|
|
16
|
-
import os
|
|
17
|
-
import pathlib
|
|
18
|
-
import re
|
|
19
|
-
import subprocess
|
|
20
|
-
import sys
|
|
21
|
-
from datetime import datetime, timezone
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def read_event() -> dict:
|
|
25
|
-
try:
|
|
26
|
-
value = json.load(sys.stdin)
|
|
27
|
-
return value if isinstance(value, dict) else {}
|
|
28
|
-
except Exception:
|
|
29
|
-
return {}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def project_root(event: dict) -> pathlib.Path:
|
|
33
|
-
start = pathlib.Path(str(event.get("cwd") or os.getcwd())).resolve()
|
|
34
|
-
for candidate in (start, *start.parents):
|
|
35
|
-
if (candidate / ".tfcore").is_dir():
|
|
36
|
-
return candidate
|
|
37
|
-
return start
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def environment(root: pathlib.Path, event: dict) -> dict[str, str]:
|
|
41
|
-
env = os.environ.copy()
|
|
42
|
-
env.update(
|
|
43
|
-
TF_HARNESS="codex",
|
|
44
|
-
TF_PROJECT_DIR=str(root),
|
|
45
|
-
CLAUDE_PROJECT_DIR=str(root),
|
|
46
|
-
TF_SESSION_ID=str(event.get("session_id") or ""),
|
|
47
|
-
)
|
|
48
|
-
if (root / ".tfcore" / ".session" / "yolo.json").exists():
|
|
49
|
-
env["TF_YOLO"] = "1"
|
|
50
|
-
return env
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def deny(reason: str) -> None:
|
|
54
|
-
print(json.dumps({
|
|
55
|
-
"hookSpecificOutput": {
|
|
56
|
-
"hookEventName": "PreToolUse",
|
|
57
|
-
"permissionDecision": "deny",
|
|
58
|
-
"permissionDecisionReason": reason,
|
|
59
|
-
}
|
|
60
|
-
}))
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def run_guard(root: pathlib.Path, event: dict, script: str, payload: dict) -> str | None:
|
|
64
|
-
path = root / ".tfcore" / "hooks" / script
|
|
65
|
-
if not path.exists():
|
|
66
|
-
return None
|
|
67
|
-
try:
|
|
68
|
-
env = environment(root, event)
|
|
69
|
-
if script == "block-git.sh":
|
|
70
|
-
# Codex also has an all-git exec-policy rule. Keep the hook's
|
|
71
|
-
# compound-command fallback equally strict in YOLO mode.
|
|
72
|
-
env["TF_STRICT_GIT"] = "1"
|
|
73
|
-
result = subprocess.run(
|
|
74
|
-
["bash", str(path)], input=json.dumps(payload), text=True,
|
|
75
|
-
capture_output=True, timeout=10, env=env, check=False,
|
|
76
|
-
)
|
|
77
|
-
except Exception as exc:
|
|
78
|
-
# Policy checks fail closed. Telemetry is handled separately and fails open.
|
|
79
|
-
return f"TechieFlow could not execute {script}: {exc}"
|
|
80
|
-
if result.returncode == 2:
|
|
81
|
-
return result.stderr.strip() or f"Blocked by TechieFlow guard {script}"
|
|
82
|
-
if result.returncode not in (0,):
|
|
83
|
-
return f"TechieFlow guard {script} failed unexpectedly (exit {result.returncode})."
|
|
84
|
-
return None
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def pre_tool(event: dict) -> None:
|
|
88
|
-
root = project_root(event)
|
|
89
|
-
tool = str(event.get("tool_name") or "")
|
|
90
|
-
raw = event.get("tool_input")
|
|
91
|
-
args = raw if isinstance(raw, dict) else {}
|
|
92
|
-
scripts: list[str] = []
|
|
93
|
-
if tool == "Bash":
|
|
94
|
-
payload = {"tool_name": "Bash", "tool_input": {"command": str(args.get("command") or "")}}
|
|
95
|
-
scripts = ["block-git.sh", "guard-artifacts.sh"]
|
|
96
|
-
elif tool == "apply_patch":
|
|
97
|
-
patch = str(args.get("command") or args.get("patch") or "")
|
|
98
|
-
# Run the existing guards once per file using actual paths and separated
|
|
99
|
-
# added/removed lines. This avoids treating context or removed Verified
|
|
100
|
-
# cells as newly introduced content.
|
|
101
|
-
headers = list(re.finditer(r"(?m)^\*\*\* (Update|Add|Delete) File: (.+)$", patch))
|
|
102
|
-
for index, header in enumerate(headers):
|
|
103
|
-
end = headers[index + 1].start() if index + 1 < len(headers) else len(patch)
|
|
104
|
-
section = patch[header.end():end]
|
|
105
|
-
file_path = header.group(2).strip()
|
|
106
|
-
base_name = pathlib.PurePosixPath(file_path.replace("\\", "/")).name.lower()
|
|
107
|
-
if header.group(1) == "Delete" and (
|
|
108
|
-
base_name == "project-status.md" or base_name.endswith("-checklist.md")
|
|
109
|
-
):
|
|
110
|
-
deny(
|
|
111
|
-
"TechieFlow protected documents cannot be deleted: "
|
|
112
|
-
f"{file_path}. Update their canonical fixed shape instead."
|
|
113
|
-
)
|
|
114
|
-
return
|
|
115
|
-
added = []
|
|
116
|
-
removed = []
|
|
117
|
-
for line in section.splitlines():
|
|
118
|
-
if line.startswith("+") and not line.startswith("+++"):
|
|
119
|
-
added.append(line[1:])
|
|
120
|
-
elif line.startswith("-") and not line.startswith("---"):
|
|
121
|
-
removed.append(line[1:])
|
|
122
|
-
payload = {
|
|
123
|
-
"hook_event_name": "PreToolUse", "cwd": str(root),
|
|
124
|
-
"session_id": event.get("session_id"), "tool_name": "Edit",
|
|
125
|
-
"tool_input": {"file_path": file_path,
|
|
126
|
-
"old_string": "\n".join(removed),
|
|
127
|
-
"new_string": "\n".join(added)},
|
|
128
|
-
}
|
|
129
|
-
for script in ("guard-status.sh", "guard-verify.sh"):
|
|
130
|
-
reason = run_guard(root, event, script, payload)
|
|
131
|
-
if reason:
|
|
132
|
-
deny(reason)
|
|
133
|
-
return
|
|
134
|
-
return
|
|
135
|
-
elif tool in ("Edit", "Write"):
|
|
136
|
-
payload = {"tool_name": tool, "tool_input": args}
|
|
137
|
-
scripts = ["guard-status.sh", "guard-verify.sh"]
|
|
138
|
-
else:
|
|
139
|
-
return
|
|
140
|
-
payload.update(hook_event_name="PreToolUse", cwd=str(root), session_id=event.get("session_id"))
|
|
141
|
-
for script in scripts:
|
|
142
|
-
reason = run_guard(root, event, script, payload)
|
|
143
|
-
if reason:
|
|
144
|
-
deny(reason)
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def stop(event: dict) -> None:
|
|
149
|
-
"""Stop hook: refuse to end the turn while PROJECT-STATUS.html is stale.
|
|
150
|
-
|
|
151
|
-
Same contract as the Claude Code Stop hook (_status-update-gate.md §8):
|
|
152
|
-
guard-status-html.sh exits 2 when the .html is older than the .md or
|
|
153
|
-
missing; `stop_hook_active` is passed through so a turn that genuinely
|
|
154
|
-
cannot render still terminates instead of looping.
|
|
155
|
-
"""
|
|
156
|
-
root = project_root(event)
|
|
157
|
-
payload = {
|
|
158
|
-
"hook_event_name": "Stop", "cwd": str(root),
|
|
159
|
-
"session_id": event.get("session_id"),
|
|
160
|
-
"stop_hook_active": bool(event.get("stop_hook_active")),
|
|
161
|
-
}
|
|
162
|
-
reason = run_guard(root, event, "guard-status-html.sh", payload)
|
|
163
|
-
if reason:
|
|
164
|
-
print(json.dumps({"decision": "block", "reason": reason}))
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def write_pointer(root: pathlib.Path, event: dict) -> None:
|
|
168
|
-
session_id = str(event.get("session_id") or "")
|
|
169
|
-
if not session_id:
|
|
170
|
-
return
|
|
171
|
-
target = root / ".tfcore" / ".session" / "codex.json"
|
|
172
|
-
try:
|
|
173
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
174
|
-
target.write_text(json.dumps({
|
|
175
|
-
"session_id": session_id,
|
|
176
|
-
"transcript_path": event.get("transcript_path"),
|
|
177
|
-
"model": event.get("model"),
|
|
178
|
-
"ts": datetime.now(timezone.utc).isoformat(),
|
|
179
|
-
}) + "\n", encoding="utf-8")
|
|
180
|
-
except Exception:
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def sweep_artifacts(root: pathlib.Path, event: dict) -> None:
|
|
185
|
-
"""SessionStart analogue of the Claude Code sweep-artifacts.sh hook: delete
|
|
186
|
-
run material under tests/.artifacts/ and .verify/ older than the retention
|
|
187
|
-
window and any banned repo-root legacy dir. No veto — never raises."""
|
|
188
|
-
script = root / ".tfcore" / "hooks" / "sweep-artifacts.sh"
|
|
189
|
-
if not script.exists():
|
|
190
|
-
return
|
|
191
|
-
try:
|
|
192
|
-
res = subprocess.run(["bash", str(script)], input=json.dumps(event), text=True,
|
|
193
|
-
capture_output=True, timeout=30, env=environment(root, event), check=False)
|
|
194
|
-
summary = (res.stdout or "").strip()
|
|
195
|
-
if summary:
|
|
196
|
-
print(summary) # SessionStart stdout is surfaced into the session
|
|
197
|
-
except Exception:
|
|
198
|
-
pass
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def session_end(root: pathlib.Path, event: dict) -> None:
|
|
202
|
-
# Transcript format is explicitly not a stable Codex hook interface. Record
|
|
203
|
-
# honest session metadata; codex exec --json telemetry is enriched separately.
|
|
204
|
-
emit = root / ".tfcore" / "utils" / "tf-emit.sh"
|
|
205
|
-
if not emit.exists() or not event.get("session_id"):
|
|
206
|
-
return
|
|
207
|
-
record = {
|
|
208
|
-
"kind": "session",
|
|
209
|
-
"session_id": event.get("session_id"),
|
|
210
|
-
"model": event.get("model"),
|
|
211
|
-
"duration_s": None,
|
|
212
|
-
"input_tokens": None,
|
|
213
|
-
"output_tokens": None,
|
|
214
|
-
"cache_read_tokens": None,
|
|
215
|
-
"cache_creation_tokens": None,
|
|
216
|
-
"cost_usd": None,
|
|
217
|
-
"children_sessions": None,
|
|
218
|
-
"harness": "codex",
|
|
219
|
-
}
|
|
220
|
-
try:
|
|
221
|
-
subprocess.run(["bash", str(emit), "sessions"], input=json.dumps(record), text=True,
|
|
222
|
-
capture_output=True, timeout=2, env=environment(root, event), check=False)
|
|
223
|
-
except Exception:
|
|
224
|
-
pass
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def main() -> int:
|
|
228
|
-
event = read_event()
|
|
229
|
-
root = project_root(event)
|
|
230
|
-
mode = sys.argv[1] if len(sys.argv) > 1 else ""
|
|
231
|
-
if mode == "pre-tool":
|
|
232
|
-
pre_tool(event)
|
|
233
|
-
elif mode == "stop":
|
|
234
|
-
stop(event)
|
|
235
|
-
elif mode == "session-start":
|
|
236
|
-
write_pointer(root, event)
|
|
237
|
-
# .codex/hooks.json runs session-start for UserPromptSubmit too; sweep
|
|
238
|
-
# only on the real session start so every prompt does not walk the tree.
|
|
239
|
-
if str(event.get("hook_event_name") or "").lower() != "userpromptsubmit":
|
|
240
|
-
sweep_artifacts(root, event)
|
|
241
|
-
elif mode == "session-end":
|
|
242
|
-
write_pointer(root, event)
|
|
243
|
-
session_end(root, event)
|
|
244
|
-
return 0
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if __name__ == "__main__":
|
|
248
|
-
raise SystemExit(main())
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# Advanced Elicitation Task
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
- Provide optional reflective and brainstorming actions to enhance content quality
|
|
6
|
-
- Enable deeper exploration of ideas through structured elicitation techniques
|
|
7
|
-
- Support iterative refinement through multiple analytical perspectives
|
|
8
|
-
- Usable during template-driven document creation or any chat conversation
|
|
9
|
-
|
|
10
|
-
## Usage Scenarios
|
|
11
|
-
|
|
12
|
-
### Scenario 1: Template Document Creation
|
|
13
|
-
|
|
14
|
-
After outputting a section during document creation:
|
|
15
|
-
|
|
16
|
-
1. **Section Review**: Ask user to review the drafted section
|
|
17
|
-
2. **Offer Elicitation**: Present 9 carefully selected elicitation methods
|
|
18
|
-
3. **Simple Selection**: User types a number (0-8) to engage method, or 9 to proceed
|
|
19
|
-
4. **Execute & Loop**: Apply selected method, then re-offer choices until user proceeds
|
|
20
|
-
|
|
21
|
-
### Scenario 2: General Chat Elicitation
|
|
22
|
-
|
|
23
|
-
User can request advanced elicitation on any agent output:
|
|
24
|
-
|
|
25
|
-
- User says "do advanced elicitation" or similar
|
|
26
|
-
- Agent selects 9 relevant methods for the context
|
|
27
|
-
- Same simple 0-9 selection process
|
|
28
|
-
|
|
29
|
-
## Task Instructions
|
|
30
|
-
|
|
31
|
-
### 1. Intelligent Method Selection
|
|
32
|
-
|
|
33
|
-
**Context Analysis**: Before presenting options, analyze:
|
|
34
|
-
|
|
35
|
-
- **Content Type**: Technical specs, user stories, architecture, requirements, etc.
|
|
36
|
-
- **Complexity Level**: Simple, moderate, or complex content
|
|
37
|
-
- **Stakeholder Needs**: Who will use this information
|
|
38
|
-
- **Risk Level**: High-impact decisions vs routine items
|
|
39
|
-
- **Creative Potential**: Opportunities for innovation or alternatives
|
|
40
|
-
|
|
41
|
-
**Method Selection Strategy**:
|
|
42
|
-
|
|
43
|
-
1. **Always Include Core Methods** (choose 3-4):
|
|
44
|
-
- Expand or Contract for Audience
|
|
45
|
-
- Critique and Refine
|
|
46
|
-
- Identify Potential Risks
|
|
47
|
-
- Assess Alignment with Goals
|
|
48
|
-
|
|
49
|
-
2. **Context-Specific Methods** (choose 4-5):
|
|
50
|
-
- **Technical Content**: Tree of Thoughts, ReWOO, Meta-Prompting
|
|
51
|
-
- **User-Facing Content**: Agile Team Perspective, Stakeholder Roundtable
|
|
52
|
-
- **Creative Content**: Innovation Tournament, Escape Room Challenge
|
|
53
|
-
- **Strategic Content**: Red Team vs Blue Team, Hindsight Reflection
|
|
54
|
-
|
|
55
|
-
3. **Always Include**: "Proceed / No Further Actions" as option 9
|
|
56
|
-
|
|
57
|
-
### 2. Section Context and Review
|
|
58
|
-
|
|
59
|
-
When invoked after outputting a section:
|
|
60
|
-
|
|
61
|
-
1. **Provide Context Summary**: Give a brief 1-2 sentence summary of what the user should look for in the section just presented
|
|
62
|
-
|
|
63
|
-
2. **Explain Visual Elements**: If the section contains diagrams, explain them briefly before offering elicitation options
|
|
64
|
-
|
|
65
|
-
3. **Clarify Scope Options**: If the section contains multiple distinct items, inform the user they can apply elicitation actions to:
|
|
66
|
-
- The entire section as a whole
|
|
67
|
-
- Individual items within the section (specify which item when selecting an action)
|
|
68
|
-
|
|
69
|
-
### 3. Present Elicitation Options
|
|
70
|
-
|
|
71
|
-
**Review Request Process:**
|
|
72
|
-
|
|
73
|
-
- Ask the user to review the drafted section
|
|
74
|
-
- In the SAME message, inform them they can suggest direct changes OR select an elicitation method
|
|
75
|
-
- Present 9 intelligently selected methods (0-8) plus "Proceed" (9)
|
|
76
|
-
- Keep descriptions short - just the method name
|
|
77
|
-
- Await simple numeric selection
|
|
78
|
-
|
|
79
|
-
**Action List Presentation Format:**
|
|
80
|
-
|
|
81
|
-
```text
|
|
82
|
-
**Advanced Elicitation Options**
|
|
83
|
-
Choose a number (0-8) or 9 to proceed:
|
|
84
|
-
|
|
85
|
-
0. [Method Name]
|
|
86
|
-
1. [Method Name]
|
|
87
|
-
2. [Method Name]
|
|
88
|
-
3. [Method Name]
|
|
89
|
-
4. [Method Name]
|
|
90
|
-
5. [Method Name]
|
|
91
|
-
6. [Method Name]
|
|
92
|
-
7. [Method Name]
|
|
93
|
-
8. [Method Name]
|
|
94
|
-
9. Proceed / No Further Actions
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Response Handling:**
|
|
98
|
-
|
|
99
|
-
- **Numbers 0-8**: Execute the selected method, then re-offer the choice
|
|
100
|
-
- **Number 9**: Proceed to next section or continue conversation
|
|
101
|
-
- **Direct Feedback**: Apply user's suggested changes and continue
|
|
102
|
-
|
|
103
|
-
### 4. Method Execution Framework
|
|
104
|
-
|
|
105
|
-
**Execution Process:**
|
|
106
|
-
|
|
107
|
-
1. **Retrieve Method**: Access the specific elicitation method from the elicitation-methods data file
|
|
108
|
-
2. **Apply Context**: Execute the method from your current role's perspective
|
|
109
|
-
3. **Provide Results**: Deliver insights, critiques, or alternatives relevant to the content
|
|
110
|
-
4. **Re-offer Choice**: Present the same 9 options again until user selects 9 or gives direct feedback
|
|
111
|
-
|
|
112
|
-
**Execution Guidelines:**
|
|
113
|
-
|
|
114
|
-
- **Be Concise**: Focus on actionable insights, not lengthy explanations
|
|
115
|
-
- **Stay Relevant**: Tie all elicitation back to the specific content being analyzed
|
|
116
|
-
- **Identify Personas**: For multi-persona methods, clearly identify which viewpoint is speaking
|
|
117
|
-
- **Maintain Flow**: Keep the process moving efficiently
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# author-brd
|
|
2
|
-
|
|
3
|
-
Author or extend a Business Requirements Document (BRD) with stable BRD-N requirement IDs, using interactive elicitation. The analyst NEVER assumes a requirement — each candidate is confirmed by the user before it lands in the BRD.
|
|
4
|
-
|
|
5
|
-
> **When to use:** this is the INTERACTIVE alternative for extending an existing BRD requirement-by-requirement. For creating a project's BRD, the default path is `*day1-brownfield` / `*day1-greenfield` (bulk draft, no per-item confirmation).
|
|
6
|
-
|
|
7
|
-
## Purpose
|
|
8
|
-
|
|
9
|
-
Produce a BRD where every business/functional requirement has a unique, stable, append-only ID (`BRD-1`, `BRD-2`, …) that downstream agents (UI agent, orchestrator, verifier) can declare and verify against. Eliminate the "implicit requirement" problem by forcing per-item user confirmation.
|
|
10
|
-
|
|
11
|
-
## elicit
|
|
12
|
-
|
|
13
|
-
elicit=true — this task REQUIRES user interaction. Never skip elicitation for efficiency.
|
|
14
|
-
|
|
15
|
-
## Inputs
|
|
16
|
-
|
|
17
|
-
- `{AppName}` argument (required for the canonical filename; ask once if missing).
|
|
18
|
-
- `{topic}` argument (optional) — the product/feature area. If absent, ask once: "What's the topic / product area for this BRD?"
|
|
19
|
-
- Existing BRD path. Resolve in this order: `core-config.yaml → customTechnicalDocuments`, then `docs/{AppName}-BRD.md` (legacy fallbacks: `docs/brd.md`, `docs/BRD.md`). If found, OPEN it and continue from the highest existing BRD-N. If not found, create `docs/{AppName}-BRD.md` from `.tfcore/templates/v4custom/app-brd-tmpl.md` (feature catalog + §10 BRD-N ledger shape — NOT ad-hoc "Phase N" sections).
|
|
20
|
-
|
|
21
|
-
## SEQUENTIAL Execution
|
|
22
|
-
|
|
23
|
-
### 1. Read or scaffold the BRD
|
|
24
|
-
|
|
25
|
-
- If the resolved BRD exists: read it, parse all existing `BRD-{N}` IDs, and record the highest N. New requirements continue from N+1.
|
|
26
|
-
- If absent: scaffold `docs/{AppName}-BRD.md` from `.tfcore/templates/v4custom/app-brd-tmpl.md` (leave unconfirmed sections empty; confirmed requirements land in the §10 ledger).
|
|
27
|
-
- Ask the user which areas they want to scope today.
|
|
28
|
-
|
|
29
|
-
### 2. Drive elicitation per area, one at a time
|
|
30
|
-
|
|
31
|
-
For each area the user wants to cover (UI, data, workflow, NFRs, etc.):
|
|
32
|
-
|
|
33
|
-
1. Generate a numbered list of CANDIDATE requirements for that area — 3 to 7 items, written as one-line "user can X" / "system shall Y" statements. Do NOT assign BRD-N IDs yet.
|
|
34
|
-
2. Present the list and ask the user to (a) accept, (b) reject, (c) refine, or (d) add their own — one item at a time. Use this exact prompt format:
|
|
35
|
-
```
|
|
36
|
-
Candidate requirements for {area}:
|
|
37
|
-
1. {candidate}
|
|
38
|
-
2. {candidate}
|
|
39
|
-
...
|
|
40
|
-
For each, reply: keep / drop / refine: <new text>. Or add a new one with: add: <text>.
|
|
41
|
-
```
|
|
42
|
-
3. After the user processes each item, assign the next BRD-N to every KEPT or REFINED item, in the order they were confirmed. Show the assignments back:
|
|
43
|
-
```
|
|
44
|
-
Assigned:
|
|
45
|
-
- BRD-{N}: {final text}
|
|
46
|
-
- BRD-{N+1}: {final text}
|
|
47
|
-
```
|
|
48
|
-
4. Append the assigned requirements to the §10 Functional-requirements ledger of the resolved BRD file (and flesh out / create the owning feature-catalog entry).
|
|
49
|
-
|
|
50
|
-
Repeat for each area until the user says they're done with this BRD pass.
|
|
51
|
-
|
|
52
|
-
### 3. NFRs and acceptance criteria (optional pass)
|
|
53
|
-
|
|
54
|
-
If the user wants NFRs (performance, accessibility, browser support, etc.) or acceptance criteria for any BRD-N, run the same elicitation pattern. NFRs get their own BRD-N IDs (do NOT use a separate `NFR-N` series — keep one ID space so the verifier can grade everything uniformly).
|
|
55
|
-
|
|
56
|
-
### 4. Final output
|
|
57
|
-
|
|
58
|
-
Append/refresh the footer block of the BRD:
|
|
59
|
-
```
|
|
60
|
-
---
|
|
61
|
-
Last updated: {YYYY-MM-DD}
|
|
62
|
-
Highest BRD ID: BRD-{N}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Print a compact summary to the user:
|
|
66
|
-
```
|
|
67
|
-
BRD updated → docs/{AppName}-BRD.md
|
|
68
|
-
Added: BRD-{a}..BRD-{b} ({count} requirements)
|
|
69
|
-
Phases touched: {list}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
HALT.
|
|
73
|
-
|
|
74
|
-
## Hard rules
|
|
75
|
-
|
|
76
|
-
- elicit=true — never batch-confirm; one item at a time.
|
|
77
|
-
- BRD-N IDs are append-only — never renumber an existing ID even if the user removes a requirement later (mark it `~~BRD-N~~ (removed)` instead).
|
|
78
|
-
- Requirements are written as observable outcomes, not implementation hints. The verifier needs to be able to test them.
|
|
79
|
-
- The analyst writes the BRD; the analyst does NOT implement anything.
|