honestweek 0.2.0 → 0.3.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-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +3 -2
- package/README.md +252 -197
- package/SKILL.md +25 -74
- package/bin/honestweek.mjs +81 -24
- package/flows/client.md +19 -0
- package/flows/digest.md +11 -0
- package/flows/mine.md +18 -0
- package/flows/view.md +45 -0
- package/flows/weekly.md +29 -0
- package/lib/ask.mjs +1142 -0
- package/lib/build.mjs +12 -3
- package/lib/config-lookup.mjs +179 -0
- package/lib/config.mjs +20 -0
- package/lib/demo/week.mjs +3 -0
- package/lib/digest-carry.mjs +3 -2
- package/lib/digest-store.mjs +3 -2
- package/lib/digest.mjs +21 -14
- package/lib/discover.mjs +28 -22
- package/lib/emit/index.mjs +18 -6
- package/lib/harvest.mjs +19 -1
- package/lib/history.mjs +10 -2
- package/lib/init.mjs +241 -55
- package/lib/mine.mjs +18 -8
- package/lib/preview.mjs +66 -13
- package/lib/private-words.mjs +25 -5
- package/lib/problems/index.mjs +60 -7
- package/lib/prompt-lane.mjs +14 -13
- package/lib/prompt-store.mjs +2 -1
- package/lib/prompts.mjs +13 -7
- package/lib/replay/assemble.mjs +25 -8
- package/lib/replay/index.mjs +200 -12
- package/lib/replay/lookup.mjs +6 -3
- package/lib/replay/saved-sessions.mjs +315 -0
- package/lib/replay/views.mjs +12 -1
- package/lib/{view → replay}/word-index.mjs +3 -3
- package/lib/replay/words.mjs +122 -0
- package/lib/repo-identity.mjs +81 -13
- package/lib/saved/checks.mjs +381 -0
- package/lib/saved/history.mjs +235 -0
- package/lib/saved/saver.mjs +111 -0
- package/lib/saved/store.mjs +256 -0
- package/lib/status.mjs +288 -0
- package/lib/validate.mjs +12 -3
- package/lib/view/assets/common.css +2 -0
- package/lib/view/assets/common.js +20 -2
- package/lib/view/assets/problems.js +4 -3
- package/lib/view/assets/replay.js +3 -1
- package/lib/view/assets/search.js +1 -1
- package/lib/view/assets/sessions.js +1 -0
- package/lib/view/assets/settings.html +16 -0
- package/lib/view/assets/settings.js +108 -4
- package/lib/view/assets/setup.html +7 -0
- package/lib/view/assets/setup.js +9 -0
- package/lib/view/codex-judge.mjs +1 -1
- package/lib/view/data.mjs +160 -76
- package/lib/view/own-week.mjs +119 -0
- package/lib/view/page-link.mjs +84 -0
- package/lib/view/problems-route.mjs +29 -3
- package/lib/view/replay-export.mjs +1 -1
- package/lib/view/selftest/clickthrough.js +9 -5
- package/lib/view/server.mjs +3 -1
- package/lib/view/settings.mjs +102 -34
- package/lib/view/setup.mjs +27 -14
- package/lib/view/suggest-words.mjs +67 -0
- package/lib/view.mjs +82 -133
- package/lib/worktrees.mjs +31 -18
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
[](https://github.com/BryceEWatson/honestweek/actions/workflows/ci.yml)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
See where your Claude Code and Codex sessions went wrong, open the exact steps behind each problem, and check every count yourself.
|
|
6
|
+
See where your Claude Code and Codex sessions went wrong, open the exact steps behind each problem, and check every count yourself. The page runs on your machine with fixed rules and sends nothing to an AI unless you turn that on.
|
|
7
7
|
|
|
8
8
|
<picture>
|
|
9
9
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/replay-dark.png">
|
|
10
10
|
<img src="docs/images/replay-light.png" alt="Replay of a three-hour session from the made-up demo week: one row for the main agent and one for each of its seven sub-agents, a Problems row with two rings, and the selected step, where the agent says all tests pass right after a test run failed.">
|
|
11
11
|
</picture>
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
This is a replay of the longest session in the made-up demo week: a main agent and seven sub-agents building a feature over three hours. It's from `npx honestweek view --demo` with the Show private text switch on, so the made-up names show. The two rings on the Problems row mark the two things worth a look. The selected one is the agent saying "All tests pass" right after a run that failed.
|
|
14
14
|
|
|
15
15
|
<details>
|
|
16
16
|
<summary>More screenshots: Problems, a problem up close, sessions, Find, Goals, Setup, a weekly page and a client report</summary>
|
|
17
17
|
|
|
18
|
-
**Problems** shows the known ways agents go wrong that turned up in your week
|
|
18
|
+
**The Problems page** shows the known ways agents go wrong that turned up in your week. It puts the worst first and gives each one a fix to copy.
|
|
19
19
|
|
|
20
20
|
<picture>
|
|
21
21
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/problems-dark.png">
|
|
@@ -29,53 +29,51 @@ Replay of the longest session in the made-up demo week (`npx honestweek view --d
|
|
|
29
29
|
<img src="docs/images/problem-focus-light.png" alt="One problem opened: the six times it happened down the left, What happened for the selected one in four numbered steps (the failed run, nothing after it, the success claim, what the agent said), and below it a hook to copy into Claude Code.">
|
|
30
30
|
</picture>
|
|
31
31
|
|
|
32
|
-
**Sessions**
|
|
32
|
+
**The Sessions list** shows your week, newest day first. When a program started a run, the list says what started it and links to that step.
|
|
33
33
|
|
|
34
34
|
<picture>
|
|
35
35
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/sessions-dark.png">
|
|
36
36
|
<img src="docs/images/sessions-light.png" alt="Replay's sessions list for the demo week, Saturday first: each session with its time, length, tool, prompts and problems, and a review run marked as started by another session's step.">
|
|
37
37
|
</picture>
|
|
38
38
|
|
|
39
|
-
**Find** takes a pull request, a commit, a file, a branch or a few words and shows the sessions and goals behind it.
|
|
39
|
+
**The Find page** takes a pull request, a commit, a file, a branch or a few words and shows the sessions and goals behind it.
|
|
40
40
|
|
|
41
41
|
<picture>
|
|
42
42
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/find-dark.png">
|
|
43
43
|
<img src="docs/images/find-light.png" alt="Find, looking up the file src/parse.mjs: the six sessions that touched it, each with how that's known, and the two goals they worked toward.">
|
|
44
44
|
</picture>
|
|
45
45
|
|
|
46
|
-
**Goals** puts one goal's sessions on a single timeline you can play.
|
|
46
|
+
**The Goals page** puts one goal's sessions on a single timeline you can play.
|
|
47
47
|
|
|
48
48
|
<picture>
|
|
49
49
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/goals-dark.png">
|
|
50
50
|
<img src="docs/images/goals-light.png" alt="Goals: the release goal's four sessions on one timeline, with a panel explaining why each session belongs to the goal.">
|
|
51
51
|
</picture>
|
|
52
52
|
|
|
53
|
-
**Setup** opens the first time you run `view` in a folder with no config
|
|
53
|
+
**The Setup page** opens the first time you run `honestweek view` in a folder with no config. It lists the repositories it found nearby and asks what to keep private.
|
|
54
54
|
|
|
55
55
|
<picture>
|
|
56
56
|
<source media="(prefers-color-scheme: dark)" srcset="docs/images/setup-dark.png">
|
|
57
57
|
<img src="docs/images/setup-light.png" alt="Setup on first run: two git repositories found nearby, each with a role menu, then the email, the timezone, how far back to look, and the words to keep private.">
|
|
58
58
|
</picture>
|
|
59
59
|
|
|
60
|
-
**A weekly page** ([page mode](#standalone-site-page-mode)) is the summary you publish yourself
|
|
60
|
+
**A weekly page** ([page mode](#standalone-site-page-mode)) is the summary you publish yourself. It lists every change with its status and the commit it came from. I built this one from the demo week.
|
|
61
61
|
|
|
62
62
|
<img src="docs/images/weekly-page.png" alt="A weekly page built from the demo week: commits per day, a one-line headline, and the week's changes, three shipped and one in progress.">
|
|
63
63
|
|
|
64
|
-
**A client report** ([client mode](#a-report-for-a-client-client-mode)) is a printable page of the work
|
|
64
|
+
**A client report** ([client mode](#a-report-for-a-client-client-mode)) is a printable page of the work you did for one client, with its counts checked against git. I built this one from the demo week too.
|
|
65
65
|
|
|
66
66
|
<img src="docs/images/client-report.png" alt="A client report built from the demo week: the title, who it's for and by, the period, a headline, counts of merged pull requests and commits, and two highlights.">
|
|
67
67
|
|
|
68
68
|
</details>
|
|
69
69
|
|
|
70
|
-
honestweek works with the session logs that Claude Code and Codex already keep on your computer. It does three things with them,
|
|
70
|
+
honestweek works with the session logs that Claude Code and Codex already keep on your computer. It does three things with them, reading everything on your own machine:
|
|
71
71
|
|
|
72
|
-
- **See where it went wrong.** `honestweek view` opens on
|
|
73
|
-
- **Find and replay your work.**
|
|
72
|
+
- **See where it went wrong.** `honestweek view` opens on the Problems page. It lists the known ways AI coding agents go wrong that showed up in your sessions, and it shows first the times an agent claimed more than it had shown, like saying "done" with no check after the last edit, or claiming a success the output doesn't show. Each one links to its step in your replay and says how it's known. It also shows whether it happened less than in the week before, and offers a fix you can copy into your own instructions or hooks.
|
|
73
|
+
- **Find and replay your work.** The Find page is one click away. Give it a pull request number, a commit, a file, a branch or a few words, and it shows the sessions behind it, which you can then replay step by step. Every link and count says how it's known: recorded if a log or git says so, derived if it's worked out from records, inferred if a named rule reads it that way, or missing. When the records fit a link more than one way, the page also marks it ambiguous.
|
|
74
74
|
- **Write an honest weekly summary.** A short pipeline turns a finished week into a summary you review and publish yourself. It checks every commit the summary cites against your real git history first, and it stops rather than write a claim it can't back.
|
|
75
75
|
|
|
76
|
-
It's for developers who do much of their work through an AI coding agent and want to find, check or show that work later.
|
|
77
|
-
|
|
78
|
-
To see it with nothing to set up, run `npx honestweek view --demo`: a made-up week opens in your browser.
|
|
76
|
+
It's for developers who do much of their work through an AI coding agent and want to find, check or show that work later. There's no account, no telemetry, and honestweek itself makes no network call. Three things you start do send session text to an AI, on your own plan: the weekly summary, where Claude runs honestweek in your own Claude Code session (or Codex, if you run the skill there), reads a redacted draft of your week and sees what each command prints; after you turn on the Include /insights switch, the Run /insights and Run with Codex buttons, which send your sessions to Claude or OpenAI; and the find skill, where Claude or Codex reads the redacted answers `find`, `replay`, `problems` and `goals` print. [Where your data goes](#where-your-data-goes) has the details. The names and client words you list stay hidden on the page. Its Show private text switch shows them, on your own screen only, and the keys, tokens and passwords it recognizes stay hidden either way.
|
|
79
77
|
|
|
80
78
|
## Try it
|
|
81
79
|
|
|
@@ -86,35 +84,51 @@ npx honestweek view --demo # a made-up week in your browser; it sets nothing u
|
|
|
86
84
|
npx honestweek view # set up in your browser, then your own last 7 days
|
|
87
85
|
```
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
If you'd rather have a plain `honestweek` command, install it with `npm install -g honestweek`, then type `honestweek` wherever this page says `npx honestweek`. From here on, I write plain `honestweek`. From a clone of this repository, type `node bin/honestweek.mjs` instead. To run unreleased code from `main`, type `npx github:BryceEWatson/honestweek`. Run `honestweek` with no command and it lists the first steps, and its messages show each next command in the same form you used to run it.
|
|
90
88
|
|
|
91
|
-
The demo opens
|
|
89
|
+
The demo opens on the Problems page, which lists the known ways AI coding agents go wrong that showed up in that week, worst first. The page has four parts: Find (the sessions behind a pull request, a commit, a file or a few words), Goals, Replay and Problems. Press Ctrl+C in the terminal to stop it.
|
|
92
90
|
|
|
93
|
-
|
|
91
|
+
**Before you run it on your own logs.** honestweek only reads your logs. It never changes them. Keys, tokens and passwords it recognizes are always hidden on the page ([what it catches, and what it doesn't](#what-the-scrubber-catches-and-what-it-doesnt)). People's names and client words aren't hidden until you list them on the Setup page. Until you do, `honestweek view` tells you so in the terminal and on every page.
|
|
94
92
|
|
|
95
|
-
Run `view`
|
|
93
|
+
Run `honestweek view` from one of your project folders, or from a new folder next to them. With no config there or for every folder, the page that opens is Setup. It lists that folder if it's a git repository, plus the git repositories next to it. A git worktree, a second working copy of a repository, shows up under its repository rather than on its own. Setup fills in your email from git and your timezone, then asks which people's names and client or project words to hide, and how far back to look. You can remove a repository or change its role first ([Repo roles](#config-reference) says what each role does). Press Save, and it writes the config and opens your week's Problems page. "Save it for" picks this folder or every folder: the every-folder config is the one a command reads from any folder without its own, so an agent working in another project finds it ([Where honestweek finds your config](#where-honestweek-finds-your-config)). It also adds the config to `.gitignore`, since the file holds your email, your folder paths and any private words. To change any of this later, open Settings in the page header. For scripts and CI, `init` asks about the repositories and private words in a terminal (`honestweek init --yes` takes the defaults). Once the config exists, Settings' "Suggest words from my sessions" lists words from your own sessions you might want to hide, or run `honestweek discover`, then `honestweek harvest`, and read `honestweek.harvest.json`. [docs/local-page.md](docs/local-page.md) has every Setup and Settings detail.
|
|
96
94
|
|
|
97
95
|
What's further down:
|
|
98
96
|
|
|
99
|
-
- [Install](#install) as a Claude Code plugin, a plain skill, or the standalone command.
|
|
97
|
+
- [Install](#install) as a Claude Code plugin, a plain skill, a Codex skill, or the standalone command.
|
|
100
98
|
- [Finding and replaying your work in the browser](#finding-and-replaying-your-work-in-the-browser-view): every option of `view`, the goal list, and what it keeps private.
|
|
101
99
|
- [The flow](#the-flow-an-honest-weekly-summary): the weekly summary from `init` to `build`, then [mining solved problems](#mining-solved-problems-worth-publishing-mine), [a standalone site](#standalone-site-page-mode) and [a report for a client](#a-report-for-a-client-client-mode).
|
|
102
100
|
- [Config reference](#config-reference), [Sidecars](#sidecars) (the files it writes) and the [privacy model](#what-it-does-not-do--privacy-model).
|
|
103
101
|
|
|
102
|
+
## Where your data goes
|
|
103
|
+
|
|
104
|
+
honestweek reads your logs and repositories on your own machine. Here's which parts of it an AI ever sees:
|
|
105
|
+
|
|
106
|
+
| What you run | What it reads | Does an AI see it? |
|
|
107
|
+
| --- | --- | --- |
|
|
108
|
+
| `honestweek view` (the page, with its Setup and Settings) | Your session logs and repositories, into memory on your machine | No, unless you turn on Include /insights and press Run |
|
|
109
|
+
| `/honestweek` (the weekly summary in Claude Code) | A redacted draft of last week's Claude Code sessions, plus what each command prints | Yes: Claude reads all of it and writes the summary from the draft |
|
|
110
|
+
| `init`, `discover`, `build` on their own | Your git settings, repositories and logs | No. Run through `/honestweek`, Claude sees what they print |
|
|
111
|
+
|
|
112
|
+
The skill in Codex works the same way as `/honestweek`, with Codex reading the draft and the command output and sending them to OpenAI, or the endpoint your Codex is set to use, in Claude's place.
|
|
113
|
+
|
|
114
|
+
[Where your data goes](docs/where-your-data-goes.md) walks through each one step by step, lists exactly what the draft holds, and says who receives what from the two Run buttons.
|
|
115
|
+
|
|
104
116
|
## Why
|
|
105
117
|
|
|
106
|
-
|
|
118
|
+
An agent can say "All tests pass" right after a test run failed, and in a three-hour session with seven sub-agents you might never scroll back far enough to see it. I built honestweek to catch that and let you dig in. The Problems page checks your sessions for known ways agents go wrong. It shows first the times an agent claimed more than it had shown, like saying "done" with no check after its last edit. Each finding opens at its place on the session's timeline. The main agent has its own row there, and its sub-agents share one row, which opens into a row for each of them. Every step opens to what's behind it: the log line it came from, the command's output and how its time is known. A step worked out from the records around it shows a note saying so in place of a log line. You see exactly what happened before you change anything. Then you copy the fix it offers, and the problem's count against the week before shows whether it's happening less.
|
|
119
|
+
|
|
120
|
+
The same rule runs through all of it: honestweek states nothing without its evidence. Every link, count and step says how it's known. The weekly summary goes further. Your commits show what shipped, and your sessions show what you *figured out*. Every line points to the commit or session turn it came from, and I call that pointer its receipt. Each work item carries one of three statuses: `shipped`, `in progress` or `designed, not proven`. The digest also picks highlights from your week, like prompts, ideas and decisions. Each pick says why it was picked, and none of them claims a status.
|
|
107
121
|
|
|
108
122
|
## Requirements
|
|
109
123
|
|
|
110
124
|
- **Node ≥ 18**
|
|
111
125
|
- The system **`git` CLI**, version 2.24 or later, on your `PATH`
|
|
112
126
|
- **Zero runtime dependencies**: Node built-ins plus `git` only
|
|
113
|
-
- Runs **entirely locally**. No telemetry, and honestweek itself makes no network call. The two optional buttons under Include /insights run your own `claude` or `codex
|
|
127
|
+
- Runs **entirely locally**. No telemetry, and honestweek itself makes no network call. The weekly summary runs inside your own Claude Code session (or Codex session), so Claude (or Codex) reads the redacted draft of your week, and the two optional buttons under Include /insights run your own `claude` or `codex` only when you press them, and those do send your sessions to Claude or OpenAI. The optional `preview` and `view` servers bind to loopback (`127.0.0.1`) only.
|
|
114
128
|
|
|
115
129
|
## Install
|
|
116
130
|
|
|
117
|
-
honestweek runs locally and has no dependencies to install. Pick whichever path you prefer. The plugin and the
|
|
131
|
+
honestweek runs locally and has no dependencies to install. Pick whichever path you prefer. The plugin, the plain skill and the Codex route each give you the weekly-summary skill, under the name each section below says, and the find skill: a read-only skill Claude or Codex starts on its own when you ask which session made a pull request, what happened in a session, or where your sessions went wrong. I checked each route for the weekly skill from a fresh setup on 7 October 2026 (Claude Code 2.1.292, Codex 0.144.6). The same day, I checked that Claude Code lists the find skill from the plugin, the plain skill and a clone, and that Codex lists it from its skills folder and from a clone (`codex debug prompt-input`, which shows the skills Codex sees without a model call). Through the skill, Claude can also start the browser page (`view`) for you; to run it yourself, use the standalone command.
|
|
118
132
|
|
|
119
133
|
### As a Claude Code plugin (recommended for the weekly summary)
|
|
120
134
|
|
|
@@ -132,7 +146,7 @@ claude plugin marketplace add BryceEWatson/honestweek
|
|
|
132
146
|
claude plugin install honestweek@honestweek
|
|
133
147
|
```
|
|
134
148
|
|
|
135
|
-
You get `/honestweek` inside Claude Code, with versioned updates via `/plugin marketplace update`.
|
|
149
|
+
You get `/honestweek:honestweek` inside Claude Code, and the find skill as `honestweek:honestweek-find`, with versioned updates via `/plugin marketplace update`. Claude Code names a plugin's skill with the plugin's name in front, so it isn't plain `/honestweek` here. The plugin is for Claude Code only: Claude Code's plugin docs say claude.ai and Cowork don't install a plugin with a top-level `bin/` folder, and this one has one.
|
|
136
150
|
|
|
137
151
|
### As a plain skill
|
|
138
152
|
|
|
@@ -142,7 +156,23 @@ Clone into your personal skills directory:
|
|
|
142
156
|
git clone https://github.com/BryceEWatson/honestweek ~/.claude/skills/honestweek
|
|
143
157
|
```
|
|
144
158
|
|
|
145
|
-
|
|
159
|
+
You get `/honestweek`, and the find skill as `honestweek:honestweek-find`. If you also have the plugin, you get both names, since the plugin's is set apart by its prefix.
|
|
160
|
+
|
|
161
|
+
With the plugin or the plain skill, the weekly skill runs its bundled CLI by an **absolute path inside the skill's own folder** (`${CLAUDE_SKILL_DIR}/bin/honestweek.mjs`), and the find skill reaches the same CLI two folders up from its own (`${CLAUDE_SKILL_DIR}/../../bin/honestweek.mjs`). That's why the commands work from *your own* project directory.
|
|
162
|
+
|
|
163
|
+
### In a clone of this repository
|
|
164
|
+
|
|
165
|
+
Working inside a clone of honestweek itself, `/honestweek` is already there with nothing to install: the repository carries a project skill in `.claude/skills/honestweek/` that points Claude at the root `SKILL.md` and the repository's own `bin/honestweek.mjs`. It only applies inside this repository; for your other projects, use the plugin or the plain skill above. If you've also installed the plain skill, Claude Code runs that one, since a personal skill wins over a project skill with the same name. The find skill is there too, in `.claude/skills/honestweek-find/`, as `honestweek-find`. For Codex, the clone carries both in `.agents/skills/`.
|
|
166
|
+
|
|
167
|
+
### In Codex
|
|
168
|
+
|
|
169
|
+
Clone into Codex's skills folder:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
git clone https://github.com/BryceEWatson/honestweek ~/.codex/skills/honestweek
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Codex lists it as `honestweek:honestweek`, which lets it start the skill when you ask for a weekly summary. It also lists `honestweek:honestweek-find`, the find skill, which it can start by its description when you ask about past sessions, and `honestweek:honestweek-contract`, the rules for writing the summary's items, which it can load by its description when it works on them. Codex has no subagents here, so it writes the items itself under those rules. If you've set `CODEX_HOME`, clone into its `skills` folder instead. Codex doesn't fill in `${CLAUDE_SKILL_DIR}`, so the skill tells it to run the CLI from the folder its `SKILL.md` is in. I've checked that Codex finds the skill there; I haven't run a whole weekly summary through Codex yet.
|
|
146
176
|
|
|
147
177
|
### As a standalone CLI
|
|
148
178
|
|
|
@@ -174,34 +204,35 @@ npx github:BryceEWatson/honestweek --help
|
|
|
174
204
|
npm install -g github:BryceEWatson/honestweek # or install that code as the honestweek command
|
|
175
205
|
```
|
|
176
206
|
|
|
177
|
-
The CLI surface is
|
|
207
|
+
The CLI surface is sixteen subcommands: `init`, `discover`, `prompts`, `digest`, `validate`, `build`, `harvest`, `preview`, `mine`, `history`, `view`, `status`, `find`, `replay`, `problems`, and `goals`. Every one answers `--help` without touching your files. `honestweek view` is the browser page, described [next](#finding-and-replaying-your-work-in-the-browser-view), and `honestweek find`, `honestweek replay`, `honestweek problems` and `honestweek goals` answer its questions in a terminal or a chat ([Asking from a terminal or a chat](#asking-from-a-terminal-or-a-chat-find-replay-problems-goals)). `honestweek init`, `honestweek discover`, `honestweek validate` and `honestweek build` make the weekly summary ([The flow](#the-flow-an-honest-weekly-summary)). `honestweek digest` adds one review of the week's prompts, ideas, techniques, decisions, reversals and next steps to `page` or `site` output, and `honestweek prompts` keeps your private prompt inbox. `honestweek harvest` suggests words to keep private, `honestweek preview` shows the built output on a local-only (`127.0.0.1`) page, `honestweek mine` finds [solved problems worth publishing](#mining-solved-problems-worth-publishing-mine), and `honestweek history` lists what landed in a period, for a [client report](#a-report-for-a-client-client-mode).
|
|
178
208
|
|
|
179
209
|
## Finding and replaying your work in the browser (`view`)
|
|
180
210
|
|
|
181
|
-
`honestweek view` opens a page on your own machine
|
|
211
|
+
`honestweek view` opens a page on your own machine. It starts on the Problems page, which shows where your sessions went wrong. From there you can find the sessions and goals behind a pull request, a commit, a file, a branch or some words, see which sessions worked toward each goal, and replay any session step by step. It reads your config and your Claude Code and Codex logs from as far back as your config's `history` says (the last 7 days unless you chose otherwise in Setup or Settings), serves the page on `127.0.0.1`, and opens your browser. It publishes nothing, and you have full control over what it keeps. It keeps only what you choose to save, like your config when you press Save and the redacted answers from Run with Codex when you run it, in your own folder where you can read or delete it.
|
|
182
212
|
|
|
183
213
|
```bash
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
214
|
+
honestweek view # as far back as your config says, 7 days by default
|
|
215
|
+
honestweek view --days 30 # look further back
|
|
216
|
+
honestweek view --from 2024-06-10 --to 2024-06-16 --goals goals.json
|
|
217
|
+
honestweek view --demo # a made-up week, before you set anything up
|
|
188
218
|
```
|
|
189
219
|
|
|
190
|
-
With no
|
|
220
|
+
With no config to read ([where it looks](#where-honestweek-finds-your-config)), it opens the Setup page instead, and the terminal says so in one line. Setup runs on the same local server with the same per-run key ([What `view` keeps private](#what-view-keeps-private) explains the key). It writes the config with the same code `init` uses, never over a config that's already there, and then the page moves on to your week's Problems page. Your answers, private words included, go only to this local server, never into an address or the terminal. If `--config` names a file that isn't there, it stops and says so. While it reads the logs, the page says what it's reading and for how long. When your config lists no private words, the terminal and every page say that names and client words show as written, and where to add them. Ctrl+C stops it.
|
|
191
221
|
|
|
192
222
|
What's on the page:
|
|
193
223
|
|
|
194
224
|
- *Find.* Type a pull request (`#67` or its address), a commit, a file or a branch, and it lists the sessions and goals behind it. Type words, and it lists the goals and sessions whose titles match, the branches that contain them, and the prompts that share the most words, each with a link to replay from that prompt. A line says what these lookups cover: your configured repositories, in the dates shown at the top of every page.
|
|
195
|
-
- *Search everywhere.*
|
|
196
|
-
- *Goals.*
|
|
197
|
-
- *Replay.* Any session, step by step. Replay opens on a list of the week's sessions by day, a few per day with "Show more"
|
|
198
|
-
- *Problems.*
|
|
199
|
-
- *Include /insights.*
|
|
200
|
-
- *Facts and Run with Codex.* Replay and Problems have a
|
|
225
|
+
- *Search everywhere.* Under "Elsewhere on this machine", this searches the same words across the prompts and titles of every session in those dates, including display-only repositories (the `display` role, which git never reads) and folders outside your config. Each result says whether it came from a configured repository, a display-only one or an outside folder.
|
|
226
|
+
- *Goals.* This shows each goal in your goal list, with the sessions working toward it on one timeline you can play, pause and scrub. If your goal list cites something no session backs, the page lists that citation as missing, with the reason.
|
|
227
|
+
- *Replay.* Any session, step by step. Replay opens on a list of the week's sessions by day, a few per day with "Show more" for the rest. Pick one there, and every replay links back to that list. Each step opens a panel showing what happened and who did it: "You", the main agent, or a named sub-agent (what a `codex exec` run was told counts as the agent's). The panel also shows the original log line, checked against its fingerprint, a command's output, and how its time is known.
|
|
228
|
+
- *Problems.* This is the page `honestweek view` opens on. It knows 42 ways AI coding agents go wrong or waste time and tokens, checks your sessions for 21 of them, and shows which turned up, starting with the times an agent claimed more than it had shown. The main list holds the problems with a finding worked out from the log itself. A problem found only by a rule's guess or a missing record goes in its own "Possible" section below it, which starts open. Each problem shows its count against the window just before it (say "2 times · 4 before"), and each count says how it's known. Open a problem for a fix you can copy (a hook, an instruction line, a setting or a skill change, never applied for you), a suggested prompt that should trigger the problem so you can watch the fix catch it, and each finding linked to its step in the replay. The replay and goal timelines can mark the same findings. To see it on the made-up week, run `honestweek view --demo`. I list every source behind these problems, once each, in [docs/sources.md](docs/sources.md).
|
|
229
|
+
- *Include /insights.* This is an optional switch under "What was checked" on the Problems page. It's off by default, and turning it on saves `"insights": true` in the config. It adds what Claude Code's own `/insights` command wrote about these sessions as a separate group labelled AI-written, never counted with honestweek's findings. A Run /insights button starts `claude -p /insights` on your machine. It asks first, since that uses your Claude plan and sends your sessions to Claude.
|
|
230
|
+
- *Facts and Run with Codex.* The Replay and Problems pages each have a collapsed "Facts" section with the plain facts `/insights` keeps about a session, worked out from your logs for Claude Code and Codex alike. Each fact says how it's known, or says "not recorded". With Include /insights on, the Run with Codex button has your own `codex` write the AI-written part for your Codex sessions. Its answers are saved beside your config and shown as their own group. It asks first, since it uses your Codex plan and sends your Codex sessions to OpenAI, and while Codex judges them it can read any file you can read.
|
|
231
|
+
- *Save results between runs.* An optional switch in Settings, off by default. Turned on, it saves `"saveResults": { "on": true }` in the config, and each time a whole window loads, `view` keeps what the Problems checks found, and each day's history, in `honestweek.saved/` beside your config: one file per day, with private words hidden, git-ignored and, on Linux and macOS, readable only by you. Each run adds to it and replaces the days it read again. So after Claude Code deletes a log (it does after 30 days, by default), its session stays on the page, on Replay, Problems, goals and pull-request and commit lookups, marked "Saved Oct 6, 2026, log gone", and `honestweek problems --session` can still say whether it was checked and what was found. Its steps can't be checked against their log lines any more, and each keeps the evidence word it had. With the history saved, a run also skips reading any log that hasn't changed since it was saved, and the Problems trend reads the week before from what was saved, so a long window loads faster. A box under the switch turns the history off, to keep only the check results, which take far less room. Saved days older than the number you keep (365 unless you choose) are deleted as it saves, and Forget saved results deletes the whole folder.
|
|
201
232
|
- *Light or dark.* A switch in every page's header, remembered in this browser only. With no choice made, the pages follow your system setting.
|
|
202
|
-
- *
|
|
233
|
+
- *How it's known.* Every link, count and step carries one of four labels: **recorded** (a log line or git says so), **derived** (computed from recorded facts), **inferred** (a named rule's best reading, and the rule is named) or **missing** (the log doesn't say). When the records fit a link more than one way, the page also marks it **ambiguous**. If you put a session in a goal yourself, by citing it in your goal list, the page labels that link as yours.
|
|
203
234
|
|
|
204
|
-
Options: `--days <n>`, or `--from` with `--to`, picks the dates; `--timezone <zone>` reads them in another timezone; `--goals <file>` names your goal list; `--config <file>` reads another config; `--port <n>` picks the port (a free one otherwise); `--no-open` only prints the address; `--self-test` adds a page that clicks through every page in your browser and reports each step as pass, fail or skip, and prints that page's address too; a step's note can quote what the page showed, so read it before you share it. `--demo` uses only its own made-up logs, config, goal list and week, so it refuses `--config`, `--goals`, `--days`, `--from`, `--to` and `--timezone`.
|
|
235
|
+
Options: `--days <n>`, or `--from` with `--to`, picks the dates; `--timezone <zone>` reads them in another timezone; `--goals <file>` names your goal list; `--config <file>` reads another config; `--port <n>` picks the port (a free one otherwise); `--no-open` only prints the address; `--page <page>` opens on one of the page's own pages instead of Problems, such as one session's replay (`replay.html?session=<id>`), and typing `link` and a page in that terminal prints a fresh one-time address to it; `--self-test` adds a page that clicks through every page in your browser and reports each step as pass, fail or skip, and prints that page's address too; a step's note can quote what the page showed, so read it before you share it. `--demo` uses only its own made-up logs, config, goal list and week, so it refuses `--config`, `--goals`, `--days`, `--from`, `--to` and `--timezone`.
|
|
205
236
|
|
|
206
237
|
### The goal list
|
|
207
238
|
|
|
@@ -219,81 +250,91 @@ Name it with `--goals <file>`, or once with `goalsFile` in the config. It's a di
|
|
|
219
250
|
|
|
220
251
|
### What `view` keeps private
|
|
221
252
|
|
|
222
|
-
- *It answers only your own page.* The server binds to `127.0.0.1
|
|
253
|
+
- *It answers only your own page.* The server binds to `127.0.0.1`. It refuses a request that names another host, and any data request that comes from another website (its page files hold no data). It answers a data request only when it carries this run's key. It makes a fresh key each run and never puts it in an address or a command line. Instead, the address it opens or prints carries a one-time code, and the page trades that code for the key. Each code works once and only for a while: 15 minutes for a printed address, two for the one it opens your browser with, so an old address in your terminal's scrollback won't open the page. Pressing Enter in the terminal prints a fresh one.
|
|
223
254
|
- *The two run buttons.* The server, not just the page, refuses Run /insights and Run with Codex while Include /insights is off. Each program gets only the environment variables it needs to start and sign in, so other tools' tokens in your environment don't reach it.
|
|
224
255
|
- *Redacted unless you ask.* The page shows redacted text. Its **Show private text** switch shows names, client words and folders on your own screen; keys, tokens and passwords stay hidden either way. The switch starts off every run and changes only text, never which sessions link to which or which goals they join. That version is built in memory the first time you turn it on, and it's never written to disk.
|
|
225
256
|
- *Display-only and outside sessions.* With the switch off, a session from a display-only repository or a folder outside your config never shows a private word, and it never joins a lookup or a goal. Git is never run against a display-only repository.
|
|
226
|
-
- *
|
|
257
|
+
- *You control what's saved.* The page's address holds only made-up ids, never what you typed or a goal's name, because the browser keeps addresses in its history. It reads your logs into memory and keeps only what you choose to save. Here's everything it writes, including two short-lived files it deletes itself:
|
|
258
|
+
- the config, when you save Setup or Settings, or flip Include /insights;
|
|
259
|
+
- the example config beside it, when that's missing;
|
|
260
|
+
- `.gitignore` lines for honestweek's private files;
|
|
261
|
+
- Run with Codex's redacted answers, in `honestweek.codex-judgments/`;
|
|
262
|
+
- with Save results between runs on, each day's check results and history, redacted, in `honestweek.saved/`;
|
|
263
|
+
- a small redirect file in your temporary folder that opens the browser. It's deleted once it's used, after two minutes, or when you stop.
|
|
227
264
|
|
|
228
|
-
|
|
265
|
+
`--demo` builds its made-up week in a temporary folder and deletes it when you stop. When it starts, it also removes its own leftover demo folders older than a day whose run has stopped.
|
|
266
|
+
|
|
267
|
+
## Asking from a terminal or a chat (`find`, `replay`, `problems`, `goals`)
|
|
229
268
|
|
|
230
|
-
|
|
269
|
+
These ask the questions `view` answers, and print the answer as text, or as JSON with `--json`, so an agent in any chat that can run a command can ask them too. With the plugin, the plain skill, a clone of this repository or Codex, the find skill lets the agent run them on its own when you ask about past sessions ([what that sends](docs/where-your-data-goes.md#the-find-skill-and-its-four-questions)):
|
|
231
270
|
|
|
232
271
|
```bash
|
|
233
|
-
|
|
272
|
+
honestweek find '#42' # the sessions and goals behind a pull request
|
|
273
|
+
honestweek find commit:abc1234 # or a commit, file:src/app.js, branch:my-branch
|
|
274
|
+
honestweek find "date filter" # or some words
|
|
275
|
+
honestweek replay cc-abcdefghijkl # one session's steps, in order
|
|
276
|
+
honestweek replay cc-abcdefghijkl --at 2026-10-05T14:30:00Z
|
|
277
|
+
honestweek problems # where sessions went wrong, highest priority first
|
|
278
|
+
honestweek problems --session cc-abcdefghijkl # one session's findings, and whether it was checked
|
|
279
|
+
honestweek problems --pattern cache-miss # one problem: its cause, fix, how sure, and timeline
|
|
280
|
+
honestweek problems --finding pf-abcdefghijkl # the same for one finding
|
|
281
|
+
honestweek goals # your goals and the sessions behind each one
|
|
234
282
|
```
|
|
235
283
|
|
|
236
|
-
|
|
284
|
+
A session id can be the one these commands print, the id in the session's own log (a Claude Code session id or a Codex thread id), or the first eight characters or more of either. When a start fits more than one session, the answer lists them and asks for more. `problems --session` says whether the checks read that session at all (they read only your configured repositories, never a display-only one), and when they read it and found nothing, it says that in one line, then how many patterns no check looks for in any session yet. A pattern's priority there is still the whole window's, and it says so.
|
|
237
285
|
|
|
238
|
-
|
|
286
|
+
`problems --pattern` answers four questions about one problem at once: what caused it, how to fix it, how sure honestweek is, and when it happened. It takes a pattern's id, its name, or a piece only that pattern has. Its cause is honestweek's general description of the pattern, labelled as general, then what your log shows: each finding's note and the steps its check recorded, with how each is known, and never a reason the log doesn't record. Its fix is the general fixes, the ready-made one you can copy, how to test it, and any tests of it already in the window; nothing is applied for you. How sure says how each finding is known, how established the pattern is, what can set the check off wrongly and where it comes from, and plainly that how often each check is right hasn't been measured yet, so there's no confidence number. Its timeline is every finding in the window in time order, each with a link that opens the replay zoomed to it, and the count per day. `--finding` gives the same for one finding. For "last week", ask with `--days 7`.
|
|
239
287
|
|
|
240
|
-
The
|
|
288
|
+
With Save results between runs on, `problems --session` also answers for a session outside the dates, from what `view` saved: by its id, the start of its id, or its log's full id (honestweek keeps only a hash of that, so its first characters alone don't find a saved session). The answer says when the results were saved, by which honestweek version, and whether the session's log is still on disk, and each finding keeps the evidence word it had then. It has no priority, since there's no window to rank it in, and no page to open.
|
|
241
289
|
|
|
242
|
-
|
|
243
|
-
- `goals` takes a goal record: a JSON list of goals plus the log of changes made to it (a separate input from the goals page's registry above). For each goal it lists the sessions that did its work and every reason each one counts: the record cites the session or one of its pull requests or commits, a tool call wrote one of the goal's entries while the record accepted it, a command acted on a cited pull request, or a prompt named the goal. Whatever the record cites that no session matches is listed with the reason.
|
|
290
|
+
Each reads the same week `view` does: the config honestweek finds, and the dates `--days`, `--from` with `--to`, or the config's "history" name. Add `--demo` to try any of them on the made-up week, with nothing set up. Every answer is redacted the way the page shows it with Show private text off, and no option shows private text: the page's switch is still the only way, and it's yours. Every row keeps its evidence word (recorded, derived, inferred, missing or ambiguous), so an inferred link never reads as a recorded one. Text copied from your logs or your goal list, and a step's description or a finding's note that carries it, is marked, so an agent can tell it from honestweek's own words and treat it as data: in JSON it sits inside `{"quoted": "..."}`, and in text it's in double quotes or on a line that starts with `>`. A text answer that found something ends with a command to try next, written the way you ran this one. Each session, step, finding and goal also names its page on `view` (`page` in JSON, such as `replay.html?session=<id>`), and a text answer's "Open it on the page" line is the `view --page` command that opens it on the same dates, since a thread's id can change with them; add any `--config` or `--goals` you gave. They write nothing to disk, except that `--demo` builds its made-up week in a temporary folder and deletes it before it exits.
|
|
244
291
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
node tools/replay-inspect.mjs --demo goals
|
|
249
|
-
node tools/replay-inspect.mjs --demo lookup '#7'
|
|
250
|
-
node tools/replay-inspect.mjs --config honestweek.config.json --from 2024-06-10 --to 2024-06-16 --goals goals.json goals
|
|
251
|
-
```
|
|
292
|
+
## Replaying how the work happened (the engine underneath)
|
|
252
293
|
|
|
253
|
-
|
|
294
|
+
`honestweek view` runs on a work-history engine (`lib/replay/`) that rebuilds how work happened from the same local logs: prompts, the sub-agents an agent started, each command and its recorded result, tests, interruptions, and what git says happened to each commit. Every step says how it's known, and it never invents working time or reasons. It only reads, and it never runs git against a display-only repository. The commands above are its published face. A developer tool in a clone of this repository also prints the history level by level (`node tools/replay-inspect.mjs --demo walk`). [docs/work-history-engine.md](docs/work-history-engine.md) explains the event model, the lookups, how a session joins a goal, and what it can't reconstruct yet.
|
|
254
295
|
|
|
255
296
|
## The flow: an honest weekly summary
|
|
256
297
|
|
|
257
|
-
This turns a completed week of your AI coding **sessions** (each one conversation log) into
|
|
298
|
+
This turns a completed week of your AI coding **sessions** (each one conversation log) into a work summary that's honest, checked against git and private by default. It includes work you figured out but haven't shipped yet, which your commits can't show.
|
|
258
299
|
|
|
259
|
-
|
|
300
|
+
I ship it as a Claude Code skill (instructions Claude follows when you type `/honestweek`, or when you ask it in words for a weekly summary) that runs small Node scripts with no dependencies, all on your machine. It reads your AI coding session transcripts and distils a completed week into an honest summary you can share. It **re-derives every claim git can check against your real commits, or aborts**. Then it produces a draft *you* review and publish yourself. It never auto-publishes. Claude runs these steps in your own Claude Code session, so it sees what each one prints, and it reads the redacted draft (`honestweek.draft.json`) to write the summary. [Where your data goes](docs/where-your-data-goes.md) lists what that draft holds and what else Claude sees, such as the picks on a `page` or `site` and what `mine` prints.
|
|
260
301
|
|
|
261
302
|
End-to-end happy path, in order. Each step names the artifact it produces.
|
|
262
303
|
|
|
263
|
-
> Installed as the skill
|
|
304
|
+
> Installed as the skill or plugin? Just run `/honestweek` (`/honestweek:honestweek` with the plugin), or ask Claude for a weekly summary: Claude drives these steps for you and resolves the CLI path automatically. It starts by running `honestweek status`, which reads the step files and says where the week stands and what to run next, so it picks up where you left off. You can run it yourself too; it writes nothing and always exits 0. To go straight to another flow, add its name after the command: `client 2026-09-01 2026-09-30`, `mine` or `view`. The commands below write `honestweek`; with `npx` or from a clone, use the form under [Try it](#try-it).
|
|
264
305
|
|
|
265
|
-
1. **`init`** → writes `honestweek.config.json`, inferred from your git state (your `git config user.email` plus the nearby git repos it finds), for you to review. If it finds no repositories, it writes nothing and says where to run it instead. It also drops `honestweek.config.example.json` if one isn't present.
|
|
306
|
+
1. **`init`** → writes `honestweek.config.json`, inferred from your git state (your `git config user.email` plus the nearby git repos it finds), for you to review. If it finds no repositories, it writes nothing and says where to run it instead. It also drops `honestweek.config.example.json` if one isn't present. If git doesn't know your email, it asks for it. If a repository it found holds a folder your config marks display-only, or sits inside one, it offers to mark that repository display-only too instead of stopping. It asks you to confirm twice before it writes, and accepting the defaults gives you a valid config. Between the two, it asks for the names and client words to keep private, which go under `redaction`. You can skip the names, the client words or both. Either way it adds the config to `.gitignore`, since the config holds your email and folder paths too. Before the second confirmation, it shows a short summary of what the file will say. Run again over an existing config it can read, it keeps that config's private words (its `redaction` lists and `neverPublicTerms`) and any display-only folder its search doesn't list, so a rewrite doesn't stop hiding a word or forget a folder you marked display-only. If the config there can't be read, it stops before running git anywhere, says why and writes nothing, since it can't tell which folders that config marked display-only.
|
|
266
307
|
```bash
|
|
267
|
-
|
|
308
|
+
honestweek init
|
|
268
309
|
```
|
|
269
310
|
Those questions need someone to answer them. Answers piped in on stdin work, one per line. In a script, in CI, or from an agent's shell where stdin ends before the last answer, `init` exits `2` rather than writing a config you never approved, and tells you to accept the inferred defaults instead:
|
|
270
311
|
```bash
|
|
271
|
-
|
|
312
|
+
honestweek init --yes
|
|
272
313
|
```
|
|
273
|
-
`--yes` leaves an existing `honestweek.config.json` untouched; add `--force` to overwrite it.
|
|
274
|
-
|
|
314
|
+
`--yes` leaves an existing `honestweek.config.json` untouched; add `--force` to overwrite it. One that can't be read stops `init` with exit 1 either way, before it runs git.
|
|
315
|
+
To set it up once for every folder, add `--user`: it still looks for repositories where you run it, and writes `~/.honestweek/honestweek.config.json` instead (`--config <file>` names another place, a file called `honestweek.config.json`).
|
|
275
316
|
```bash
|
|
276
|
-
|
|
317
|
+
honestweek init --user
|
|
277
318
|
```
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
319
|
+
2. **`discover`** → scans the **last completed week's** sessions **and session-end handoffs** (the `.claude/handoffs/*.md` notes) from your allowlisted repos. It reads handoffs only for `featured` and `reference` repos, and never reads one from a `display` repo. It writes the **redacted** result to `honestweek.draft.json`, which is gitignored. From each handoff it adds a bounded amount of extra material: its tagged claims, reversals and cited commits. It's deterministic, with no model call.
|
|
320
|
+
```bash
|
|
321
|
+
honestweek discover # or: discover --week 2024-W23
|
|
322
|
+
```
|
|
323
|
+
3. **`/honestweek`** (the skill) → **distils** the draft into the human-reviewable `honestweek.items.json`, with a status badge **and** a receipt on every item. This is the one model-judgment step; see [`SKILL.md`](SKILL.md) for the distillation contract. With the plugin, Claude hands it to a distiller that has file tools only, no shell or web, and none of your CLAUDE.md instructions, with the contract loaded, so a line in your session logs written to steer an agent can't make it run a command or open a page. It can still write files, and it's told to write only the items file. With the plugin, the contract is also set to load whenever Claude works with `honestweek.items.json`.
|
|
324
|
+
If your output is `page` or `site` and you don't use the optional goals registry (`honestweek.objectives.json`), run `honestweek digest prepare` too. It reads the finished week's Claude Code and Codex sessions, picks a short list of prompts, ideas, techniques, decisions, reversals and next steps, each linked to the session it came from, and writes the ones that pass the privacy check to `honestweek.prompt-items.json`. `digest candidates` and `digest explain <item-ref>` show why each one was picked. `digest keep`, `hide` and `delete <item-ref> --yes` change what goes in. They change the selection only and never bypass the receipt or privacy gates. Then you run `validate` and `build`. A deleted item leaves a no-text tombstone (a marker with no text in it) so the next `prepare` doesn't pick it again. Deleting cannot recall an output you've already built. The balanced digest and the goals page don't work together yet, so with a goals registry, use the distillation step above. [docs/digest.md](docs/digest.md) has the rest: the hold on high-risk items, carrying unresolved items into later weeks, and recovering an interrupted build.
|
|
284
325
|
> Optional but recommended: gate the distilled items before building:
|
|
285
326
|
> ```bash
|
|
286
|
-
>
|
|
327
|
+
> honestweek validate # add --no-dashes for the voice rule
|
|
287
328
|
> ```
|
|
288
|
-
> `validate` exits `2` if any item
|
|
289
|
-
4. **`build`** → re-derives and **git-verifies every cited commit**. It **aborts with exit code `2`** if any cited commit is unresolved or its `authorEmail` is not in `identity.authorEmails
|
|
329
|
+
> `validate` exits `2` if any item has a status that isn't one of the three badges, lacks a receipt, **names a `display`-role repo or cites a commit against one**, or lets a configured redaction term survive into the prose. It catches an authoring leak at the source instead of relying on build-time scrubbing.
|
|
330
|
+
4. **`build`** → re-derives and **git-verifies every cited commit**. It **aborts with exit code `2`** if any cited commit is unresolved or its `authorEmail` is not in `identity.authorEmails`. It writes nothing rather than emit a half-true summary. A `shipped` badge also requires every cited commit to have **landed**: reachable from the repo's default branch (origin/HEAD as recorded locally, else `main`/`master`, else the repo's only branch), checked offline from local refs, never a fetch. Real work still on an unmerged branch keeps its receipt, but `build` downgrades it to `in progress` and says so on stderr. If `build` can't work out the repo's default branch, it can't verify the `shipped` claim, so it aborts (exit `2`).
|
|
290
331
|
```bash
|
|
291
|
-
|
|
332
|
+
honestweek build
|
|
292
333
|
```
|
|
293
|
-
5. **emit** → on success, `build` renders the final **local** output in the configured `output.mode` (`post` / `changelog` / `digest` / `report` / `page` / `site`) to `output.file`. The `digest` carries a git-derived **Activity** summary (commits and active days for `featured`/`reference` repos; `display` repos are never git-read, so they get no metrics, and an unreadable repo gets no fabricated `0`). `page` renders a self-contained, interactive HTML **standalone site** (see below). You review it and publish it yourself.
|
|
294
|
-
6. **`preview`** (optional) → serves the built `output.file` on a local-only `127.0.0.1` server, then opens your browser. A Markdown output is converted to a locked-down HTML page; the `page` output is already HTML and is served verbatim (with its inline interactivity). It is a viewer: it reads the file `build` wrote, publishes nothing, and needs no internet. Press Ctrl+C to stop.
|
|
334
|
+
5. **emit** → on success, `build` renders the final **local** output in the configured `output.mode` (`post` / `changelog` / `digest` / `report` / `page` / `site` / `client`) to `output.file`. The `digest` carries a git-derived **Activity** summary (commits and active days for `featured`/`reference` repos; `display` repos are never git-read, so they get no metrics, and an unreadable repo gets no fabricated `0`). `page` renders a self-contained, interactive HTML **standalone site** (see below). You review it and publish it yourself.
|
|
335
|
+
6. **`preview`** (optional) → serves the built `output.file` on a local-only `127.0.0.1` server, then opens your browser. A Markdown output is converted to a locked-down HTML page; the `page` output is already HTML and is served verbatim (with its inline interactivity). It is a viewer: it reads the file `build` wrote, publishes nothing, and needs no internet. Press Ctrl+C to stop it, or it stops on its own after 30 minutes with no visits.
|
|
295
336
|
```bash
|
|
296
|
-
|
|
337
|
+
honestweek preview # add --no-open to just print the URL, or --port <n>
|
|
297
338
|
```
|
|
298
339
|
|
|
299
340
|
## Mining solved problems worth publishing (`mine`)
|
|
@@ -304,33 +345,33 @@ The weekly flow above answers "what did I ship". `mine` answers a different ques
|
|
|
304
345
|
Not every hard hour is worth writing up. When your own code breaks and you fix your own
|
|
305
346
|
code, nobody else can use that. But when a tool *you did not write* fails in your
|
|
306
347
|
environment and you work out why, someone else will hit the same wall and paste the same
|
|
307
|
-
error into a search box. That second kind is rare
|
|
308
|
-
logs, and it
|
|
348
|
+
error into a search box. That second kind is rare. It's already sitting in your session
|
|
349
|
+
logs, and it's almost never written down.
|
|
309
350
|
|
|
310
|
-
`mine` finds those
|
|
351
|
+
`mine` finds those and ranks them. With `--draft`, it also writes one up.
|
|
311
352
|
|
|
312
353
|
```bash
|
|
313
|
-
|
|
314
|
-
|
|
354
|
+
honestweek mine # report what is undecided
|
|
355
|
+
honestweek mine --draft # and write the top one up as a post
|
|
315
356
|
```
|
|
316
357
|
|
|
317
358
|
**What it reads.** Claude Code (`~/.claude/projects`), Codex (`~/.codex/sessions`) and
|
|
318
359
|
Cowork session logs. Pick with `--corpus claude-code,codex,cowork`. A name outside that
|
|
319
|
-
list
|
|
360
|
+
list stops with an error (exit 1) instead of scanning nothing, because a typo must never read as a quiet week.
|
|
320
361
|
|
|
321
362
|
**How it decides.** A session is a candidate only when all three hold:
|
|
322
363
|
|
|
323
364
|
| Requirement | Why |
|
|
324
365
|
| --- | --- |
|
|
325
|
-
| A quotable error from software you
|
|
366
|
+
| A quotable error from software you didn't write | It's what a stranger types into a search box. It leaves out errors from your own compiler, test runner or git. |
|
|
326
367
|
| Diagnosis outside your working tree | Probing the machine, reading another program's install directory, or researching a third party's known behaviour. |
|
|
327
368
|
| Evidence it was resolved | An unresolved failure is a bug report, not a guide. |
|
|
328
369
|
|
|
329
|
-
|
|
330
|
-
however good it looks otherwise. That
|
|
370
|
+
`mine` rejects a session that edited your repo far more than it investigated anything else,
|
|
371
|
+
however good it looks otherwise. That's ordinary work.
|
|
331
372
|
|
|
332
373
|
**The ledger.** Findings land in `honestweek.findings.json` with a status. The number
|
|
333
|
-
that matters is the **backlog
|
|
374
|
+
that matters is the **backlog**, the findings you haven't accepted or declined yet:
|
|
334
375
|
|
|
335
376
|
```text
|
|
336
377
|
ERROR SIGNAL — backlog 3 undecided; oldest waiting 12 day(s).
|
|
@@ -340,19 +381,19 @@ ERROR SIGNAL — backlog 3 undecided; oldest waiting 12 day(s).
|
|
|
340
381
|
reached a reader, and it can only fall when **you** decide:
|
|
341
382
|
|
|
342
383
|
```bash
|
|
343
|
-
|
|
384
|
+
honestweek mine --decide "<finding key>=published" # or =declined
|
|
344
385
|
```
|
|
345
386
|
|
|
346
387
|
**Drafts are honest by construction.** A draft asserts nothing about today. Its
|
|
347
|
-
last-verified field is
|
|
388
|
+
last-verified field is **empty**, its publication date is blank, and it
|
|
348
389
|
carries a checklist where every item starts `UNVERIFIED`, plus a "What I could not
|
|
349
|
-
check" section.
|
|
390
|
+
check" section. That section always lists two things a session log can never establish:
|
|
350
391
|
whether anyone actually searches for this, and whether the fix still works on the
|
|
351
392
|
current build. `mine` never publishes anything.
|
|
352
393
|
|
|
353
|
-
**When it
|
|
394
|
+
**When it's blind, it says so.** Every run reports the files it found in each log source and the
|
|
354
395
|
retention floor: the oldest session still on disk, since agents delete old logs. If a
|
|
355
|
-
|
|
396
|
+
log source points to a real directory that holds zero logs, `mine` **exits `2`**. A zero from
|
|
356
397
|
a blind sensor is not evidence of a quiet week.
|
|
357
398
|
|
|
358
399
|
Configure the destination under `mine` in your config (all optional):
|
|
@@ -371,15 +412,18 @@ Configure the destination under `mine` in your config (all optional):
|
|
|
371
412
|
}
|
|
372
413
|
```
|
|
373
414
|
|
|
374
|
-
`draft.frontmatter`
|
|
375
|
-
|
|
376
|
-
|
|
415
|
+
`draft.frontmatter` lists your destination's fields, not honestweek's. Of the keys it recognises,
|
|
416
|
+
it fills in `title` and `tags` (your schema's own tags, or `bug-fix`), and leaves `description`
|
|
417
|
+
and `date` empty with a note saying when to fill each in. A publish-status field (`draft`,
|
|
418
|
+
`published`, `public` or `live`) is always set to not published, and any other key it doesn't
|
|
419
|
+
recognise is kept, empty, for you. `ownRepos` stops
|
|
420
|
+
issues on your own repositories from counting as evidence that someone else's software broke.
|
|
377
421
|
honestweek reads the GitHub remote of each configured repository for this, except `display`
|
|
378
|
-
repositories, which it never runs `git` against
|
|
422
|
+
repositories, which it never runs `git` against. List their `owner/name` under `ownRepos` if
|
|
379
423
|
issues there should count as yours.
|
|
380
424
|
|
|
381
|
-
|
|
382
|
-
|
|
425
|
+
[`docs/mining.md`](docs/mining.md) covers the detector's signals, what it measures and what it
|
|
426
|
+
guesses at, and how I calibrated the score bar.
|
|
383
427
|
|
|
384
428
|
## Sample output
|
|
385
429
|
|
|
@@ -405,7 +449,7 @@ A short, fabricated (clean-room) example. The distilled `honestweek.items.json`:
|
|
|
405
449
|
}
|
|
406
450
|
```
|
|
407
451
|
|
|
408
|
-
|
|
452
|
+
Here's part of what the default `digest` output renders from it, leaving out its opening note and Activity summary. Every line carries a status badge and a receipt:
|
|
409
453
|
|
|
410
454
|
```markdown
|
|
411
455
|
# Weekly digest — 2024-06-10 to 2024-06-16
|
|
@@ -420,45 +464,45 @@ Rendered to the default `digest` output. Every line carries a status badge and a
|
|
|
420
464
|
## Standalone site (`page` mode)
|
|
421
465
|
|
|
422
466
|
Set `"output": { "mode": "page" }` and `build` writes one self-contained, interactive
|
|
423
|
-
HTML file (`honestweek.report.html` by default)
|
|
424
|
-
|
|
425
|
-
|
|
467
|
+
HTML file (`honestweek.report.html` by default). It's a **standalone site** with a
|
|
468
|
+
chart of commits per day from git, a collapsible card for each project with its metrics, items with
|
|
469
|
+
their status badges, and an expandable git receipt on each. No target project, no framework, no build
|
|
426
470
|
step, and **zero external resources** (inline CSS + JS, system fonts), so it opens
|
|
427
|
-
anywhere and `preview` can serve it under a no-egress CSP:
|
|
471
|
+
anywhere, and `preview` can serve it under a no-egress CSP (a browser rule that blocks loading anything from another site):
|
|
428
472
|
|
|
429
473
|
```bash
|
|
430
|
-
|
|
431
|
-
|
|
474
|
+
honestweek build # writes honestweek.report.html
|
|
475
|
+
honestweek preview # serves it on 127.0.0.1 + opens your browser
|
|
432
476
|
```
|
|
433
477
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
and
|
|
437
|
-
`max(commit-active days, session-active days, entry-active days)
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
file (the integrated path), use `site` mode with a
|
|
448
|
-
`docs/site-integration.md
|
|
478
|
+
It runs on the same honesty engine as every other mode. Every cited commit is checked against git,
|
|
479
|
+
and one that fails stops the build. honestweek works out every number on the page itself, the same
|
|
480
|
+
way every time, using git for the commits and the chart. Curated prose is HTML-escaped.
|
|
481
|
+
A project card's **active-days** is `max(commit-active days, session-active days, entry-active days)`:
|
|
482
|
+
the largest of its days with commits, days with sessions and days with entries, though entry days count only once it has a day with commits or sessions. So a `display`-role or
|
|
483
|
+
session-only project shows the days it really had interactive sessions instead of a blank. Those
|
|
484
|
+
days are counted from your local session logs, never authored. A card's header can never show fewer
|
|
485
|
+
active days than the dated rows under it. That holds even when a session ran in one project's folder
|
|
486
|
+
but its work was filed under another project because of its content. In `site` mode, for a `display`-role or session-only project with a session, the same
|
|
487
|
+
adjustment keeps the header's "sessions this week" from falling below that number of active days.
|
|
488
|
+
A session happens on one day, so N active days mean at least N sessions. For a project whose
|
|
489
|
+
sessions ran from more than one folder, that adjusted figure is a lower bound on how many distinct
|
|
490
|
+
days it had sessions, not a raw count of session logs. Every figure is a count, never authored.
|
|
491
|
+
To write into an existing website's data file instead (the integrated path), use `site` mode with a
|
|
492
|
+
committed `output.adapter`, as `docs/site-integration.md` explains.
|
|
449
493
|
|
|
450
494
|
### A goals page too (opt-in, multi-page)
|
|
451
495
|
|
|
452
496
|
Drop a `honestweek.objectives.json` registry beside your config and `page` mode becomes
|
|
453
|
-
**multi-page**: it emits a second self-contained page, `goals.html`, next to `report.html`
|
|
497
|
+
**multi-page**: it emits a second self-contained page, `goals.html`, next to the report (`honestweek.report.html` by default)
|
|
454
498
|
and cross-links the two. The goals page groups your verified work **by goal** instead of by
|
|
455
|
-
project
|
|
456
|
-
counts, and an expandable list of the entries behind
|
|
457
|
-
mode stays single-page exactly as above
|
|
499
|
+
project. Each goal gets a card with a tag for its kind, a what / why / how, a per-week activity strip, status
|
|
500
|
+
counts, and an expandable list of the entries behind it. With **no** registry, nothing changes: `page`
|
|
501
|
+
mode stays single-page, exactly as above.
|
|
458
502
|
|
|
459
|
-
The registry
|
|
460
|
-
to no goal
|
|
461
|
-
|
|
503
|
+
The registry decides which goals get published. Only goals listed in it appear, and a work item that maps
|
|
504
|
+
to no goal stays off the page. honestweek checks the registry before it writes anything. An invalid
|
|
505
|
+
registry, or one holding text the redactor would change, stops the whole build, and neither page is written.
|
|
462
506
|
|
|
463
507
|
```jsonc
|
|
464
508
|
// honestweek.objectives.json (opt-in; absent -> single-page)
|
|
@@ -482,57 +526,70 @@ leaky registry aborts the whole build, writing neither page).
|
|
|
482
526
|
}
|
|
483
527
|
```
|
|
484
528
|
|
|
485
|
-
A work item
|
|
486
|
-
`projectToObjective[<its repo label>]`.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
529
|
+
A work item finds its goal by its own `objectiveId`, if it has one that's in the registry. If not, it
|
|
530
|
+
uses `projectToObjective[<its repo label>]`. A goal's activity across weeks adds up the current week
|
|
531
|
+
and any weeks in your local `output.archive`, so a first run shows one week, and more as weeks
|
|
532
|
+
go by. An optional `honestweek.goal-changelog.json` adds a "what changed" band for
|
|
533
|
+
changes to the set of goals itself: a goal added, split, retired, relabeled or merged.
|
|
490
534
|
|
|
491
535
|
`preview` serves **both** pages (so the cross-links resolve), still loopback-only under the
|
|
492
536
|
same no-external-egress CSP:
|
|
493
537
|
|
|
494
538
|
```bash
|
|
495
|
-
|
|
496
|
-
|
|
539
|
+
honestweek build # writes honestweek.report.html + goals.html (when the registry is present)
|
|
540
|
+
honestweek preview # serves both at 127.0.0.1 (/ and /goals.html)
|
|
497
541
|
```
|
|
498
542
|
|
|
499
543
|
## A report for a client (`client` mode)
|
|
500
544
|
|
|
501
545
|
A weekly log is for you. A client report is for the person paying for the work: what you did for them over a period you choose (a sprint, a month, the contract so far), in their words, with the evidence attached. It's one light, printable HTML file (`honestweek.client.html` by default) they can read in a browser or save as a PDF.
|
|
502
546
|
|
|
503
|
-
It keeps every guarantee the weekly modes have. Every change in it names the pull requests it came from,
|
|
547
|
+
It keeps every guarantee the weekly modes have. Every change in it names the pull requests it came from, or its commit when there's no pull request. Every cited commit is checked against git, and one that fails stops the build. A commit has to be yours and on the default branch to count as merged, and a cited commit dated outside the period also stops the build. The numbers at the top (pull requests merged, commits on the main branch, days with work landed) and the activity chart come from git. If a repo can't be read, the numbers at the top stay blank rather than show one that's too low. An appendix lists every pull request of yours that landed in the period and marks the ones the report describes, so nothing is quietly left out.
|
|
504
548
|
|
|
505
549
|
The source is what reached the default branch, not a week of session logs:
|
|
506
550
|
|
|
507
|
-
1. Add a `client` block to the config
|
|
551
|
+
1. Add a `client` block to the config and set `"output": { "mode": "client" }`. The block names the client. It can also say who the report is for and who it's from, and give link prefixes that turn PR numbers into links. Use a separate folder and config for each client.
|
|
508
552
|
2. List what landed in the period. This writes the gitignored `honestweek.history.json` and prints only counts:
|
|
509
553
|
```bash
|
|
510
|
-
|
|
554
|
+
honestweek history --from 2026-04-01 --to 2026-06-30
|
|
511
555
|
```
|
|
512
|
-
3. Distil it into `honestweek.items.json` (the skill does this)
|
|
556
|
+
3. Distil it into `honestweek.items.json` (the skill does this). The file holds a `period` with the same dates and a `content` block: a `title`, a one-sentence `headline`, `summary` paragraphs, the `themes` the work falls into, and optional `next` steps, which show as planned and are never counted. It also holds one item per meaningful change, each with a `theme`, a `title` and `summary` written for the client, a status, and `commits` citing the squash-merge commits it came from. Mark the few that matter most with `"highlight": true`.
|
|
513
557
|
4. `validate`, `build`, and `preview` as usual. Put anything the client must never see (billing, other clients) in `redaction.terms` so `validate` stops it at the source.
|
|
514
558
|
|
|
515
559
|
In a client report, `shipped` reads as **Merged**: on the main branch and checked against git. It doesn't claim the change has been released to production, and the report says so.
|
|
516
560
|
|
|
517
561
|
### Shaping it for the reader (reader profiles)
|
|
518
562
|
|
|
519
|
-
Different readers want different things from the same report. An optional `honestweek.reader.json` beside the config describes the
|
|
563
|
+
Different readers want different things from the same report. An optional `honestweek.reader.json` beside the config describes the reader this report is for. It sets which sections come first, adds sections that gather the changes they care about, names areas to leave out, and says whether to also write a short note for wherever they read updates. It never changes a fact. Every view shows the same entries, statuses and counts, an area it leaves out is still counted on the page, and the full record and "how this report was made" are always there.
|
|
520
564
|
|
|
521
|
-
- An extra section picks its changes
|
|
565
|
+
- An extra section picks its changes in one of two ways. **By git**, it uses the issue numbers named in the commit messages (`"select": { "issues": [12, 14] }`). **By hand**, it uses tags on items (`"select": { "tags": ["requested"] }`). The page says which.
|
|
522
566
|
- Every section and every line of writing guidance says where it came from: `their-words`, `your-notes` (both with a `ref`), or `guess`. If everything in the file is a guess, `build` tells you the view is unconfirmed.
|
|
523
567
|
- `"format": { "note": true }` also writes `<report>.note.md`: the headline, the reader's sections and what's next, in a few lines, pointing to the full report.
|
|
524
|
-
-
|
|
568
|
+
- If a profile asks for something it can't honestly do, the build fails instead. That covers redefining "done", unknown keys, a missing source, excluding an area that doesn't exist, and an item tag no section picks.
|
|
525
569
|
|
|
526
|
-
Without the file, the report uses the
|
|
570
|
+
Without the file, the report uses the default and client profiles that ship with honestweek. [docs/reader-profiles.md](docs/reader-profiles.md) has the design and its rules.
|
|
527
571
|
|
|
528
572
|
## Config reference
|
|
529
573
|
|
|
530
|
-
|
|
574
|
+
### Where honestweek finds your config
|
|
575
|
+
|
|
576
|
+
Every command reads the first config it finds:
|
|
577
|
+
|
|
578
|
+
1. the file `--config <file>` names, which every command takes;
|
|
579
|
+
2. `honestweek.config.json` in the folder you run it from;
|
|
580
|
+
3. the file the `HONESTWEEK_CONFIG` environment variable names;
|
|
581
|
+
4. `~/.honestweek/honestweek.config.json`, the every-folder config that `init --user` and Setup's "Every folder" write.
|
|
582
|
+
|
|
583
|
+
A config in the folder you run from always wins, so a setup you already have reads exactly what it did. A file that `--config` or `HONESTWEEK_CONFIG` names but that isn't there is an error, never a quiet switch to another config. Each command names the config it read in one line on stderr. The files a command writes (the draft, the items, the sidecars, the output) go beside that config, not in the folder you ran it from, so running `discover` from an unrelated project never drops a draft there, and the `.gitignore` lines go beside it too. Settings changes the config `view` read, in its own folder, as long as it's called `honestweek.config.json`.
|
|
584
|
+
|
|
585
|
+
### The file
|
|
586
|
+
|
|
587
|
+
Your `honestweek.config.json` follows the shape of `honestweek.config.example.json`. `init`, Setup and Settings add it to `.gitignore`, because it holds your email, your folder paths and the words you want hidden. Adding a file to `.gitignore` doesn't remove it from git if it was committed before; if yours was, run `git rm --cached honestweek.config.json`. If you do want it committed, add it once with `git add -f honestweek.config.json`: git keeps tracking it, and Settings puts the `.gitignore` line back if you remove it. Here's what it looks like:
|
|
531
588
|
|
|
532
589
|
```jsonc
|
|
533
590
|
{
|
|
534
591
|
"identity": { "authorEmails": ["you@example.com"] }, // required, non-empty; the commit-authorship allowlist
|
|
535
|
-
"week": { "startsOn": "monday", "timezone": "UTC" }, // optional; startsOn is "monday"
|
|
592
|
+
"week": { "startsOn": "monday", "timezone": "UTC" }, // optional; startsOn is "monday" (the only supported value); timezone is an IANA zone (defaults to the host zone)
|
|
536
593
|
"repos": [ // required, non-empty
|
|
537
594
|
{ "path": "/path/to/your/repo", "label": "your-project", "role": "featured" },
|
|
538
595
|
{ "path": "~/code/a-repo-you-contribute-to", "label": "a-shared-repo", "role": "reference" },
|
|
@@ -551,29 +608,30 @@ Your `honestweek.config.json` mirrors `honestweek.config.example.json`. Whether
|
|
|
551
608
|
| Field | Meaning |
|
|
552
609
|
| --- | --- |
|
|
553
610
|
| `identity.authorEmails` | The emails a commit must be authored by to count as yours. `build` aborts on any cited commit not authored by one of these. |
|
|
554
|
-
| `week.startsOn` | `"monday"` (the only supported value
|
|
611
|
+
| `week.startsOn` | `"monday"` (the only supported value). |
|
|
555
612
|
| `week.timezone` | IANA timezone used to compute the week boundary; defaults to your host zone. |
|
|
556
|
-
| `repos[].path` | A repo path. `~`/`~/` expands to your home dir
|
|
613
|
+
| `repos[].path` | A repo path. `~`/`~/` expands to your home dir, and relative paths resolve against the config file. A session counts toward this repo when it ran in **any working tree of the same git repository**: the path itself, its sub-directories, and every `git worktree`, including one checked out at a sibling path rather than inside it. Git reads (commits, handoffs, metrics) always use this path alone, so your commit counts never rest on a worktree's branch or detached `HEAD`. A separate *clone* has its own git database, so its sessions never count here. |
|
|
557
614
|
| `repos[].label` | The short name items reference and outputs display. |
|
|
558
615
|
| `repos[].role` | One of the three trust levels below. |
|
|
559
|
-
| `redaction.codenames` / `names` / `terms` | Private
|
|
560
|
-
| `curation.*` |
|
|
561
|
-
| `privacy.publicRenditions.*` |
|
|
562
|
-
| `output.mode` | `post` (build-in-public update), `changelog` (
|
|
616
|
+
| `redaction.codenames` / `names` / `terms` | Private terms scrubbed from all output, in any letter case. honestweek finds a term as a word, after an underscore or a digit, or as one part of a camel-case name (`acme_report`, `AcmeReport`, `XMLAcmeThing`). When part of a web address or file name starts with a codename or term of four or more letters, it replaces that whole part (`www.acmehq.com`, `http://acmehq:3000`, `acmereport.pdf`). It matches a person's name that way only in a web address, so "Bill" leaves `billing.ts` alone. A word that only shares letters with a term (`academy`) is kept. All three are empty by default (clean-room). |
|
|
617
|
+
| `curation.*` | How the weekly digest picks its items, on your machine. By default it aims for 12 items, with at most 2 prompts, 2 ideas, 3 techniques, 2 decisions, 1 reversal and 2 next steps. The automatic floor, the lowest score an item can have and still be picked without you keeping it, is 2. `automaticCarryWeeks` defaults to 2 and can't go above 2. `retentionWeeks` defaults to 12 and can't go above 12. Items you keep yourself and one-week renewals are never silently dropped, but they never bypass receipt or privacy gates. |
|
|
618
|
+
| `privacy.publicRenditions.*` | The check that decides which redacted digest items can go public without asking you. `enabled` defaults to true for the local artifact. `maxAutomaticChangedPercent` defaults to 20 and can't go higher: if redaction changed more of an item's text than that, the item needs your approval. `neverPublicTerms` adds terms to hard redaction. `generalizationMappings` must stay empty, since this version doesn't support it yet. Anything ambiguous or still high-risk after redaction stays private, whatever its category. |
|
|
619
|
+
| `output.mode` | `post` (a build-in-public update), `changelog` (a section for the repo's own `CHANGELOG.md`), `digest` (the default: a private Markdown file that stays on your machine, with every item grouped by status, each with its badge and receipt), `report` (items grouped by project, each under its metrics from git, shaped like a structured weekly work log and still a local file you publish yourself), `site` (an advanced mode that writes the verified report into a target website's data file through a committed adapter, as [docs/site-integration.md](docs/site-integration.md) explains), or `client` (a printable report of the work you did for one client over the items file's `period`, covered in [A report for a client](#a-report-for-a-client-client-mode)). |
|
|
563
620
|
| `output.file` | Where the output is written. Defaults per mode when unset. (Not used by `site`, whose write path comes from the adapter.) |
|
|
564
|
-
| `output.adapter` | **Required for `site` mode only
|
|
565
|
-
| `output.redact` |
|
|
566
|
-
| `output.skipProgramSessions` |
|
|
567
|
-
| `output.archive` / `output.archiveDir` |
|
|
621
|
+
| `output.adapter` | **Required for `site` mode only.** The path to the committed adapter, resolved like a repo path. It's either a `.json` *static* field-map or, for a data file that needs grouping, sorting or joins, a `.mjs` *transform* (`transform(model, ctx)`). It maps the verified report onto the site's data file, and it holds that file's write path too. |
|
|
622
|
+
| `output.redact` | Defaults to `true`: honestweek scrubs every byte. In `site` mode only, `false` hands string redaction to the committed transform, so a site with its own redactor gets placeholders that exactly match its own. That's allowed **only with a transform adapter**. Either way, the build still verifies every cited commit or stops, and the numeric fact-fence (the check that every number in the output is one honestweek verified) always runs. See [docs/site-integration.md](docs/site-integration.md). |
|
|
623
|
+
| `output.skipProgramSessions` | Defaults to `true`. In `page` and `site` modes, the interactive-session count leaves out a Claude Code session that a program, a background task or another session opened and that has no turn from you. If you sent it a turn later, it counts from your first turn, on that turn's day, the way the rest of honestweek reads a program's turns. Current Claude Code marks who sent each turn (`turnOrigin`: `human` when it came from your own session, typed or pasted). Older logs don't, so they count as before. Set it to `false` to count the old way. If you publish this count, it changes starting with 0.2.0 wherever your logs record `turnOrigin`. See [docs/site-integration.md](docs/site-integration.md). |
|
|
624
|
+
| `output.archive` / `output.archiveDir` | An opt-in weekly archive on your machine. With `archive: true`, `build` also saves a snapshot of each week to `<archiveDir>/<weekStart>.json` and keeps `<archiveDir>/index.json` up to date, a local version of a "/log" series of past weekly reports. It doesn't in `site` or `client` mode. The folder defaults to `honestweek.archive`. These are local files only, never pushed. |
|
|
568
625
|
| `client.name` | **Required for `client` mode.** The client or product the report covers. |
|
|
569
626
|
| `client.preparedFor` / `preparedBy` / `organization` | Optional lines for the report's header: who it's for, who wrote it, and the business it comes from. |
|
|
570
627
|
| `client.prLinks` | Optional map of repo label to an https prefix (`https://github.com/your-org/your-project/pull/`), so a PR number derived from a verified commit becomes a link. Every key must be a configured repo label. |
|
|
571
|
-
| `voice.denyMeta` |
|
|
572
|
-
| `history` | Optional. How far back `view` reads with no `--days`, `--from` or `--to`: `{ "days": 30 }`, `{ "from": "2025-01-01" }`, a range in the past `{ "from": "2025-01-01", "to": "2025-03-31" }`, or `{ "all": true }`. The last 7 days or fewer always load whole. A longer choice loads at most the newest `historyLimitMB` of logs and says which days it loaded when that cuts it short. Leave it out for the last 7 days. Setup and Settings write it. |
|
|
573
|
-
| `historyLimitMB` | Optional.
|
|
628
|
+
| `voice.denyMeta` | An opt-in honesty check on authored prose, **OFF by default**. When `true`, `build` stops (exit 2, writes nothing) if an authored-prose field (an item's `title`/`summary`/`text`, or curated `content`/`projects` prose) *narrates what it's holding back* ("keeping the specifics sealed", "kept generic here", "not public-facing") or *announces the page's own honesty* ("show the work honestly, receipts and retractions included", "belongs in an honest log"). An honest log should show that through its badges and receipts, not say it about itself. It does for prose what the numeric fact-fence does for numbers, and it names each field it flags, the phrase it matched and the rule. It's **never** applied to verified evidence snippets or receipts, where a word like "sealed" can rightly appear. In turn, keep authored prose out of keys named for evidence (`commits`, `receipt`, `snippet`, ...), because those count as evidence and are skipped. Leave it out and nothing changes. |
|
|
629
|
+
| `history` | Optional. How far back `view` reads with no `--days`, `--from` or `--to`: `{ "days": 30 }`, `{ "from": "2025-01-01" }`, a range in the past `{ "from": "2025-01-01", "to": "2025-03-31" }`, or `{ "all": true }`. The last 7 days or fewer always load whole, unless they need more memory than Node has left. A longer choice loads at most the newest `historyLimitMB` of logs and says which days it loaded when that cuts it short. Leave it out for the last 7 days. Setup and Settings write it. |
|
|
630
|
+
| `historyLimitMB` | Optional. A cap, in MB, on two reads: how much log data a saved `history` longer than a week loads at once, and how much the Problems page reads of the window just before a longer choice. It's 500 unless you raise it (50 to 20000). For a one-week window, the week before loads whole, unless it needs more memory than Node has left. Settings shows an estimate of the time and memory before you save a new value. |
|
|
574
631
|
| `goalsFile` | Optional. The goal list `view` reads, resolved like a repo path. Leave it out and `view` runs without goals, or pass `--goals <file>` for one run. It's not the goals page's `honestweek.objectives.json`; see [The goal list](#the-goal-list). |
|
|
575
|
-
| `
|
|
576
|
-
| `
|
|
632
|
+
| `saveResults` | Optional. Whether `view` keeps its results between runs, in `honestweek.saved/` beside the config: `{ "on": true }`, with `"keepDays"` (1 to 36500, 365 if left out) for how long a saved day is kept, and `"history": false` to save only the check results, not each day's history. The history is kept for sessions in your configured repositories; `"otherSessions": true` keeps display-only repositories' and outside folders' sessions too, redacted the same way. Leave it out, or set `"on": false`, and nothing is saved or read. Settings sets it, and its Forget saved results button deletes what's saved. |
|
|
633
|
+
| `longSessionTokens` | Optional. How many tokens of context an agent can carry before the Problems page flags the session as long. It takes 10000 to 10000000, for example `150000`. Leave it out and that check is off, because no vendor recommends a number. Settings sets it. |
|
|
634
|
+
| `voice.denyPhrases` / `voice.allowPhrases` | Optional lists of strings, empty by default. `denyPhrases` **extends** the built-in list that `voice.denyMeta` checks with your own phrases, matched literally and in any letter case. `allowPhrases` is the **off-ramp** for a false match. It exempts a legitimate phrase a built-in pattern would otherwise flag, and only the matched text, so one over-eager match doesn't force you to turn off the whole check. |
|
|
577
635
|
|
|
578
636
|
**Repo roles:**
|
|
579
637
|
|
|
@@ -583,52 +641,55 @@ Your `honestweek.config.json` mirrors `honestweek.config.example.json`. Whether
|
|
|
583
641
|
|
|
584
642
|
## Sidecars
|
|
585
643
|
|
|
644
|
+
Each of these sits beside the config the command read ([Where honestweek finds your config](#where-honestweek-finds-your-config)).
|
|
645
|
+
|
|
586
646
|
| File | Status |
|
|
587
647
|
| --- | --- |
|
|
588
648
|
| `honestweek.draft.json` | The redacted weekly digest from `discover`. **Gitignored.** An intermediate working artifact, never published. |
|
|
589
|
-
| `honestweek.prompts.json` | The private, redacted Claude Code and Codex
|
|
590
|
-
| `honestweek.curated.json` | The private, redacted
|
|
591
|
-
| `honestweek.digest.pending.json` | A no-text
|
|
592
|
-
| `honestweek.prompt-items.json` | The
|
|
593
|
-
| `honestweek.carry.json` | The private, redacted
|
|
594
|
-
| `honestweek.carry.pending.json` |
|
|
649
|
+
| `honestweek.prompts.json` | The private, redacted inbox of your Claude Code and Codex prompts, plus a no-text tombstone for each one you delete. **Gitignored.** No renderer ever reads it. |
|
|
650
|
+
| `honestweek.curated.json` | The private, redacted review file from `digest prepare`, covering all six categories. **Gitignored.** It holds the exact selection and privacy decisions. An item you delete from the current week leaves only a no-text tombstone. |
|
|
651
|
+
| `honestweek.digest.pending.json` | A no-text marker of a `digest prepare` in progress, used only to recover one that was interrupted. **Gitignored.** While it exists, other commands stop instead of running. |
|
|
652
|
+
| `honestweek.prompt-items.json` | The items that passed the privacy check and are safe to make public. Version 1 holds prompts only, and version 2 is the balanced digest. **Gitignored.** `validate` and `build` rebuild it in memory from local sources and stop if the file doesn't match. |
|
|
653
|
+
| `honestweek.carry.json` | The private, redacted history of items carried into later weeks, kept to `curation.retentionWeeks` week records, 12 by default. **Gitignored.** Only a successful `build` that carries items between weeks moves it forward. |
|
|
654
|
+
| `honestweek.carry.pending.json` | What honestweek needs to recover if a `build` that carries items between weeks is interrupted, tied by hashes to the output and carry history it was writing. **Gitignored.** If the output and carry history don't match a combination it recognizes, it stops. |
|
|
595
655
|
| `honestweek.items.json` | The distilled, human-reviewable items. **Yours to keep or ignore** (not gitignored unless you add it; safe to delete). |
|
|
596
656
|
| `honestweek.reader.json` (opt-in) | The reader profile for a client report: who it's for, what they see first, and where each line of that came from. Holds a real person's preferences, so keep it private with the report. |
|
|
597
657
|
| `<report>.note.md` (opt-in) | The short note a reader profile asks for with `format.note`, written beside the client report. Yours to share. |
|
|
598
658
|
| `honestweek.history.json` | What landed on the default branch in a period, from `history`: the raw material for a client report. **Gitignored.** Redacted before it's written; only counts are printed. |
|
|
599
659
|
| `honestweek.drafts/` (opt-in) | Post drafts from `mine --draft`, with their claims still unverified. **Gitignored** in a folder `init` set up; elsewhere, add it yourself or set `mine.draft.dir`. |
|
|
600
|
-
| `honestweek.harvest.json` |
|
|
660
|
+
| `honestweek.harvest.json` | Words `harvest` suggests adding to your redaction lists. **Gitignored.** Only the count is printed, and the raw nouns stay on your machine for you to review. |
|
|
601
661
|
| `honestweek.codex-judgments/` (opt-in) | What your own `codex` wrote about each Codex session when you press Run with Codex in `view`, one file per session. **Gitignored**: the folder ignores itself and gets a line in the config folder's `.gitignore`. Redacted before it's written. |
|
|
662
|
+
| `honestweek.saved/` (opt-in) | What `view` keeps between runs when `saveResults` is on: each day's sessions and what the Problems checks found, one file per day under `checks/`, and, unless `history` is false, each day's history, gzipped, one file per day under `days/`. A session whose log is gone comes back from it, marked saved. **Gitignored**: the folder ignores itself and gets a line in the config folder's `.gitignore`. Owner-only where the system has file modes. Redacted before it's written, and again with your current private words each time it's read. A log's own session id is kept only as a hash, and a log file only as a hash of its path. Forget saved results in Settings deletes it. |
|
|
602
663
|
| `output.file` (e.g. `honestweek.digest.md`) | The final rendered output. **Yours to keep or ignore.** |
|
|
603
|
-
| `honestweek.config.json` | Your config.
|
|
604
|
-
| `honestweek.archive/` (opt-in) | The
|
|
605
|
-
| `honestweek.objectives.json` (opt-in) | The goal registry
|
|
606
|
-
| `honestweek.goal-changelog.json` (opt-in) |
|
|
607
|
-
| `honestweek.findings.json` (opt-in) | The
|
|
664
|
+
| `honestweek.config.json` | Your config. **Gitignored** by `init`, Setup and Settings, since it holds your email, your repo paths and any private words. To track it anyway, `git add -f` it once. |
|
|
665
|
+
| `honestweek.archive/` (opt-in) | The weekly snapshots and `index.json`, a local version of a "/log" series of past weekly reports. `build` writes it only when `output.archive` is true. **Yours to keep, ignore, or commit.** |
|
|
666
|
+
| `honestweek.objectives.json` (opt-in) | The goal registry. With it, `page` mode also writes `goals.html`. Without it, `page` mode stays single-page. It decides which goals get published, so commit it if you want the goals page. |
|
|
667
|
+
| `honestweek.goal-changelog.json` (opt-in) | An optional log you only ever add to, recording changes to the set of goals itself. The goals page shows it as its "what changed" band. |
|
|
668
|
+
| `honestweek.findings.json` (opt-in) | The ledger of what `mine` found, and what you accepted or declined. **Commit it**: it's the only record of what you already said no to, and everything in it is de-identified and redacted before it's written. |
|
|
608
669
|
|
|
609
670
|
## What it does NOT do / privacy model
|
|
610
671
|
|
|
611
|
-
- **Only your own allowlisted repos are read.** `git` runs only against the repositories in your `repos` list,
|
|
672
|
+
- **Only your own allowlisted repos are read.** `git` runs only against the repositories in your `repos` list, with two exceptions. First, the scans that suggest repos to list (`init`, and the Setup and Settings pages in `view`) look in the folder you run them in and the folders next to it, but never ask `git` about the commits in a repository that holds a folder your config marks display-only, or sits inside one. Second, `discover` and Settings check that the draft file and the config aren't tracked in the folder you run them in. Where that would reach a display-only folder, they skip git, say so and give the two commands to check by hand. Weekly reports use only sessions from those repos. The `mine` command reads every session in your logs, as [SECURITY.md](SECURITY.md) explains.
|
|
612
673
|
- **`display`-role repos are summarized generically and NEVER git-read.** There is no code path that runs `git` against a `display` repo.
|
|
613
674
|
- **Output stays local until you publish it.** honestweek writes local files only.
|
|
614
|
-
- **No telemetry, no network egress.** honestweek makes no network call.
|
|
675
|
+
- **No telemetry, no network egress.** honestweek makes no network call. Three things you start do send session text to an AI. In the weekly summary, Claude runs honestweek in your own Claude Code session (or Codex in yours, if you run the skill there), reads the redacted draft (`honestweek.draft.json`) and sees what each command prints. With Include /insights on, Run /insights and Run with Codex ask you first, then run your own `claude` or `codex`, which send your sessions to Claude or OpenAI. When Claude or Codex runs `find`, `replay`, `problems` or `goals` for you, through the find skill, it reads their redacted answers. [Where your data goes](docs/where-your-data-goes.md) has each step. The optional `preview` server is loopback-only (`127.0.0.1`). It serves your already-built output with no key, so any program or account on your machine can read it while it runs, and nothing leaves your machine. The `view` page is loopback-only too. It answers only the page it opened and keeps only what you choose to save, as [What `view` keeps private](#what-view-keeps-private) explains.
|
|
615
676
|
- **Nothing is auto-published.** honestweek produces a draft; *you* are the publisher.
|
|
616
677
|
|
|
617
678
|
### What the scrubber catches, and what it doesn't
|
|
618
679
|
|
|
619
|
-
Redaction
|
|
680
|
+
Redaction works by matching patterns, and when a pattern is ambiguous, it hides more than it needs to, on purpose. It reliably removes email addresses (including ones with an encoded `@`, like `%40`), home and user paths (including `~/…`, the root account's `/root/…`, URL-encoded paths, and the user name in Claude Code's encoded project folder names like `C--Users-you-…`), prefixed API keys (GitLab's `glpat-` too) and JWTs, high-entropy tokens of 32+ characters, UUIDs, bare 9+ digit runs, money amounts written with `$`, a currency code like `EUR`, or a word like `euros`, and every term you list under `redaction`, whether its accents are written composed or decomposed. A bare hex string of 32 or more characters counts as a token too, unless it's exactly 40 characters, the length of a full commit id. It scrubs the names of fields in what it writes (JSON keys, like a chart's repo labels or a tool's name) the same way as their values.
|
|
620
681
|
|
|
621
|
-
It also hides the value of a field whose name says it's a secret: a password, passphrase, token, secret, API key, access or private key, credential, cookie, signature or authorization. The name can be spelled `API_KEY`, `x-api-key`, `client_secret`, `dbPassword`, `authtoken`, `DB_PASS`, `PGPASSWORD`, `MYSQL_PWD` or ODBC's `PWD`, and the value can follow `=`, `=>`, `:`, `:=`, `==` or `===`, sit in a quoted JSON string at any level of escaping, sit inside an XML element named that way (`<password>…</password>`), or follow a `--password` flag or a `-Password` parameter.
|
|
682
|
+
It also hides the value of a field whose name says it's a secret: a password, passphrase, token, secret, API key, access or private key, credential, cookie, signature or authorization. The name can be spelled `API_KEY`, `x-api-key`, `client_secret`, `dbPassword`, `authtoken`, `DB_PASS`, `PGPASSWORD`, `MYSQL_PWD` or ODBC's `PWD`, and the value can follow `=`, `=>`, `:`, `:=`, `==` or `===`, sit in a quoted JSON string at any level of escaping, sit inside an XML element named that way (`<password>…</password>`), or follow a `--password` flag or a `-Password` parameter. It hides a `password:` line and an `Authorization:` or `Cookie:` header up to the end of the line, a quote, or the next `key:` on it. When it reads back a whole JSON record, it hides a value under a key like that too. Bearer and Basic credentials, the password in a web address (`redis://:…@host`) or after `curl -u user:…`, and a PowerShell `ConvertTo-SecureString` literal (after `-String` or `-AsPlainText`, or piped in) go the same way. It replaces only the value, with `[redacted:secret]`, so you can still see which field held it. A key that only ends in `Key`, like `fileKey` or `sessionKey`, isn't a secret, and neither is a value like `true`, `none`, or a test count after `pass:`.
|
|
622
683
|
|
|
623
|
-
It
|
|
684
|
+
It's a safety net, not a guarantee. Here are the known gaps, so you can decide rather than assume:
|
|
624
685
|
|
|
625
|
-
- **Short secrets with nothing naming them.** A hand-picked password under 32 characters
|
|
626
|
-
- **Prose that reads like a field.** Because it errs toward hiding, a sentence that starts like one loses the word after the colon: `Auth: users get logged out`
|
|
627
|
-
- **A value after a bold label.** In `**Token:** abc123
|
|
628
|
-
- **A quoted part inside a header.**
|
|
686
|
+
- **Short secrets with nothing naming them.** A hand-picked password under 32 characters survives when no field, flag, header or scheme names it (a bare `hunter2` in a sentence, a password glued to `mysql -p`, an item in a plural `tokens` list). It can't be told apart from prose.
|
|
687
|
+
- **Prose that reads like a field.** Because it errs toward hiding, a sentence that starts like one loses the word after the colon: `Auth: users get logged out` comes out as `Auth: [redacted:secret] get logged out`. In goal text (an objective's label, `what`, `why` or `how`, or a changelog entry), anything the redactor would change stops `build` instead, so reword a line like `Auth: refresh sessions quietly` there. It leaves plain words after `Bearer` or `Basic` (`basic validation`) and a type annotation (`login(password: string)`) alone.
|
|
688
|
+
- **A value after a bold label.** In `**Token:** abc123`, the redactor reads the closing `**` as the field's value, so `abc123` still shows. Keep secrets out of Markdown bold labels.
|
|
689
|
+
- **A quoted part inside a header.** In a header with a quoted part (`Cookie: theme="dark"; session=…`, `Authorization: Digest … response="…"`), the hidden part ends at the quote, so what follows can show.
|
|
629
690
|
- **Unlisted spellings of a listed term.** Adding `AcmeCorp` does not cover `Acme Corp`, `Acme-Corp`, or `Doe, Jane` for `Jane Doe`. List the variants you care about; `harvest` proposes candidates from your own draft.
|
|
630
691
|
- **Structured personal data.** Phone numbers, SSNs, and space- or hyphen-separated card numbers are not matched. Only unbroken 9+ digit runs are.
|
|
631
|
-
- **UNC paths.** `\\server\Users\you
|
|
692
|
+
- **UNC paths.** It doesn't match a Windows network path like `\\server\Users\you\…`. It does match drive-letter and POSIX forms.
|
|
632
693
|
|
|
633
694
|
Read the built output before you publish it. That review is part of the design, not a formality, and `preview` exists to make it easy.
|
|
634
695
|
|
|
@@ -636,12 +697,16 @@ Read the built output before you publish it. That review is part of the design,
|
|
|
636
697
|
|
|
637
698
|
honestweek's two non-negotiable promises:
|
|
638
699
|
|
|
639
|
-
1. **A receipt on every line.** Every
|
|
640
|
-
2. **It never asserts a motive the log
|
|
700
|
+
1. **A receipt on every line.** Every item in the output points to its source: a commit SHA or a session turn. If an item reaches the renderer without a receipt, that's a build error, not a line without a receipt.
|
|
701
|
+
2. **It never asserts a motive the log doesn't contain.** honestweek defaults to **under-claiming**. Verified or measured work that has landed on the repo's default branch reads as `shipped`. Real work still on an unmerged branch reads as `in progress`. Anything weaker reads as `designed, not proven`. It never claims an intent the transcript doesn't support.
|
|
641
702
|
|
|
642
703
|
## Releasing (maintainers)
|
|
643
704
|
|
|
644
|
-
honestweek is on npm, starting with version 0.2.0. I publish each version from my own terminal and then tag it, in the order [docs/releasing.md](docs/releasing.md) sets out. The `files` allowlist in `package.json` decides what ships (`bin/`, `lib/`, `SKILL.md
|
|
705
|
+
honestweek is on npm, starting with version 0.2.0. I publish each version from my own terminal and then tag it, in the order [docs/releasing.md](docs/releasing.md) sets out. The `files` allowlist in `package.json` decides what ships (`bin/`, `lib/`, `SKILL.md` and its `flows/` folder, the example config and the plugin manifests), and `test/package-contents.test.mjs` pins it.
|
|
706
|
+
|
|
707
|
+
## How it reads Claude Code and Codex logs
|
|
708
|
+
|
|
709
|
+
[docs/session-logs.md](docs/session-logs.md) says which Claude Code turns count as yours (a turn a program sent doesn't), which Codex files it reads, and which parts of a Codex turn it keeps.
|
|
645
710
|
|
|
646
711
|
## Contributing and security
|
|
647
712
|
|
|
@@ -650,13 +715,3 @@ honestweek is on npm, starting with version 0.2.0. I publish each version from m
|
|
|
650
715
|
## License
|
|
651
716
|
|
|
652
717
|
[MIT](LICENSE)
|
|
653
|
-
|
|
654
|
-
## Which Claude Code turns count as yours
|
|
655
|
-
|
|
656
|
-
Current Claude Code marks each turn with who sent it, in a `turnOrigin` field: `human` when it came from your own session, typed or pasted, `sdk` when a program sent it (a script, the Agent SDK, a headless `claude -p` run, or another session through one), and other values for a background task's notice or a message from another session. The interactive-session count in `page` and `site` modes reads it too, unless you set `output.skipProgramSessions` to `false`. The weekly digest, the prompt inbox behind `prompts` and the digest's Prompt highlights, and `mine` read a turn as yours only when it's marked `human` or isn't marked at all, as in logs from older Claude Code, which read exactly as before. A turn marked as anyone else's isn't one of your prompts, your words in a session's digest entry, an idea or decision cue, or the first prompt `mine` uses to tell sessions apart. A session where only a program, a task or another session sent turns isn't one you worked in, so the digest and `mine` leave it out; one a program opened and you typed into later still counts. A program's turn keeps its place in the session's turn numbers, so prompts you've already kept or hidden keep their receipts. It also ends your turn, even when it's only a slash command or a notice, so a test run or reply that follows it isn't credited to your prompt. Claude Code also logs a turn in a queue before delivering it, and only the delivery (the turn itself, or a note attached mid-turn) says who sent it, so `mine` counts a queued turn once, as its delivery, and not at all when the delivery is someone else's. A value honestweek doesn't recognize counts as someone else's here; Replay reads one as yours and marks that as inferred.
|
|
657
|
-
|
|
658
|
-
## Codex Voice and session logs
|
|
659
|
-
|
|
660
|
-
honestweek reads regular JSONL files under `$CODEX_HOME/sessions` and `$CODEX_HOME/archived_sessions`, excluding `subagents`. It does not read `history.jsonl`, plaintext logs, or other app state. A human turn is read from either shape Codex has used: the current `response_item` message with `role: "user"`, or the older `event_msg` / `user_message` string. Codex sends its own context (environment, `AGENTS.md`, plugin lists) and other agents' hand-offs through the same user slot, so a block that opens with a tag or the `AGENTS.md` preamble is dropped, only the request is kept from the IDE extension's wrapper (open file, tabs, mentioned files), and a message carrying a delegation, heartbeat, automation, or approval-review block isn't counted as a person at all. When a turn is written in both shapes, it's counted once. A session started with `codex exec` is never counted as mine: another agent or a script usually starts those, so none of its messages becomes a prompt in the inbox, the digest or the miner, and the work history shows its first message as the agent's starting instruction. A session I type in that only mentions `codex exec` still counts. A Voice or dictated turn is ingested only when Codex records its transcript as one of those message shapes. The `audio`, `local_audio`, image, reasoning, tool-output, and other non-message fields are never retained as prompt text. A paired shell record sets only the observed-verification boolean when it contains one literal recognized test or commit command, an explicit zero exit, and matching positive evidence. Current Codex `exec` wrappers qualify only in a closed form that forwards the unchanged shell result; they are parsed without evaluation, and their source and output text are discarded. Raw session ids and working paths become hashes or private attribution; the redacted prompt, privacy audit, timestamp, source, turn, and receipt hashes remain in the current gitignored review store. Raw transcript retention remains Codex's responsibility and is not changed by honestweek.
|
|
661
|
-
|
|
662
|
-
A valid Codex session record does not need a final assistant message. Its public-safe human prompt can contribute to cross-session lexical recurrence and automatic draft selection, but it cannot supply assistant-final cues or observed verification unless those records exist. A missing, unconfigured, or `display`-role working directory makes the turn private. Private or hidden turns cannot supply recurrence evidence or enter automatic output. An ambiguous or high-risk human prompt is withheld from prompt recurrence and prompt output. A labelled cue in that human prompt retains the prompt receipt and conservative prompt audit; an assistant-final cue is gated separately on its own redacted rendition and exact receipt. A malformed record or missing Codex session identity makes that source unreadable and preserves the prior store. The private prompt store is regenerated for the completed week. Its no-text deletion tombstones persist until explicit reset, and redacted lifecycle carry persists only within the limits described above.
|