@debonet/idd 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTRUCTIONS.md +159 -0
- package/README.md +89 -2
- package/bin/idd +16 -0
- package/bin/idd-merge-hook +13 -0
- package/docs/existing-page-migration.md +92 -0
- package/docs/hosted-viewer.md +164 -0
- package/package.json +57 -4
- package/scripts/check.js +593 -0
- package/scripts/commands.js +908 -0
- package/scripts/html-text.js +50 -0
- package/scripts/import-page.js +80 -0
- package/scripts/merge-hook.js +365 -0
- package/scripts/page-build.js +21 -0
- package/scripts/project-lock.js +135 -0
- package/specs/adoption.md +133 -0
- package/specs/build.md +201 -0
- package/specs/guidance/agent-merge.md +63 -0
- package/specs/guidance/answers.md +108 -0
- package/specs/guidance/claude-code.md +76 -0
- package/specs/guidance/codex.md +93 -0
- package/specs/guidance/session.md +238 -0
- package/specs/guidance/writing-questions.md +171 -0
- package/specs/hosted-questionnaire.md +793 -0
- package/specs/idd-merge-hook.md +42 -0
- package/specs/idd-page.md +367 -0
- package/specs/project-files.md +198 -0
- package/specs/questions-page.md +169 -0
- package/specs/themes.md +114 -0
- package/templates/questions-page.html +337 -0
package/INSTRUCTIONS.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# IDD instructions for coding agents
|
|
2
|
+
|
|
3
|
+
<!-- @implements g-mfqz8n@63b06e1 -->
|
|
4
|
+
|
|
5
|
+
This project uses IDD when its `AGENTS.md` says so. The npm package supplies
|
|
6
|
+
the agent workflow and commands. The hosted questionnaire runs separately at
|
|
7
|
+
`https://interrogation.dev`; installing the npm package does not install or
|
|
8
|
+
run the web application. Each tool uses its native questionnaire.
|
|
9
|
+
|
|
10
|
+
## Opt in a project
|
|
11
|
+
|
|
12
|
+
Install IDD in the project with `npm install @debonet/idd`. Add this short
|
|
13
|
+
instruction to its root `AGENTS.md`:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
This project uses IDD. Before other work, read the installed package's instructions at the path printed by `node -p "require.resolve('@debonet/idd/INSTRUCTIONS.md')"`. If IDD is not installed, run `npm install @debonet/idd` first.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Before expecting the viewer to discover a questionnaire, install the IDD GitHub App on each project repository. [Add the repository to the IDD app
|
|
20
|
+
installation](https://github.com/apps/interrogation-driven-development/installations/new)
|
|
21
|
+
and grant it access to that repository.
|
|
22
|
+
|
|
23
|
+
## Start a session
|
|
24
|
+
|
|
25
|
+
1. Identify the checked-out code branch and matching `idd-<branch>` branch.
|
|
26
|
+
2. Open or create a separate Git worktree for that IDD branch under the code
|
|
27
|
+
checkout's `tmp/` directory. Keep the questionnaire files out of the code
|
|
28
|
+
branch. A branch based on another code branch starts from that parent's
|
|
29
|
+
IDD branch so the data histories can merge.
|
|
30
|
+
3. Fetch the latest IDD branch before reading its questions or answers. Run
|
|
31
|
+
`npm exec -- idd` from the data worktree for every questionnaire
|
|
32
|
+
command.
|
|
33
|
+
4. Read its pending answers and incorporate those before the task.
|
|
34
|
+
5. Run `npm exec -- idd thoughts` and review the project's submitted
|
|
35
|
+
thoughts in creation order. Work on a note when it applies and has not
|
|
36
|
+
already been addressed. Ask through the usual IDD question flow when a
|
|
37
|
+
note needs a decision. Leave submitted notes in the shared log.
|
|
38
|
+
6. Before incorporating an answer or acting on a thought or conflict, claim
|
|
39
|
+
that item with `npm exec -- idd claim <answer|thought|conflict>
|
|
40
|
+
<item-id> <session-id>`. Commit and push `idd/claims.json` before starting
|
|
41
|
+
the work. If the push is rejected, sync and inspect the branch; proceed
|
|
42
|
+
only if this session owns the claim. Release it with
|
|
43
|
+
`npm exec -- idd release <kind> <item-id> <session-id>` after the work is
|
|
44
|
+
incorporated, then commit and push the release.
|
|
45
|
+
|
|
46
|
+
For a project's first IDD branch, get its numeric GitHub repository id and
|
|
47
|
+
run `npm exec -- idd branch-hash <repository-id>
|
|
48
|
+
refs/heads/<code-branch>`. Create an orphan data branch named
|
|
49
|
+
`idd-<code-branch>`, then run `npm exec -- idd init "<Project> Open
|
|
50
|
+
Questions" <printed-hash>` from that worktree. Commit and push the `idd/`
|
|
51
|
+
files to the same GitHub repository. For a new code branch with a parent,
|
|
52
|
+
create its IDD branch from the parent's IDD branch and set the page's branch
|
|
53
|
+
hash to the new code branch hash; keep inherited question hashes unchanged.
|
|
54
|
+
|
|
55
|
+
## Ask and publish a question
|
|
56
|
+
|
|
57
|
+
Write a complete, self-contained question with a short title, enough context
|
|
58
|
+
to decide without looking elsewhere, a concrete example, and two to four clear
|
|
59
|
+
options. Do not use terms the model invented in private reasoning unless they
|
|
60
|
+
have been discussed with the user. Ask only about choices that matter to the
|
|
61
|
+
product or change what the user experiences; decide internal implementation
|
|
62
|
+
details without asking when they make no product difference. Describe the
|
|
63
|
+
choices in terms of what the user does and can observe, not hidden
|
|
64
|
+
implementation details. Add it with
|
|
65
|
+
`npm exec -- idd add`, using one JSON object on stdin with `title`,
|
|
66
|
+
`body` and `options`. Use the question id it prints. Present the question
|
|
67
|
+
with the current tool's native questionnaire when available. Commit and push
|
|
68
|
+
the changed IDD files to the matching `idd-<branch>` branch.
|
|
69
|
+
|
|
70
|
+
Get a direct viewer URL with
|
|
71
|
+
`npm exec -- idd viewer-url <owner/repository> <code-branch>`. Open it
|
|
72
|
+
when the tool can open a browser and include the link in the same update.
|
|
73
|
+
Repeat the link in progress updates while questions remain unanswered so it
|
|
74
|
+
is easy to reopen the page. Anyone with repository read access can view the
|
|
75
|
+
questionnaire; submitting an answer requires repository write access.
|
|
76
|
+
|
|
77
|
+
In Codex, present the question with `functions.request_user_input_async`:
|
|
78
|
+
put the title and body together in the question title, and pass each option
|
|
79
|
+
as a choice string beginning with its key. Save the returned choice and note
|
|
80
|
+
with `npm exec -- idd answer <question-id>` before acting on it. The
|
|
81
|
+
Codex-specific details are in `specs/guidance/codex.md` in this package.
|
|
82
|
+
|
|
83
|
+
## Receive an answer
|
|
84
|
+
|
|
85
|
+
When a person answers through the hosted page, run
|
|
86
|
+
`npm exec -- idd wait <question-id>` from a clean data worktree. It
|
|
87
|
+
waits for the hosted viewer's push event, checks the remote IDD branch when
|
|
88
|
+
an event arrives, fast-forwards the local worktree when it changes, records
|
|
89
|
+
the answer as pending and prints it as JSON. If push delivery is unavailable
|
|
90
|
+
or the event stream disconnects, it checks the branch every 30 seconds by
|
|
91
|
+
default. Continue work only after incorporating that answer. If the tool's
|
|
92
|
+
native questionnaire returns the answer directly, record it with
|
|
93
|
+
`npm exec -- idd answer <question-id>` using one JSON object on stdin
|
|
94
|
+
with `sChoice`, `sNote` and `dtm` (the current ISO 8601 time). Commit and
|
|
95
|
+
push the answer files to the IDD branch before continuing. Commit and push
|
|
96
|
+
changes to `pending.json` when you record an answer and after you clear it,
|
|
97
|
+
so another session can see the remaining work.
|
|
98
|
+
|
|
99
|
+
In Codex, connect the IDD MCP server once with
|
|
100
|
+
`codex mcp add idd --url https://interrogation.dev/mcp`, then restart Codex.
|
|
101
|
+
While waiting for a hosted answer, keep an `idd_wait_for_change` MCP call active
|
|
102
|
+
and run `npm exec -- idd wait <question-id>` as a second listener. The MCP tool
|
|
103
|
+
signals any IDD branch change; `idd wait` synchronizes and records that
|
|
104
|
+
question's answer. After either signal, inspect the latest branch state. Both
|
|
105
|
+
may report the same update, so check pending data before incorporating an answer.
|
|
106
|
+
|
|
107
|
+
Never replace an answer already accepted on the IDD branch; show the
|
|
108
|
+
accepted answer if another submission conflicts.
|
|
109
|
+
|
|
110
|
+
When a human answer is the only thing preventing progress, publish the
|
|
111
|
+
session's `blocked` status on the data branch with
|
|
112
|
+
`npm exec -- idd status <session-id> blocked`. Change it to `working`
|
|
113
|
+
when work can proceed and clear the entry when the session ends. Commit and
|
|
114
|
+
push status changes so the viewer shows the current state. Commit and push
|
|
115
|
+
the pending queue after recording or clearing an answer, so later sessions
|
|
116
|
+
can see what still needs work.
|
|
117
|
+
|
|
118
|
+
## Count questions
|
|
119
|
+
|
|
120
|
+
From the IDD data worktree, run `npm exec -- idd count` to print conflicts,
|
|
121
|
+
unanswered, answered and superseded question counts. By default, the command
|
|
122
|
+
requires a clean worktree, fetches the matching `idd-<branch>` from `origin`,
|
|
123
|
+
and fast-forwards before counting. Use `--nosync` to count the current local
|
|
124
|
+
files without fetching; this also permits a dirty worktree.
|
|
125
|
+
|
|
126
|
+
Use `--type` to print just one numeric count:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
npm exec -- idd count --type conflicts
|
|
130
|
+
npm exec -- idd count --type u
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The accepted types are `conflicts` (`c`), `unanswered` (`u`), `answered`
|
|
134
|
+
(`a`) and `superseded` (`s`).
|
|
135
|
+
|
|
136
|
+
## Thoughts and observations
|
|
137
|
+
|
|
138
|
+
The questionnaire page has an always-open text box for project ideas and
|
|
139
|
+
observations. Submitting a note writes it to `idd/thoughts.json` on the
|
|
140
|
+
project's IDD branch, where repository writers can post notes and project
|
|
141
|
+
readers can see them. The note is kept as plain text and does not change
|
|
142
|
+
question counts.
|
|
143
|
+
|
|
144
|
+
From the IDD data worktree, run `npm exec -- idd thoughts` to sync and list
|
|
145
|
+
the notes. Use `npm exec -- idd thoughts --nosync` to list the current local
|
|
146
|
+
copy without fetching. Notes stay in the repository after an agent has acted
|
|
147
|
+
on them; a follow-up decision becomes a normal IDD question.
|
|
148
|
+
|
|
149
|
+
## Keep IDD data separate and reconcile branches
|
|
150
|
+
|
|
151
|
+
Commit questionnaire files, answers, history, conflicts and agent status
|
|
152
|
+
only to `idd-<code-branch>`; do not include unfinished code in those commits.
|
|
153
|
+
Before merging code branches, merge the source IDD branch into the target
|
|
154
|
+
IDD branch, review duplicate, obsolete and overlapping questions, resolve
|
|
155
|
+
answer conflicts, and complete any work needed to implement the accepted
|
|
156
|
+
decision. Push the reconciled IDD branch before completing the code merge.
|
|
157
|
+
|
|
158
|
+
Install the repository's merge hooks with
|
|
159
|
+
`npm exec -- idd-merge-hook install` when the project uses that merge gate.
|
package/README.md
CHANGED
|
@@ -1,3 +1,90 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Interrogation-Driven Development (IDD)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<img align="right" src="assets/logos/idd-logo-icon.png" alt="IDD logo" width="140">
|
|
4
|
+
|
|
5
|
+
## Purpose / Why
|
|
6
|
+
|
|
7
|
+
Interrogation-Driven Development (IDD) is a framework for progressive
|
|
8
|
+
software development. As an agent works through a specification, it records
|
|
9
|
+
asynchronous questions for the engineer when it reaches an ambiguity or a
|
|
10
|
+
decision boundary. The engineer answers through the project's questionnaire;
|
|
11
|
+
those answers become recorded decisions that guide the implementation.
|
|
12
|
+
|
|
13
|
+
IDD exists because decisions asked in a terminal or chat are easy to miss,
|
|
14
|
+
repeat, or lose between sessions. A shared question list and recorded answers
|
|
15
|
+
keep the agent and engineer aligned while the work advances one decision at a
|
|
16
|
+
time.
|
|
17
|
+
|
|
18
|
+
[Horizontal logo](assets/logos/idd-logo-horizontal.png) ·
|
|
19
|
+
[Square logo](assets/logos/idd-logo-square.png) ·
|
|
20
|
+
[Icon](assets/logos/idd-logo-icon.png)
|
|
21
|
+
|
|
22
|
+
## TL;DR
|
|
23
|
+
|
|
24
|
+
* Every decision a coding session needs from the human is added to the project's shared question list and presented through that agent tool's questionnaire.
|
|
25
|
+
* Each code branch has its own `idd-<branch>` branch in the same GitHub repository. Questionnaire files stay out of code commits.
|
|
26
|
+
* Any repository reader can view questions; submitting an answer requires repository write access. The browser commits answers directly to GitHub.
|
|
27
|
+
* Agents can wait for answers with `idd wait`; GitHub push events wake the command when configured, with branch polling as a fallback. ChatGPT Work chats can subscribe to the hosted MCP event for idle-session notifications.
|
|
28
|
+
* A project adopts IDD with one line in its `AGENTS.md`; every new session then reads the package's `INSTRUCTIONS.md` and acts on pending answers first.
|
|
29
|
+
* The rules for writing questions and reading answers were earned in AIOS, one observed mistake at a time; they live here once, for every project.
|
|
30
|
+
* IDD is a ConcordSTC project: its rules are marked statements rooted in the human's own words, and its code is tested against them.
|
|
31
|
+
|
|
32
|
+
## Adopt IDD
|
|
33
|
+
|
|
34
|
+
Install the package in the project with `npm install @debonet/idd`, then
|
|
35
|
+
paste this line into the project's `AGENTS.md`:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
This project uses IDD. Before other work, read the installed package's instructions at the path printed by `node -p "require.resolve('@debonet/idd/INSTRUCTIONS.md')"`. If IDD is not installed, run `npm install @debonet/idd` first.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The path is resolved from the project's npm installation, so the instruction
|
|
42
|
+
does not depend on where npm placed the package. The package's
|
|
43
|
+
[`INSTRUCTIONS.md`](INSTRUCTIONS.md) explains branch setup and the session
|
|
44
|
+
workflow.
|
|
45
|
+
|
|
46
|
+
## Solution (what?)
|
|
47
|
+
|
|
48
|
+
IDD has two parts: the agent-side npm package and the hosted questionnaire at
|
|
49
|
+
`https://interrogation.dev`. The `idd` command manages question data, prints
|
|
50
|
+
a direct viewer link, counts question states, and polls the matching remote
|
|
51
|
+
IDD branch for answers. Its package includes the agent instructions and a Git
|
|
52
|
+
merge hook; it does not include or run the hosted web application. An adopting project installs the tools with
|
|
53
|
+
`npm install @debonet/idd`; the model reads the installed instructions using
|
|
54
|
+
`node -p "require.resolve('@debonet/idd/INSTRUCTIONS.md')"`.
|
|
55
|
+
|
|
56
|
+
Questionnaire, answer, status and history files live on the `idd-<branch>`
|
|
57
|
+
branch in the same repository as the code. Agents edit them from a separate
|
|
58
|
+
Git worktree, so an unfinished implementation never enters an IDD commit.
|
|
59
|
+
Codex can present a question through its interactive questionnaire. The
|
|
60
|
+
hosted viewer also lets the human answer from any device, and the agent can
|
|
61
|
+
wait for that committed answer with `idd wait`.
|
|
62
|
+
|
|
63
|
+
IDD also includes an optional hosted viewer for GitHub projects. It runs on
|
|
64
|
+
Cloud Run, discovers questionnaire branches across repositories available to
|
|
65
|
+
the signed-in user, and commits answers from the browser directly to GitHub.
|
|
66
|
+
It does not store repository data or user tokens. It stores only ChatGPT MCP
|
|
67
|
+
event subscription metadata in Firestore. ChatGPT Work chats can subscribe to
|
|
68
|
+
the global answer-change event; each event contains no repository or answer
|
|
69
|
+
data and asks the chat to inspect its current project. See
|
|
70
|
+
[`docs/hosted-viewer.md`](docs/hosted-viewer.md) for GitHub App setup and
|
|
71
|
+
deployment instructions.
|
|
72
|
+
|
|
73
|
+
## Method (how?)
|
|
74
|
+
|
|
75
|
+
An agent can present a question through its native questionnaire. The hosted
|
|
76
|
+
viewer provides the same question on a web page; the browser commits the
|
|
77
|
+
answer to GitHub. An agent waiting with `idd wait` receives a prompt event
|
|
78
|
+
when the GitHub push webhook is configured, then fetches the answer and
|
|
79
|
+
queues it as pending. Branch polling covers environments without push
|
|
80
|
+
delivery. ChatGPT Work chats can receive the same webhook-triggered change
|
|
81
|
+
through MCP Events while idle. Claude.ai currently uses an active `idd wait`
|
|
82
|
+
call. A session lists pending answers at its start and acts on them
|
|
83
|
+
before the task it was started for.
|
|
84
|
+
|
|
85
|
+
The core workflow is harness-independent: the npm package supplies the data
|
|
86
|
+
format, branch commands and agent instructions. The hosted viewer runs as a
|
|
87
|
+
separate Cloud Run service at `interrogation.dev`. Tool-specific guidance
|
|
88
|
+
describes how each agent presents a question and reads its immediate response.
|
|
89
|
+
|
|
90
|
+
Each rule is a guidance line in `specs/guidance/`, rooted in the human's quoted words or marked as an architect's decision for him to ratify, and cites the observations in `observations.md` that it rests on. The page's behaviour and the command's are specified in `specs/questions-page.md`, `specs/project-files.md` and `specs/idd-page.md`, and tested against those statements. How a project adopts IDD is in `specs/adoption.md`; how a project with an existing page moves over, keeping its address and every saved answer, is in `docs/existing-page-migration.md`.
|
package/bin/idd
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @implements s-cg2j10@e28309f
|
|
3
|
+
// @implements s-vfgnzf@47216b8
|
|
4
|
+
const { aRun } = require( "../scripts/commands" )
|
|
5
|
+
|
|
6
|
+
Promise.resolve( aRun(
|
|
7
|
+
process.cwd(), process.argv.slice( 2 ),
|
|
8
|
+
() => require( "fs" ).readFileSync( 0, "utf8" )
|
|
9
|
+
)).then(( aResult ) => {
|
|
10
|
+
process.stdout.write( aResult.sOut )
|
|
11
|
+
process.stderr.write( aResult.sErr )
|
|
12
|
+
process.exitCode = aResult.nExit
|
|
13
|
+
}).catch(( xError ) => {
|
|
14
|
+
process.stderr.write( "idd: " + xError.message + "\n" )
|
|
15
|
+
process.exitCode = 1
|
|
16
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict"
|
|
3
|
+
|
|
4
|
+
// @implements s-e4kj5b@45aff9e
|
|
5
|
+
const { fzMain } = require( "../scripts/merge-hook" )
|
|
6
|
+
|
|
7
|
+
process.exitCode = fzMain(
|
|
8
|
+
process.argv.slice( 2 ),
|
|
9
|
+
process.cwd(),
|
|
10
|
+
( s ) => process.stdout.write( s ),
|
|
11
|
+
( s ) => process.stderr.write( s ),
|
|
12
|
+
process.env
|
|
13
|
+
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Moving a project with an existing questions page to IDD
|
|
2
|
+
|
|
3
|
+
This guide is for a project that already has a questions page made from the older template (`~/.claude/templates/questions-page.html`, questions held in a `vaQuestion` array inside the page) and rules of its own about questions for the human in its `AGENTS.md`, `CLAUDE.md` or specs. After it, the project's page is built from `idd/questions.json` and published to the same address, every saved answer still shows, and the project's rules files hold the IDD line in place of the rules IDD now holds. AIOS is the worked example throughout; another project substitutes its own files.
|
|
4
|
+
|
|
5
|
+
Do it when no agent is running in the project, since it edits rules files, a spec and the observations file.
|
|
6
|
+
|
|
7
|
+
## 1. Save the current state
|
|
8
|
+
|
|
9
|
+
From the project root:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
mkdir -p tmp/idd-migration
|
|
13
|
+
npm run spec-map > tmp/idd-migration/spec-map-before.txt
|
|
14
|
+
npm run spec-map -- --gate > tmp/idd-migration/gate-before.txt
|
|
15
|
+
cp AGENTS.md CLAUDE.md observations.md tmp/idd-migration/
|
|
16
|
+
cp specs/guidance/human-interaction.md tmp/idd-migration/
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Write down the page's address (the session that published it has it; it is the artifact the human answers on). List the page's pending answers and its saved answers (in Claude Code, ArtifactData `list` on `pending` and on `answers`) into `tmp/idd-migration/store-before.txt`. Count the answered questions the page shows.
|
|
20
|
+
|
|
21
|
+
## 2. Find the page's source
|
|
22
|
+
|
|
23
|
+
The older practice copied the template to a scratch directory. Find the file that was last published: it holds `const vaQuestion = [`.
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
grep -rl "const vaQuestion" tmp/ 2>/dev/null
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If it is not under `tmp/`, look in the publishing session's scratchpad. Copy it to `tmp/idd-migration/page-before.html`, and count its questions:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
grep -c 'sId: "q' tmp/idd-migration/page-before.html
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 3. Create the IDD files and import the questions
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
~/@idd/bin/idd init "AIOS Open Questions"
|
|
39
|
+
~/@idd/bin/idd import tmp/idd-migration/page-before.html
|
|
40
|
+
~/@idd/bin/idd check
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Edit `idd/page.json` and set `url` to the address from step 1. Confirm the question count is unchanged (`grep -c '"id": "q' idd/questions.json` equals the count from step 2), and read a few imported bodies against the old page: code shown in backticks, quoted markup shown as text.
|
|
44
|
+
|
|
45
|
+
Build and publish to the same address:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
~/@idd/bin/idd build
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Publish `tmp/idd/page.html` to the recorded `url` (`~/@idd/specs/guidance/claude-code.md`, Publishing) and open it. The answered group's count must equal the count from step 1, since the answers are kept by question id. Commit `idd/page.json` and `idd/questions.json`.
|
|
52
|
+
|
|
53
|
+
## 4. Add the IDD line
|
|
54
|
+
|
|
55
|
+
Add this line, on its own line, near the top of the project's `AGENTS.md`:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Read @~/@idd/AGENTS.md before any other work; every decision for the human goes on this project's questions page.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 5. Remove the rules IDD now holds
|
|
62
|
+
|
|
63
|
+
From the rules files, delete each rule that IDD's guidance now states, keeping any fact of the project's own that the rule carried. In AIOS:
|
|
64
|
+
|
|
65
|
+
* `AGENTS.md`, section 1, Communication: delete the rules on pointer answers, a question's example scenario, the standing-principles check, mapping onto an existing element, a ruling that gives a key a new meaning, a card's verbs, a question holding builds, nouns naming a tab, a saved answer being an answer, and a gloss of a ruling. Keep the human's quoted rulings that state AIOS's own principle (his q124, q131 and q172 words) under THE FIRST COMMANDMENT, which IDD's standing-principles check reads, and keep the list of AIOS specs that give keys their meanings as a fact beside it.
|
|
66
|
+
* `CLAUDE.md`: delete the section "The questions page (Claude Code artifacts)".
|
|
67
|
+
|
|
68
|
+
In the spec of guidance for dealing with the human (`specs/guidance/human-interaction.md` in AIOS), an architect deletes the guidance lines IDD now holds and keeps the project's own: in AIOS it keeps When to report, Orthogonality, the two product nouns (dialog, harness) and the on-screen-control rule, and deletes the rest of Questions, His rulings cited, the line on product decisions reaching the specs, and the nouns lines on spec words and on-screen things. A motive line left with no line rooted in it is deleted too (`grep -rn "<m-id>" specs/` prints only the motive line itself). The spec gains one sentence pointing at `~/@idd/AGENTS.md` for questions and answers.
|
|
69
|
+
|
|
70
|
+
## 6. Move the observations
|
|
71
|
+
|
|
72
|
+
For each observation cited only by rules deleted in step 5, list its citations and delete them and the entry:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
npm run spec-map -- --sid o-x2i8vm
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
In AIOS these are o-7ioawk, o-x2i8vm, o-8rmpk8, o-65eyze, o-8qre78, o-il1nvy, o-bpncb3, o-a1t5mg, o-m7spcg, o-oud1hd and o-1asexx; each lives on in `~/@idd/observations.md` under the same id. o-faqe7j stays in AIOS as well, since THE FIRST COMMANDMENT cites it.
|
|
79
|
+
|
|
80
|
+
## 7. Check and compare
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
npm run spec-map -- --assign
|
|
84
|
+
npm run spec-map > tmp/idd-migration/spec-map-after.txt
|
|
85
|
+
npm run spec-map -- --gate
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Lists (34) and (35) are empty, and stale links, unresolved link lines, dangling targets, re-derive, unstamped, underived and malformed are all 0. Compare with the saved state: every rule removed in step 5 has a line in `~/@idd/specs/guidance/` stating it, and the store listing matches `store-before.txt`.
|
|
89
|
+
|
|
90
|
+
## 8. Check a fresh session
|
|
91
|
+
|
|
92
|
+
Start a new session in the project and give it an unrelated first task. Before that task, it reads `idd/page.json`, lists the pending answers and names them in one line. If it does not, check that the IDD line is in `AGENTS.md` outside backticks and that the session's tool loads `AGENTS.md`.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Hosted viewer setup
|
|
2
|
+
|
|
3
|
+
The IDD viewer runs as a small Node HTTP service on Cloud Run. Questionnaire
|
|
4
|
+
files live in each project repository, on branches named `idd-<code-branch>`.
|
|
5
|
+
The viewer discovers those branches through the signed-in user's GitHub App
|
|
6
|
+
access and reads and writes their `idd/` files from the browser.
|
|
7
|
+
|
|
8
|
+
## GitHub App
|
|
9
|
+
|
|
10
|
+
Create a GitHub App for the viewer with these settings:
|
|
11
|
+
|
|
12
|
+
* Homepage URL: `https://interrogation.dev`.
|
|
13
|
+
* Callback URL: `https://interrogation.dev/auth/callback`.
|
|
14
|
+
* User authorization callback URL: the same callback URL.
|
|
15
|
+
* Repository permissions: Contents read and write; Metadata read-only.
|
|
16
|
+
* The viewer requests GitHub's `offline_access` OAuth scope so sessions can
|
|
17
|
+
refresh without adding repository permissions.
|
|
18
|
+
* Webhook URL: `https://interrogation.dev/github/webhook`.
|
|
19
|
+
* Webhook secret: a separate random secret, stored in Google Secret Manager
|
|
20
|
+
under `GITHUB_APP_WEBHOOK_SECRET` in Cloud Run.
|
|
21
|
+
* Subscribe to the Push event.
|
|
22
|
+
* Install the app on each repository whose IDD questionnaire should appear.
|
|
23
|
+
|
|
24
|
+
GitHub sends push events for branches in installed repositories. The viewer
|
|
25
|
+
service validates the webhook signature and only notifies browsers about
|
|
26
|
+
`idd-*` branches. It sends a content-free invalidation over Server-Sent Events;
|
|
27
|
+
each browser then reads current data directly from GitHub. The browser sends
|
|
28
|
+
repository requests directly to GitHub. Its encrypted, HttpOnly authentication
|
|
29
|
+
cookie is sent only to the IDD service's `/auth` endpoints and the service does
|
|
30
|
+
not persist the cookie contents. When push delivery is not configured or the
|
|
31
|
+
event stream is disconnected, the browser checks branch
|
|
32
|
+
heads every 30 seconds until the stream reconnects.
|
|
33
|
+
|
|
34
|
+
The Cloud Run service is mapped to `https://interrogation.dev` and uses a
|
|
35
|
+
Google-managed HTTPS certificate. Set the GitHub App homepage, callback and
|
|
36
|
+
webhook URLs to the custom-domain values in the GitHub App section above.
|
|
37
|
+
|
|
38
|
+
The Cloud Run service needs `GITHUB_APP_CLIENT_ID`,
|
|
39
|
+
`GITHUB_APP_CLIENT_SECRET`, `IDD_OAUTH_STATE_SECRET`,
|
|
40
|
+
`GITHUB_APP_WEBHOOK_SECRET` and `IDD_PUBLIC_URL`. After the GitHub App is
|
|
41
|
+
configured to send push events to the service, set `IDD_GITHUB_PUSH_ENABLED`
|
|
42
|
+
to `true`; otherwise the viewer keeps its branch-head polling fallback. Create independent random
|
|
43
|
+
secrets for the OAuth state and webhook. Bind the client secret, state secret
|
|
44
|
+
and webhook secret from Google Secret Manager; set the client ID and public
|
|
45
|
+
URL as environment variables. Set `IDD_PUBLIC_URL` to
|
|
46
|
+
`https://interrogation.dev`, with no trailing slash. To update an existing
|
|
47
|
+
service, run:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
gcloud run services update idd-service --project idd-platform --region us-east4 \
|
|
51
|
+
--update-env-vars=IDD_PUBLIC_URL=https://interrogation.dev
|
|
52
|
+
```
|
|
53
|
+
Do not commit credentials or pass them as plain deployment environment values.
|
|
54
|
+
|
|
55
|
+
## ChatGPT event notifications
|
|
56
|
+
|
|
57
|
+
The service's `/mcp` endpoint exposes an `idd.data.changed` MCP Event for
|
|
58
|
+
ChatGPT Work chats. Enable the Firestore API, create the default Firestore
|
|
59
|
+
database in Native mode, and grant the Cloud Run service account Firestore
|
|
60
|
+
read/write access so subscriptions persist across service restarts. Add the
|
|
61
|
+
hosted MCP endpoint as a ChatGPT custom connector and enable its event
|
|
62
|
+
subscriptions. The event is global and carries no project or answer content;
|
|
63
|
+
instruct a subscribed chat to check the IDD answers for the project it is
|
|
64
|
+
working on when an event arrives.
|
|
65
|
+
|
|
66
|
+
After Firestore is ready, set `IDD_MCP_EVENTS_ENABLED=true` on Cloud Run. The
|
|
67
|
+
ChatGPT connector URL is `https://interrogation.dev/mcp`.
|
|
68
|
+
|
|
69
|
+
Claude.ai's documented remote MCP connector does not support MCP Events. A
|
|
70
|
+
Claude.ai chat can use the standard `idd_wait_for_change` tool during an
|
|
71
|
+
active conversation; its tool call returns when a push arrives or after four
|
|
72
|
+
minutes. Add `https://interrogation.dev/mcp` as a custom connector under
|
|
73
|
+
Settings > Connectors. Claude Code can use the local `idd wait` command
|
|
74
|
+
instead.
|
|
75
|
+
|
|
76
|
+
## Deploy
|
|
77
|
+
|
|
78
|
+
Use the deployment script from the IDD checkout. It requires the Google Cloud
|
|
79
|
+
CLI (`gcloud`) installed and authenticated to a Google account with permission
|
|
80
|
+
to deploy Cloud Run services in the `idd-platform` project. Run:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
npm run deploy
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The script builds the root Dockerfile and deploys `idd-service` in
|
|
87
|
+
`us-east4`, with at most one instance and concurrency 1000. It preserves the
|
|
88
|
+
service's existing environment variables, Secret Manager bindings, and access
|
|
89
|
+
policy. It does not take credentials or secret values as arguments. The
|
|
90
|
+
existing instance limit keeps the webhook and its open event streams on one
|
|
91
|
+
instance; browsers reconnect and refresh after a restart.
|
|
92
|
+
|
|
93
|
+
To print the deployed service URL, run:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
gcloud run services describe idd-service --project idd-platform --region us-east4 --format='value(status.url)'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Add the GitHub App client ID as an environment variable and bind the client
|
|
100
|
+
secret, OAuth state secret, and webhook secret from Secret Manager in the Cloud
|
|
101
|
+
Run service configuration. Later deployments with `npm run deploy` preserve
|
|
102
|
+
those settings.
|
|
103
|
+
|
|
104
|
+
Set Cloud Run ingress to the intended public access policy. Firestore holds
|
|
105
|
+
only MCP event subscription metadata; the service stores no questionnaire or
|
|
106
|
+
user-token data server-side. The OAuth callback uses the app secret to
|
|
107
|
+
exchange a one-use authorization code, sends the access token to the opener
|
|
108
|
+
window, and writes the access and optional refresh tokens into an encrypted,
|
|
109
|
+
Secure, HttpOnly, SameSite cookie. On page load, `/auth/session` restores the
|
|
110
|
+
access token into JavaScript memory and refreshes it with GitHub when needed.
|
|
111
|
+
GitHub access tokens last eight hours and refresh tokens last six months;
|
|
112
|
+
after the refresh token expires, sign in again. Signing out clears the cookie.
|
|
113
|
+
Keep `IDD_OAUTH_STATE_SECRET` stable across deployments so existing cookies
|
|
114
|
+
can be decrypted.
|
|
115
|
+
|
|
116
|
+
## Publish a project questionnaire
|
|
117
|
+
|
|
118
|
+
Create the IDD data branch matching the code branch, for example
|
|
119
|
+
`idd-main` for `main` and `idd-feature/login` for `feature/login`. Commit the
|
|
120
|
+
questionnaire's `idd/` JSON files there and push the branch to the same
|
|
121
|
+
repository. The viewer will discover it for users who can access the
|
|
122
|
+
repository through the GitHub App. Answer submissions are committed by the
|
|
123
|
+
browser, so no GitHub credential is needed in the agent environment.
|
|
124
|
+
|
|
125
|
+
Use worktrees so IDD branches contain questionnaire files without a second
|
|
126
|
+
copy of the source tree. For a repository's first code branch, create its
|
|
127
|
+
matching IDD branch as an orphan with
|
|
128
|
+
`git worktree add --orphan idd-<branch> tmp/idd-data`, initialize its
|
|
129
|
+
question files there with `npm exec -- idd init`, then stage, commit
|
|
130
|
+
and push those files to `refs/heads/idd-<branch>`. Never copy IDD data into
|
|
131
|
+
the code branch. The data worktree can ignore generated files under `tmp/`.
|
|
132
|
+
For a code branch based on another code branch, create its matching IDD
|
|
133
|
+
branch from that base branch's IDD branch with
|
|
134
|
+
`git worktree add -b idd-<branch> tmp/idd-data idd-<base-branch>`; this keeps
|
|
135
|
+
the IDD branch histories mergeable. Set `idd/page.json`'s `branchHash` to the
|
|
136
|
+
new code branch's hash, but leave inherited questions' `branchHash` values
|
|
137
|
+
unchanged; new questions use the new page hash. For later updates, add the existing IDD
|
|
138
|
+
branch as a worktree, edit its `idd/` files there, commit and push, then
|
|
139
|
+
remove the temporary worktree. Do not copy the IDD data branch into the code
|
|
140
|
+
branch.
|
|
141
|
+
|
|
142
|
+
Initialize question ids with the branch hash computed from the GitHub
|
|
143
|
+
repository's numeric id and full code ref by running
|
|
144
|
+
`npm exec -- idd branch-hash <repository-id> refs/heads/<branch>`, then
|
|
145
|
+
pass the printed hash to `npm exec -- idd init`.
|
|
146
|
+
|
|
147
|
+
The viewer never merges code branches. The agent compares the corresponding
|
|
148
|
+
IDD branches, reconciles duplicate, obsolete or conflicting questions, and
|
|
149
|
+
completes the code decision before completing the code merge, as
|
|
150
|
+
`specs/guidance/agent-merge.md` specifies.
|
|
151
|
+
|
|
152
|
+
## Agent-aware merges
|
|
153
|
+
|
|
154
|
+
Before a project uses the merge gate, run `npm exec -- idd-merge-hook install`
|
|
155
|
+
from its root and commit the generated `.githooks/` files. Each participant
|
|
156
|
+
runs the installer once in their clone to set Git's local `core.hooksPath`.
|
|
157
|
+
Use `git merge --no-ff` for code branches. If the hook stops a merge, the
|
|
158
|
+
agent first merges the source IDD branch into the target IDD branch, resolves
|
|
159
|
+
file conflicts, consolidates duplicate or obsolete questions, and resolves
|
|
160
|
+
answer conflicts. If the decisions still disagree, it adds a clarifying
|
|
161
|
+
question and waits for the answer and implementation. Once reconciliation is
|
|
162
|
+
complete, it pushes the target IDD branch and runs
|
|
163
|
+
`npm exec -- idd-merge-hook reviewed`. The pre-merge hook then permits the code
|
|
164
|
+
merge, and the post-merge hook confirms the same IDD history was reviewed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@debonet/idd",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Interrogation-driven development: the questions page and its command",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/debonet/idd"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"INSTRUCTIONS.md",
|
|
14
|
+
"README.md",
|
|
15
|
+
"bin/",
|
|
16
|
+
"docs/existing-page-migration.md",
|
|
17
|
+
"docs/hosted-viewer.md",
|
|
18
|
+
"scripts/check.js",
|
|
19
|
+
"scripts/commands.js",
|
|
20
|
+
"scripts/html-text.js",
|
|
21
|
+
"scripts/import-page.js",
|
|
22
|
+
"scripts/merge-hook.js",
|
|
23
|
+
"scripts/page-build.js",
|
|
24
|
+
"scripts/project-lock.js",
|
|
25
|
+
"specs/",
|
|
26
|
+
"templates/"
|
|
27
|
+
],
|
|
28
|
+
"workspaces": [
|
|
29
|
+
"web"
|
|
30
|
+
],
|
|
31
|
+
"bin": {
|
|
32
|
+
"idd": "bin/idd",
|
|
33
|
+
"idd-merge-hook": "bin/idd-merge-hook"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"start": "node web/server.js",
|
|
37
|
+
"build:web": "node scripts/build-web.js",
|
|
38
|
+
"deploy": "npm run build:web && node scripts/deploy.js",
|
|
39
|
+
"test": "npm run build:web && jest",
|
|
40
|
+
"spec-map": "$HOME/@concord/bin/spec-map",
|
|
41
|
+
"spec-coverage": "$HOME/@concord/bin/spec-coverage",
|
|
42
|
+
"hook-install": "$HOME/@concord/bin/concord-hook install"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"esbuild": "^0.28.2",
|
|
49
|
+
"jest": "^29.7.0",
|
|
50
|
+
"jsdom": "^24.1.0"
|
|
51
|
+
},
|
|
52
|
+
"jest": {
|
|
53
|
+
"rootDir": ".",
|
|
54
|
+
"roots": [
|
|
55
|
+
"<rootDir>/test"
|
|
56
|
+
],
|
|
57
|
+
"testEnvironment": "node"
|
|
58
|
+
}
|
|
59
|
+
}
|