@techierathore/techieflow 1.0.0
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 +97 -0
- package/.claude/commands/TechieFlow/agents/architect.md +84 -0
- package/.claude/commands/TechieFlow/agents/flow-master.md +217 -0
- package/.claude/commands/TechieFlow/agents/verifier.md +72 -0
- package/.claude/commands/TechieFlow/tasks/_metrics-emit-gate.md +138 -0
- package/.claude/commands/TechieFlow/tasks/_smoke-test-policy.md +98 -0
- package/.claude/commands/TechieFlow/tasks/_status-update-gate.md +78 -0
- package/.claude/commands/TechieFlow/tasks/_yolo-mode.md +77 -0
- package/.claude/commands/TechieFlow/tasks/advanced-elicitation.md +117 -0
- package/.claude/commands/TechieFlow/tasks/amend-docs.md +149 -0
- package/.claude/commands/TechieFlow/tasks/author-brd.md +79 -0
- package/.claude/commands/TechieFlow/tasks/build-phase.md +231 -0
- package/.claude/commands/TechieFlow/tasks/create-deep-research-prompt.md +278 -0
- package/.claude/commands/TechieFlow/tasks/create-doc.md +101 -0
- package/.claude/commands/TechieFlow/tasks/day1-brownfield.md +507 -0
- package/.claude/commands/TechieFlow/tasks/day1-greenfield.md +224 -0
- package/.claude/commands/TechieFlow/tasks/devguide.md +224 -0
- package/.claude/commands/TechieFlow/tasks/document-project.md +343 -0
- package/.claude/commands/TechieFlow/tasks/execute-checklist.md +86 -0
- package/.claude/commands/TechieFlow/tasks/facilitate-brainstorming-session.md +136 -0
- package/.claude/commands/TechieFlow/tasks/fix-issues.md +134 -0
- package/.claude/commands/TechieFlow/tasks/generate-html.md +115 -0
- package/.claude/commands/TechieFlow/tasks/handoff-phase.md +126 -0
- package/.claude/commands/TechieFlow/tasks/index-docs.md +173 -0
- package/.claude/commands/TechieFlow/tasks/kb-mode-interaction.md +75 -0
- package/.claude/commands/TechieFlow/tasks/log-miss.md +160 -0
- package/.claude/commands/TechieFlow/tasks/metrics-report.md +143 -0
- package/.claude/commands/TechieFlow/tasks/mockups.md +122 -0
- package/.claude/commands/TechieFlow/tasks/productguide.md +105 -0
- package/.claude/commands/TechieFlow/tasks/refresh-status.md +135 -0
- package/.claude/commands/TechieFlow/tasks/render-workflow-docs.md +117 -0
- package/.claude/commands/TechieFlow/tasks/shard-doc.md +185 -0
- package/.claude/commands/TechieFlow/tasks/split-brd.md +131 -0
- package/.claude/commands/TechieFlow/tasks/triage-issues.md +157 -0
- package/.claude/commands/TechieFlow/tasks/verify-phase.md +579 -0
- package/.claude/commands/generate-html.md +124 -0
- package/.codex/config.toml +46 -0
- package/.codex/hooks.json +63 -0
- package/.codex/rules/techieflow.rules +8 -0
- package/.opencode/command/generate-html.md +129 -0
- package/.opencode/plugin/techieflow.js +350 -0
- package/.tfcore/TOKEN-GUIDE.md +59 -0
- package/.tfcore/agents/analyst.md +97 -0
- package/.tfcore/agents/architect.md +84 -0
- package/.tfcore/agents/flow-master.md +217 -0
- package/.tfcore/agents/verifier.md +72 -0
- package/.tfcore/checklists/architect-checklist.md +438 -0
- package/.tfcore/core-config.yaml +47 -0
- package/.tfcore/data/brainstorming-techniques.md +36 -0
- package/.tfcore/data/elicitation-methods.md +154 -0
- package/.tfcore/data/techieflow-kb.md +807 -0
- package/.tfcore/data/technical-preferences.md +3 -0
- package/.tfcore/enhanced-ide-development-workflow.md +248 -0
- package/.tfcore/hooks/block-git.sh +301 -0
- package/.tfcore/hooks/codex-adapter.py +248 -0
- package/.tfcore/hooks/guard-artifacts.sh +101 -0
- package/.tfcore/hooks/guard-status-html.sh +102 -0
- package/.tfcore/hooks/guard-status.sh +124 -0
- package/.tfcore/hooks/guard-verify.sh +108 -0
- package/.tfcore/hooks/metrics-session.sh +129 -0
- package/.tfcore/hooks/session-pointer.sh +52 -0
- package/.tfcore/hooks/sweep-artifacts.sh +198 -0
- package/.tfcore/install-manifest.yaml +231 -0
- package/.tfcore/routing.yaml +105 -0
- package/.tfcore/tasks/_metrics-emit-gate.md +138 -0
- package/.tfcore/tasks/_smoke-test-policy.md +98 -0
- package/.tfcore/tasks/_status-update-gate.md +78 -0
- package/.tfcore/tasks/_yolo-mode.md +77 -0
- package/.tfcore/tasks/advanced-elicitation.md +117 -0
- package/.tfcore/tasks/amend-docs.md +149 -0
- package/.tfcore/tasks/author-brd.md +79 -0
- package/.tfcore/tasks/build-phase.md +231 -0
- package/.tfcore/tasks/create-deep-research-prompt.md +278 -0
- package/.tfcore/tasks/create-doc.md +101 -0
- package/.tfcore/tasks/day1-brownfield.md +507 -0
- package/.tfcore/tasks/day1-greenfield.md +224 -0
- package/.tfcore/tasks/devguide.md +224 -0
- package/.tfcore/tasks/document-project.md +343 -0
- package/.tfcore/tasks/execute-checklist.md +86 -0
- package/.tfcore/tasks/facilitate-brainstorming-session.md +136 -0
- package/.tfcore/tasks/fix-issues.md +134 -0
- package/.tfcore/tasks/generate-html.md +115 -0
- package/.tfcore/tasks/handoff-phase.md +126 -0
- package/.tfcore/tasks/index-docs.md +173 -0
- package/.tfcore/tasks/kb-mode-interaction.md +75 -0
- package/.tfcore/tasks/log-miss.md +160 -0
- package/.tfcore/tasks/metrics-report.md +143 -0
- package/.tfcore/tasks/mockups.md +122 -0
- package/.tfcore/tasks/productguide.md +105 -0
- package/.tfcore/tasks/refresh-status.md +135 -0
- package/.tfcore/tasks/render-workflow-docs.md +117 -0
- package/.tfcore/tasks/shard-doc.md +185 -0
- package/.tfcore/tasks/split-brd.md +131 -0
- package/.tfcore/tasks/triage-issues.md +157 -0
- package/.tfcore/tasks/verify-phase.md +579 -0
- package/.tfcore/telemetry/SCHEMA.md +678 -0
- package/.tfcore/telemetry/install-metrics.sh +390 -0
- package/.tfcore/telemetry/pre-commit +94 -0
- package/.tfcore/telemetry/tf-metrics.sh +1415 -0
- package/.tfcore/templates/architecture-tmpl.yaml +650 -0
- package/.tfcore/templates/brainstorming-output-tmpl.yaml +156 -0
- package/.tfcore/templates/brownfield-architecture-tmpl.yaml +476 -0
- package/.tfcore/templates/competitor-analysis-tmpl.yaml +306 -0
- package/.tfcore/templates/front-end-architecture-tmpl.yaml +218 -0
- package/.tfcore/templates/fullstack-architecture-tmpl.yaml +823 -0
- package/.tfcore/templates/market-research-tmpl.yaml +252 -0
- package/.tfcore/templates/project-brief-tmpl.yaml +221 -0
- package/.tfcore/templates/v4custom/app-agents-md-tmpl.md +61 -0
- package/.tfcore/templates/v4custom/app-architecture-tmpl.md +127 -0
- package/.tfcore/templates/v4custom/app-brd-tmpl.md +204 -0
- package/.tfcore/templates/v4custom/app-checklist-tmpl.md +90 -0
- package/.tfcore/templates/v4custom/app-claude-md-tmpl.md +33 -0
- package/.tfcore/templates/v4custom/app-devguide-tmpl.md +167 -0
- package/.tfcore/templates/v4custom/app-editorconfig-tmpl.editorconfig +44 -0
- package/.tfcore/templates/v4custom/app-library-feedback-tmpl.md +31 -0
- package/.tfcore/templates/v4custom/app-productguide-tmpl.md +54 -0
- package/.tfcore/templates/v4custom/app-project-status-tmpl.md +98 -0
- package/.tfcore/templates/v4custom/app-uidesign-tmpl.md +48 -0
- package/.tfcore/templates/v4custom/app-usageguide-tmpl.md +67 -0
- package/.tfcore/templates/v4custom/build-invocation-ladder.md +190 -0
- package/.tfcore/templates/v4custom/html-render-shell.md +502 -0
- package/.tfcore/templates/v4custom/metrics-report-template.md +273 -0
- package/.tfcore/templates/v4custom/opencode-operating-contract.md +56 -0
- package/.tfcore/user-guide.md +633 -0
- package/.tfcore/utils/techieflow-doc-template.md +325 -0
- package/.tfcore/utils/tf-assets.sh +310 -0
- package/.tfcore/utils/tf-codex-bind.py +196 -0
- package/.tfcore/utils/tf-codex-telemetry.py +60 -0
- package/.tfcore/utils/tf-emit.sh +1075 -0
- package/.tfcore/utils/tf-gitignore-audit.sh +281 -0
- package/.tfcore/utils/tf-goal.sh +421 -0
- package/.tfcore/utils/tf-harness.sh +160 -0
- package/.tfcore/utils/tf-mockup-parity.mjs +555 -0
- package/.tfcore/utils/tf-mockup-parity.sh +65 -0
- package/.tfcore/utils/tf-opencode-audit.py +126 -0
- package/.tfcore/utils/tf-perf.sh +241 -0
- package/.tfcore/utils/tf-render-html.py +715 -0
- package/.tfcore/utils/tf-render-html.sh +28 -0
- package/.tfcore/utils/tf-routing-bind.sh +216 -0
- package/.tfcore/utils/tf-routing.sh +247 -0
- package/.tfcore/utils/tf-yolo.sh +119 -0
- package/.tfcore/working-in-the-brownfield.md +606 -0
- package/LICENSE +201 -0
- package/README.md +1212 -0
- package/WORKFLOW.html +1986 -0
- package/docs/TechieFlow-Installation.md +299 -0
- package/opencode.jsonc +929 -0
- package/package.json +60 -0
- package/scripts/install.mjs +992 -0
- package/scripts/test-install.mjs +505 -0
- package/scripts/validate.mjs +155 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate TechieFlow's Codex agents and thin workflow skills."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import pathlib
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
PHASES = {
|
|
12
|
+
"day1-brownfield": ("analyst", "Reverse-document and initialize an existing application."),
|
|
13
|
+
"day1-greenfield": ("analyst", "Initialize planning artifacts and mockups for a new application."),
|
|
14
|
+
"amend-docs": ("analyst", "Amend existing requirements and design artifacts in place."),
|
|
15
|
+
"author-brd": ("analyst", "Interactively author or extend numbered business requirements."),
|
|
16
|
+
"mockups": ("analyst", "Create or update the greenfield UI design and HTML mockups."),
|
|
17
|
+
"split-brd": ("analyst", "Convert a BRD into the single implementation checklist."),
|
|
18
|
+
"build-phase": ("flow_master", "Implement the open checklist and chain smoke and verification."),
|
|
19
|
+
"verify-phase": ("verifier", "Independently verify requirements against runtime evidence."),
|
|
20
|
+
"fix-issues": ("flow_master", "Fix reported or verifier-discovered application defects."),
|
|
21
|
+
"triage-issues": ("flow_master", "Analyze and document human-found bugs without fixing source."),
|
|
22
|
+
"log-miss": ("flow_master", "Record one missed requirement as telemetry and a checklist line."),
|
|
23
|
+
"devguide": ("flow_master", "Create the developer-facing screen and component guide."),
|
|
24
|
+
"productguide": ("flow_master", "Create the user-facing guide from the running application."),
|
|
25
|
+
"handoff-phase": ("flow_master", "Complete handoff documents, status, and rendered artifacts."),
|
|
26
|
+
"refresh-status": ("flow_master", "Recover truthful project status after an interrupted run."),
|
|
27
|
+
"generate-html": ("flow_master", "Render an arbitrary human-readable Markdown document to HTML."),
|
|
28
|
+
"render-workflow-docs": ("flow_master", "Render the canonical BRD, Architecture, and status HTML files."),
|
|
29
|
+
"metrics-report": ("flow_master", "Report TechieFlow development telemetry without changing code."),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
PERSONAS = {
|
|
33
|
+
"flow-master": "flow-master.md",
|
|
34
|
+
"analyst": "analyst.md",
|
|
35
|
+
"architect": "architect.md",
|
|
36
|
+
"verifier": "verifier.md",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
WORKERS = {
|
|
40
|
+
"tf-builder": """Implement one assigned FN/NFR requirement cluster. Read `.tfcore/tasks/_smoke-test-policy.md`. Never run git or gh. Follow project coding standards, smoke the changed behavior, update only the assigned checklist rows, and return structured evidence to the parent.""",
|
|
41
|
+
"tf-test-writer": """Write black-box verification tests for one assigned requirement cluster. Never edit application source and never run git or gh. Follow `.tfcore/tasks/verify-phase.md` and return tests added, tests refreshed, and anything unobservable.""",
|
|
42
|
+
"tf-explorer": """Perform a focused read-only codebase scan. Never edit files and never run git or gh. Return concise evidence with file paths and symbols.""",
|
|
43
|
+
"trblazeui": """Read the NuGet-deployed TrBlazeUI persona and adopt its implementation rules. Resolve it in this order and use the FIRST that exists: `.claude/commands/trblazeui.md` (current deploy target), `.claude/trblazeui.md` (legacy deploy target), `.opencode/command/trblazeui.md`, `.trblazeui/TrBlazeUI-AI-Reference.md` (packaged component reference). Only if NONE exists, report that the TrBlazeUI persona is not deployed (`dotnet build` the app to unpack the package) and stop. Never run git or gh.""",
|
|
44
|
+
"techierag": """Read the NuGet-deployed TechieRag persona and adopt its implementation rules. Resolve it in this order and use the FIRST that exists: `.claude/commands/techierag.md` (current deploy target), `.claude/techierag.md` (legacy deploy target), `.opencode/command/techierag.md`, `.techierag/TechieRag-AI-Reference.md` (packaged service reference). Only if NONE exists, report that the TechieRag persona is not deployed (`dotnet build` the app to unpack the package) and stop. Never run git or gh.""",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Library-persona workers are COMPATIBILITY wrappers: the library NuGet packages own
|
|
48
|
+
# the native `.codex/agents/<lib>.toml` (TrBlazeUI.Components >= 2.0.3 deploys it on
|
|
49
|
+
# `dotnet build`; TechieRag is expected to follow the same contract). The package's
|
|
50
|
+
# MSBuild target deploys only when the file is absent OR the ownership marker
|
|
51
|
+
# `.<lib>/.codex-agent-package-owned` exists; otherwise it preserves what it finds as
|
|
52
|
+
# consumer-owned. So the framework must (a) never overwrite a file that is not its own
|
|
53
|
+
# wrapper, and (b) write the marker alongside its wrapper so the package is allowed to
|
|
54
|
+
# replace it. The wrapper then self-retires per repo on the first post-2.0.3 build.
|
|
55
|
+
COMPAT = {
|
|
56
|
+
"trblazeui": ("TrBlazeUI.Components", ".trblazeui"),
|
|
57
|
+
"techierag": ("TechieRag", ".techierag"),
|
|
58
|
+
}
|
|
59
|
+
MARKER = ".codex-agent-package-owned"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def own_wrapper(path: pathlib.Path, name: str) -> bool:
|
|
63
|
+
"""True when `path` is absent or holds the framework's own compat wrapper."""
|
|
64
|
+
if not path.exists():
|
|
65
|
+
return True
|
|
66
|
+
return f'description = "TechieFlow {name} role."' in path.read_text(encoding="utf-8")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def routing(path: pathlib.Path) -> dict:
|
|
70
|
+
cfg = {"enabled": False, "tiers": {}, "phases": {}, "subagents": {}, "effort": {}}
|
|
71
|
+
section = tier = None
|
|
72
|
+
if not path.exists():
|
|
73
|
+
return cfg
|
|
74
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
75
|
+
if not line.strip() or line.lstrip().startswith("#"):
|
|
76
|
+
continue
|
|
77
|
+
if not line.startswith(" "):
|
|
78
|
+
key, _, value = line.partition(":")
|
|
79
|
+
section, tier = key.strip(), None
|
|
80
|
+
if section == "enabled":
|
|
81
|
+
cfg["enabled"] = value.strip() == "true"
|
|
82
|
+
elif section == "tiers":
|
|
83
|
+
if re.match(r"^ [a-z-]+:\s*$", line):
|
|
84
|
+
tier = line.strip()[:-1]
|
|
85
|
+
cfg["tiers"][tier] = {}
|
|
86
|
+
elif tier and line.startswith(" "):
|
|
87
|
+
key, _, value = line.strip().partition(":")
|
|
88
|
+
cfg["tiers"][tier][key] = value.strip()
|
|
89
|
+
elif section in ("phases", "subagents", "effort"):
|
|
90
|
+
key, _, value = line.strip().partition(":")
|
|
91
|
+
cfg[section][key] = value.strip()
|
|
92
|
+
return cfg
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def quoted(value: str) -> str:
|
|
96
|
+
return '"' + value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + '"'
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def write(path: pathlib.Path, content: str) -> None:
|
|
100
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
101
|
+
path.write_text(content.rstrip() + "\n", encoding="utf-8", newline="\n")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def persona_instructions(root: pathlib.Path, source_name: str) -> str:
|
|
105
|
+
source = root / ".tfcore" / "agents" / source_name
|
|
106
|
+
return f"""Read `{source.relative_to(root)}` completely before acting and follow its persona, core principles, command routing, and dependency rules. Skip only its activation greeting/help/halt ritual because this is a spawned Codex role. Treat `.tfcore/tasks/*.md` as executable workflows. Never run git or gh. Preserve TechieFlow's smoke, verifier, artifact-location, local-only runtime, checklist, and PROJECT-STATUS invariants. Load only dependencies needed for the assigned task."""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def agent_file(name: str, description: str, instructions: str, model: str | None,
|
|
110
|
+
effort: str | None, read_only: bool = False) -> str:
|
|
111
|
+
lines = [f"name = {quoted(name)}", f"description = {quoted(description)}",
|
|
112
|
+
f"developer_instructions = {quoted(instructions)}"]
|
|
113
|
+
if model:
|
|
114
|
+
lines.append(f"model = {quoted(model)}")
|
|
115
|
+
if effort:
|
|
116
|
+
lines.append(f"model_reasoning_effort = {quoted(effort)}")
|
|
117
|
+
if read_only:
|
|
118
|
+
lines.append('sandbox_mode = "read-only"')
|
|
119
|
+
return "\n".join(lines)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main() -> int:
|
|
123
|
+
parser = argparse.ArgumentParser()
|
|
124
|
+
parser.add_argument("root", nargs="?", default=".")
|
|
125
|
+
args = parser.parse_args()
|
|
126
|
+
root = pathlib.Path(args.root).resolve()
|
|
127
|
+
if not (root / ".tfcore").is_dir():
|
|
128
|
+
parser.error(f"not a TechieFlow repository: {root}")
|
|
129
|
+
cfg = routing(root / ".tfcore" / "routing.yaml")
|
|
130
|
+
|
|
131
|
+
persona_tier = {"flow-master": "build-phase", "analyst": "day1-greenfield",
|
|
132
|
+
"architect": "day1-greenfield", "verifier": "verify-phase"}
|
|
133
|
+
for name, source in PERSONAS.items():
|
|
134
|
+
tier = cfg["phases"].get(persona_tier[name], "inherit")
|
|
135
|
+
model = cfg["tiers"].get(tier, {}).get("codex") if cfg["enabled"] and tier != "inherit" else None
|
|
136
|
+
effort = cfg["effort"].get(tier) if model else None
|
|
137
|
+
write(root / ".codex" / "agents" / f"{name}.toml", agent_file(
|
|
138
|
+
name.replace("-", "_"), f"TechieFlow {name} specialist.",
|
|
139
|
+
persona_instructions(root, source), model, effort))
|
|
140
|
+
|
|
141
|
+
kept = []
|
|
142
|
+
for name, instructions in WORKERS.items():
|
|
143
|
+
tier = cfg["subagents"].get(name, "inherit")
|
|
144
|
+
model = cfg["tiers"].get(tier, {}).get("codex") if cfg["enabled"] and tier != "inherit" else None
|
|
145
|
+
effort = cfg["effort"].get(tier) if model else None
|
|
146
|
+
target = root / ".codex" / "agents" / f"{name}.toml"
|
|
147
|
+
if name in COMPAT:
|
|
148
|
+
package, lib_dir = COMPAT[name]
|
|
149
|
+
if not own_wrapper(target, name):
|
|
150
|
+
kept.append(name) # package- or consumer-owned agent: never overwrite
|
|
151
|
+
continue
|
|
152
|
+
marker = root / lib_dir / MARKER
|
|
153
|
+
if not marker.exists():
|
|
154
|
+
write(marker, package)
|
|
155
|
+
ignore = root / lib_dir / ".gitignore" # same `*` the package writes on build
|
|
156
|
+
if not ignore.exists():
|
|
157
|
+
write(ignore, "*")
|
|
158
|
+
write(target, agent_file(
|
|
159
|
+
name.replace("-", "_"), f"TechieFlow {name} role.", instructions,
|
|
160
|
+
model, effort, read_only=name == "tf-explorer"))
|
|
161
|
+
|
|
162
|
+
for phase, (owner, description) in PHASES.items():
|
|
163
|
+
skill_name = f"techieflow-{phase.removesuffix('-phase')}"
|
|
164
|
+
task = f".tfcore/tasks/{phase}.md"
|
|
165
|
+
body = f"""---
|
|
166
|
+
name: {skill_name}
|
|
167
|
+
description: {description} Use when a TechieFlow project needs its `{phase}` workflow.
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
# {skill_name}
|
|
171
|
+
|
|
172
|
+
1. Read `{task}` completely and follow it as the canonical executable workflow.
|
|
173
|
+
2. Read `.tfcore/core-config.yaml` and only the task dependencies required for this run.
|
|
174
|
+
3. Operate as the `{owner}` role. Delegate only where the task explicitly calls for independent subagents, using the registered Codex roles and waiting for their results.
|
|
175
|
+
4. Preserve interactive elicitation unless `.tfcore/.session/yolo.json` exists or the user explicitly requested YOLO/goal mode.
|
|
176
|
+
5. Never run `git` or `gh`. Run required builds, smoke tests, runtime observations, verifier gates, document updates, and telemetry yourself.
|
|
177
|
+
6. Treat old `*...` and harness slash-command text in the canonical task as vocabulary aliases; execute the named task or delegate to the named Codex role directly.
|
|
178
|
+
"""
|
|
179
|
+
write(root / ".agents" / "skills" / skill_name / "SKILL.md", body)
|
|
180
|
+
|
|
181
|
+
yolo = """---
|
|
182
|
+
name: techieflow-yolo
|
|
183
|
+
description: Enable, disable, or inspect TechieFlow YOLO mode for an explicitly requested unattended workflow.
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
Read `.tfcore/tasks/_yolo-mode.md` completely. Run `bash .tfcore/utils/tf-yolo.sh on|off` as requested. YOLO removes elicitation pauses but does not broaden the user's task, allow git/gh, bypass the Codex workspace sandbox, or waive genuine external blockers. For a supervised long-running goal, use `.tfcore/utils/tf-goal.sh --harness codex`.
|
|
187
|
+
"""
|
|
188
|
+
write(root / ".agents" / "skills" / "techieflow-yolo" / "SKILL.md", yolo)
|
|
189
|
+
print(f"tf-codex-bind: generated {len(PERSONAS) + len(WORKERS) - len(kept)} agents and {len(PHASES) + 1} skills")
|
|
190
|
+
for name in kept:
|
|
191
|
+
print(f"tf-codex-bind: kept library-owned .codex/agents/{name}.toml (compat wrapper retired)")
|
|
192
|
+
return 0
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Emit authoritative Codex exec JSONL usage into TechieFlow sessions telemetry."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import pathlib
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> int:
|
|
14
|
+
if len(sys.argv) != 3:
|
|
15
|
+
print("usage: tf-codex-telemetry.py <project-root> <codex-jsonl>", file=sys.stderr)
|
|
16
|
+
return 2
|
|
17
|
+
root = pathlib.Path(sys.argv[1]).resolve()
|
|
18
|
+
source = pathlib.Path(sys.argv[2])
|
|
19
|
+
thread_id = None
|
|
20
|
+
model = None
|
|
21
|
+
totals = {"input_tokens": 0, "output_tokens": 0, "cache_read_tokens": 0,
|
|
22
|
+
"reasoning_output_tokens": 0}
|
|
23
|
+
try:
|
|
24
|
+
for line in source.read_text(encoding="utf-8", errors="replace").splitlines():
|
|
25
|
+
try:
|
|
26
|
+
event = json.loads(line)
|
|
27
|
+
except Exception:
|
|
28
|
+
continue
|
|
29
|
+
if event.get("type") == "thread.started":
|
|
30
|
+
thread_id = event.get("thread_id") or thread_id
|
|
31
|
+
if event.get("model"):
|
|
32
|
+
model = event.get("model")
|
|
33
|
+
if event.get("type") == "turn.completed" and isinstance(event.get("usage"), dict):
|
|
34
|
+
usage = event["usage"]
|
|
35
|
+
totals["input_tokens"] += int(usage.get("input_tokens") or 0)
|
|
36
|
+
totals["output_tokens"] += int(usage.get("output_tokens") or 0)
|
|
37
|
+
totals["cache_read_tokens"] += int(usage.get("cached_input_tokens") or 0)
|
|
38
|
+
totals["reasoning_output_tokens"] += int(usage.get("reasoning_output_tokens") or 0)
|
|
39
|
+
except Exception:
|
|
40
|
+
return 0
|
|
41
|
+
if not thread_id or not any(totals.values()):
|
|
42
|
+
return 0
|
|
43
|
+
record = {
|
|
44
|
+
"kind": "session", "session_id": thread_id, "model": model,
|
|
45
|
+
"duration_s": None, **totals, "cache_creation_tokens": None,
|
|
46
|
+
"cost_usd": None, "children_sessions": None,
|
|
47
|
+
}
|
|
48
|
+
emit = root / ".tfcore" / "utils" / "tf-emit.sh"
|
|
49
|
+
env = os.environ.copy()
|
|
50
|
+
env.update(TF_HARNESS="codex", TF_PROJECT_DIR=str(root), CLAUDE_PROJECT_DIR=str(root))
|
|
51
|
+
try:
|
|
52
|
+
subprocess.run(["bash", str(emit), "sessions"], input=json.dumps(record), text=True,
|
|
53
|
+
timeout=10, env=env, check=False)
|
|
54
|
+
except Exception:
|
|
55
|
+
pass
|
|
56
|
+
return 0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
raise SystemExit(main())
|