@debonet/idd 0.0.0-stage → 0.1.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.
@@ -0,0 +1,738 @@
1
+ # Hosted questionnaire
2
+
3
+ ## Purpose
4
+
5
+ The hosted IDD page lets a person review and answer questionnaires stored in
6
+ GitHub projects, and lets that person see questionnaires from several
7
+ projects in one viewer.
8
+
9
+ ## His words
10
+
11
+ > {#m-3jzy1x} RULING (CEO) 2026-11-05: “Seems like CloudRun is the way to go.”
12
+
13
+ > {#m-7wyw60} RULING (CEO) 2026-11-05: “can the comms go directly
14
+ > from the browser? so the form generates json in the browser, and the
15
+ > browser submits the change directly to github?”
16
+
17
+ > {#m-ol5xyr} RULING (CEO) 2026-11-05: “Prior answers need to always
18
+ > be presented as text and never as HTML.”
19
+
20
+ > {#m-4as0w8} RULING (CEO) 2026-11-05: “But if it's a separate
21
+ > repository we can't leverage github code repository permissions for
22
+ > access control.”
23
+
24
+ > {#m-3jz9c9} RULING (CEO), 2026-11-08, IDD question
25
+ > `3e4177d4bd9b9d93457d3c254374b354d1874ed32b17391f3b4433bd92db78be`:
26
+ > “Which projects should appear first on the IDD page? After you sign in to
27
+ > the IDD page, it lists project questionnaires you can read. A project can
28
+ > have open questions, rejected answers, or only answered questions. If
29
+ > several projects need your attention, which project should the page put at
30
+ > the top? A) Projects with unanswered questions first, sorted by the oldest
31
+ > question. B) Projects where the agent is marked blocked first, then other
32
+ > unanswered questions by age. C) All projects in alphabetical order, with
33
+ > open and conflict counts shown.” His answer: “B — Projects where the agent
34
+ > is marked blocked first, then other unanswered questions by age.”
35
+
36
+ > {#m-2wp6gd} BUG REPORT (CEO), 2026-11-08: “This does not count as a
37
+ > conflict: [the same question's accepted answer and a rejected submission
38
+ > with identical choice B and an empty note].”
39
+
40
+ > {#m-65v6r2} BUG REPORT (CEO), 2026-11-08: “Returning to ‘all projects’
41
+ > effectively unsubmits my prior answers.”
42
+
43
+ > {#m-c37rfq} RULING (CEO), 2026-11-08: “The web page is alreay open. It
44
+ > should somehow know to reload.”
45
+
46
+ > {#m-umb15o} RULING (CEO), 2026-11-08, IDD question
47
+ > `de91a974a87d89a88e487cbe7650fbdb743f7259ce32fe59fc6f3818d708c658`:
48
+ > “How should a project writer resolve a conflicting answer? A question has
49
+ > an accepted answer and a different later answer was rejected. What should
50
+ > the IDD page let a project writer do to resolve this conflict? A) Keep
51
+ > accepted answer and mark rejected submission resolved. B) Accept rejected
52
+ > submission instead, preserving both answers in history. C) Ask a new
53
+ > clarifying question and keep both submissions until answered.” His answer:
54
+ > “A”. His note: “Huh? What is a ‘project writer’? What do you mean by
55
+ > ‘accepted’ and ‘rejected’ (Do you mean one was first and the other was a
56
+ > conflict?)
57
+ >
58
+ > Look, here's what should happen:
59
+ >
60
+ > if a question is answered and then re-answered later (either by another
61
+ > session, or someone revisits an already answered question and changes their
62
+ > answer) the response should be a follow on questions to clarify what to do.
63
+ > Something like: ‘on date X answer Y was chosen, but on date Z, answer A was
64
+ > chosen. Given that Y has already been implemented and subsequent decisions
65
+ > made based on that, should we now switch to A?”
66
+
67
+ > {#m-j48adi} RULING (CEO), 2026-11-08: “previously answered questions
68
+ > should be ‘re-visitable’. i.e. I should be able to change prior answers
69
+ > (causing a conflict, which triggers a clarification sequence)”
70
+
71
+ > {#m-1nrz2d} RULING (CEO), 2026-11-09: “So you need to figure out how to send a
72
+ > notification from webpage to the codex (or claude code, chatgpt.com,
73
+ > claude.ai) session”
74
+
75
+ > {#m-g75yf0} RULING (CEO), 2026-11-09: “So let's fix it. `idd-page` should just be
76
+ > `idd`. For ChatGPT.com or Claude.ai, an idle chat can’t currently be
77
+ > addressed through this page: it would need a supported integration in that
78
+ > host. Such things exist. Find the mechanism and use it.”
79
+
80
+ > {#m-551a7e} RULING (CEO), 2026-11-09: “answers should get letters so they can
81
+ > be referenced in the note, e.g. A, B, C, etc.”
82
+
83
+ > {#m-t4tzrb} RULING (CEO), 2026-11-09: “Also, make it so that the IDD page gets a
84
+ > cookie, so that when I open it again I don't need to re-login every time.”
85
+
86
+ > {#m-zgomvq} RULING (CEO), 2026-11-10: “We may need a button to give the app
87
+ > access to more repositories. I think I may have only approved the one
88
+ > project (idd) at this point.”
89
+
90
+ > {#m-h21kou} RULING (CEO), 2026-11-10: “Also, don't show the branch in the
91
+ > special case where it is \"main\"
92
+ >
93
+ > Design issues:
94
+ > * the \"Give IDD access to repositories\" button is huge and in the wrong
95
+ > spot. It should live at the top of the \"Your questionnaires\" dashboard.
96
+ > * make the order on the dashboard: conflicts, unanswered, answered. Make
97
+ > the conflict and unanswered numbers much bigger than the text. Color them
98
+ > red, and blue (or some theme-appropriate colorization indicating
99
+ > very-important, important), unanswered remains small and default colored.
100
+ > * what does \"no active agent status\" mean? It is way to prominent. If
101
+ > needed, put on the right side and use short phrases (e.g. \"none active\")
102
+ > and hover can show more info.
103
+ > * when in a project the title should be \"Project: <project>, Branch:
104
+ > <branch> Questions\", this stuff should go away:
105
+ >
106
+ > Questionnaire data updated from GitHub.
107
+ >
108
+ > ← All projects
109
+ > debonet/aios · main
110
+ > Questionnaire data is on idd-main
111
+ >
112
+ > * the return arrow should be above the title and should read \"<-- dashboard\"
113
+ > (with a real arrow)
114
+ > * \"Questionnaires are stored in their GitHub project repositories.\" should
115
+ > be removed
116
+ > * add a hamburger menu that includes:
117
+ > either:
118
+ > * sign out
119
+ > * signed in as <username>
120
+ > or:
121
+ > * sign in
122
+ >
123
+ > and:
124
+ > * add repositories
125
+ > * top repositories (top 10 sorted by date of conflicts, then unanswered)
126
+ > * <repo 1>
127
+ > * <repo 2>
128
+ > * FAQ
129
+ > * About
130
+ >
131
+ > * make the About page basically be a digest of the README that answers: why?
132
+ > what? how?
133
+ > * make the FAQ include questions about security and access (where are keys
134
+ > kept? questions and answers kept)
135
+ > * make the IDD in the upper left bigger, and use the logo (Logo version),
136
+ > which I will put in the docs/ directory
137
+ > * make a favicon from the \"Icon\" version of the logo”
138
+
139
+ > {#m-2cjvpr} BUG REPORT (CEO), 2026-11-10: “Fix questions so that all the text is
140
+ > to the right of the radio button on wrapped lines. I.e. the text should be
141
+ > left justified to the right of the radio button”
142
+
143
+ > {#m-w1kbnf} BUG REPORT (CEO), 2026-11-10: “When you click
144
+ > \"submit answer\" the question box should roll-up and disappear immediatley
145
+ > and the networking should happen in the background.”
146
+
147
+ > {#m-5saq28} BUG REPORT (CEO), 2026-11-10: “The rollup on submit is not working.
148
+ > It should take a second or two. Currently the question immediately
149
+ > disappears, which is jarring and confusing because it is immediately
150
+ > replaced with the question below. Instead it should roll-up (shrink
151
+ > vertically, as in the jquery-style animation) and the question below rising
152
+ > with it so that it is clear what is happening.”
153
+
154
+ > {#m-loh9m9} BUG REPORT (CEO), 2026-11-10: “doing back to the dashboard still
155
+ > yields and empty screen?”
156
+
157
+ > {#m-4fn63n} “Can we cache/store the projects in a cookie so that there's no delay
158
+ > when you reload or go back to the dashboard? When the fetch completes it can
159
+ > update the display and cookie.”
160
+
161
+ > {#m-65brxv} “It would be useful if the \"<-- dashboard\" could also indicate how
162
+ > many projects have conflicts and/or questions pending. Some number that tells
163
+ > how mnay projects need your attention.”
164
+
165
+ > {#m-3xcl02} BUG REPORT (CEO), 2026-11-11: “The count after "<-- dashboard" should
166
+ > not include the current project!”
167
+
168
+ > {#m-n9dd7y} “Drop the \"Project: \" in the header”
169
+
170
+ > {#m-i0grng} BUG REPORT (CEO), 2026-11-10: “The logo and favicon are not
171
+ > working”
172
+
173
+ > {#m-j5r1fg} “I moved the old logos out of the way and replaced them with a single
174
+ > cleaner logo. Use that for both the page and the favicon. It no longer
175
+ > contains text, so for the logo at the top of the page add in html "IDD
176
+ > Interrogation-Driven Development" in some attrative way”
177
+
178
+ > {#m-rhr8be} “That should be a standard part of your unit test suite.”
179
+
180
+ > {#m-v12ugx} “Use the new docs/Question*png image as the favicon”
181
+
182
+ > {#m-zanwxq} “So \"Question Histor\" should instead be
183
+ > \"depricated questions\" or \"revisited questions\" or something like that.”
184
+
185
+ > {#m-3fsbff} “The theme selector is too prominent. Move it to the
186
+ > right side, on the same line as the \"<-- dashboard\"”
187
+
188
+ > {#m-8drgj4} RULING (CEO), 2026-11-10: “We should also have a
189
+ > splash/informational page that shows up when you're not logged in. And
190
+ > when you're logged in, you go directly to your dashboard.”
191
+ >
192
+ > {#m-cba3po} RULING (CEO), 2026-11-10: “On the splash page, show some
193
+ > screenshots with fake questions and answers, using the various themes.
194
+ > Put them in drop-shadow'd rounded rectangle gradient-alpha (fade at top)
195
+ > image containers.”
196
+
197
+ > {#m-1um0ef} RULING (CEO), 2026-11-11: “blurb below is too wordy. TL;DR.
198
+ > Make it short punchy sentences. something like: ‘You provide initial
199
+ > spec, agent starts coding, posts async questions, you answer to guide the
200
+ > development’ but even punchier”
201
+
202
+ > {#m-jp4via} RULING (CEO), 2026-11-11: “the key motivator here is:
203
+ > human intelligence is the limited resource. Don't waste it reading walls
204
+ > of text. Critical issues surfaced. Compactly, clearly, and decisively.
205
+ > Human judgement is captured efficiently. --> Use it in why and elsewhere”
206
+
207
+ > {#m-yj5thl} RULING (CEO), 2026-11-11: “themes is not the big
208
+ > feature. The big features are:
209
+ > * secure
210
+ > * access to questions matches developer's access to the code
211
+ > * works on any github project public or private
212
+ > * works from anywhere -- laptops, tablets, phones
213
+ > * you dont need to set up a server
214
+ > * supports branches, question merging, conflict resolution
215
+ > --> make each of the example images demonstrate/visualize a different
216
+ > one of those things, and do it with different themes (so theming isn't
217
+ > the feature being promoted). Your goal is to show examples how the
218
+ > system can be used”
219
+
220
+ > {#m-cpqj0v} RULING (CEO), 2026-11-11: “add a teaser at the bottom
221
+ > that IDD optionally integrates with the ConcordSTC agentic engineerign
222
+ > approach.”
223
+
224
+ > {#m-hfp7kb} RULING (CEO), 2026-11-11: “The why, what, how boxes were good.
225
+ > Drop the \"Why IDD\". Keep the Human judgement text, then below it add back
226
+ > Why, How, What boxes, with very short sentences:
227
+ > Why: Efficient capture of human judgement
228
+ > What: No walls of text. Just crisp questions
229
+ > How: Agent asks when it needs, you answer when you can.”
230
+
231
+ > {#m-nnxwab} RULING (CEO), 2026-11-11: “The examples need to be examples.
232
+ > You've mixed examples of the product with key features. For the features,
233
+ > list them in attractive boxes (not images of that kind of look like the
234
+ > product). Again the list from above, but make crisper:
235
+ > * secure
236
+ > * access to questions matches developer's access to the code
237
+ > * works on any github project public or private
238
+ > * work from anywhere -- laptops, tablets, phones
239
+ > * you dont need to set up a server
240
+ > * supports branches, question merging, conflict resolution
241
+ >
242
+ > Then show examples of semi-real things:
243
+ > * the \"when should reminders arrive?\" question is a good one
244
+ > * another one about using one package over another
245
+ > * another one showing a conflict resolution (you said X, bob said Y, which
246
+ > is correct?)”
247
+
248
+ > {#m-3sqckb} “Can you pick a theme that is somewhat more attractive and interesting?
249
+ > Perhaps the colors you use for the silk theme, but with a sans serif font.
250
+ > Also, have greater size variations in the fonts”
251
+
252
+ > {#m-ikc4ps} “No that is too \"brown\", look at the openai.com/about page, and use a
253
+ > theme closer to that”
254
+
255
+ > {#m-ry1hp7} BUG REPORT (CEO), 2026-11-12: “BUG: conflict
256
+ > resolution is not working. I'm clicking submit changed answer, and another
257
+ > conflict shows up. Also, the rejected submissions are showing up in the
258
+ > conflicts area.”
259
+
260
+ > {#m-4w4679} FEATURE (CEO), 2026-11-12: “reverse the order
261
+ > of the answered questions, so the most recent is at the top.”
262
+
263
+ > {#m-o26kii} BUG REPORT (CEO), 2026-11-12: “the
264
+ > \"<-- dashboard\" is still showing a needs attention count that includes
265
+ > the current project.”
266
+
267
+ > {#m-awh12l} BUG REPORT (CEO), 2026-11-12: “take a look at the idd file in
268
+ > ~/@aois. It seems to contain a conflict which keeps reoccurring every time I
269
+ > \"resolve\" it.”
270
+
271
+ > {#m-hvgu3e} RULING (CEO), 2026-11-12: “Ohh. So there's two different things:
272
+ > * conflicts to be resolved
273
+ > * conflicts that have been resolved but have not yet been addressed
274
+ > The latter seems like it should just go into the answered section. Answered
275
+ > questions also may not yet have been addressed, but they leave the open
276
+ > questions section.”
277
+
278
+ > {#m-yxktyi} RULING (CEO), 2026-11-12: “Can we add a ‘thoughts and
279
+ > observations’ section, which is essentially a perpetually open question
280
+ > of what do you have in mind? and just provides a text box. When you write
281
+ > in it, it generates a new question-id (with essentially an empty question,
282
+ > maybe the date) and the statement you've made? That way you can remotely
283
+ > send ideas and any active agent can pick them up and work on them (and
284
+ > presumably ask followup questions about them if needed)”
285
+
286
+ > {#m-2cwth4} RULING (CEO), 2026-11-12: “That information should somehow be
287
+ > embedded in the splash page so that I can tell a model ‘go look at
288
+ > interrogation.dev and let's use it’.”
289
+
290
+ ## Hosted page
291
+
292
+ * {#s-71l9ho <m-3jzy1x@623b849} The IDD viewer and project questionnaires are
293
+ served from an IDD web application deployed on Google Cloud Run.
294
+ * {#s-1lggg7 <arch} The viewer lists the projects the signed-in GitHub
295
+ user can read that have an IDD questionnaire, and links each project to
296
+ its questionnaire.
297
+ * {#s-7f2p1j <arch} A project questionnaire page identifies its GitHub
298
+ repository and code branch; the page shows that branch's IDD questionnaire.
299
+ * {#s-6k70cj <arch} The dashboard shows each project's unanswered, conflicting, and
300
+ answered questions, and the time unanswered questions have been waiting.
301
+ * {#s-0kqa6m <arch,m-h21kou@7fe10b2} Dashboard question counts appear in this order:
302
+ conflicts, unanswered, answered. Conflict and unanswered numbers are larger
303
+ than their labels; conflicts use the theme's alert color and unanswered
304
+ counts use the theme's accent color. Answered counts stay small and use the
305
+ default subdued color.
306
+ * {#s-c128mc <arch,m-h21kou@7fe10b2} Agent status is aligned at the right of each
307
+ project row and uses a short label such as `none active`, `working`, or
308
+ `blocked`; its title tooltip provides the detailed session status.
309
+ * {#s-nf173i <arch,m-h21kou@7fe10b2} Project and questionnaire headings omit the
310
+ branch label when the code branch is `main`; other branches remain visible.
311
+ * {#s-eeqrcf <arch,m-h21kou@7fe10b2,m-n9dd7y@66937d7} A questionnaire heading reads
312
+ `<repository>, Branch: <branch> Questions`, omitting `, Branch:
313
+ <branch>` for `main`. Above it, one back link returns to the dashboard.
314
+ The questionnaire view does not show the success notice, the IDD data
315
+ branch name, or another project/branch line.
316
+ * {#s-pgrj98 <m-65brxv@d2a98c2,m-o26kii@87c1cd6} The questionnaire's
317
+ dashboard return link reads `← dashboard · <n> need attention`, where `<n>`
318
+ counts each other repository and IDD branch with at least one unanswered
319
+ question or unresolved answer conflict once, excluding the current
320
+ repository and IDD branch by their stable identities.
321
+ * {#s-ajo3ld <m-3fsbff@a314ab9} The theme selector shares a row with the dashboard
322
+ back link and is aligned at the right side of that row.
323
+ * {#s-kmiped <m-zgomvq@a9d3d33,m-h21kou@7fe10b2} The signed-in dashboard places a
324
+ compact `Add repositories` link at the top of `Your questionnaires`; the
325
+ hamburger menu also contains that link.
326
+ * {#s-prsnbh <arch,m-h21kou@7fe10b2} A hamburger menu opens and closes an accessible
327
+ navigation panel. It shows either sign-in or the signed-in username and
328
+ sign-out action, an Add repositories link, the top ten repositories, FAQ,
329
+ and About. The panel uses the compact spacing, aligned text, and clear
330
+ hierarchy of a standard graphical application menu; repository links are
331
+ indented beneath Top repositories with tree lines showing their parentage.
332
+ The final repository connector ends in an L, without a vertical line
333
+ continuing below it.
334
+ * {#s-sb8f7i <arch,m-h21kou@7fe10b2} The menu lists at most ten distinct
335
+ repositories with questionnaires. Repositories with conflicts come first,
336
+ sorted by their latest conflict time descending; the rest are sorted by
337
+ unanswered question count descending, then oldest unanswered question
338
+ first, then repository name. A repository link opens its most urgent
339
+ questionnaire branch.
340
+ * {#s-ia2mkv <arch,m-h21kou@7fe10b2} The About page presents a concise digest of
341
+ the README's Why, What and How sections.
342
+ * {#s-kmzltz <arch,m-h21kou@7fe10b2} The FAQ answers who can read and answer,
343
+ where GitHub credentials and app secrets are kept, and where questions and
344
+ answers are stored.
345
+ * {#s-vgd6wr <m-j5r1fg@473daea,m-v12ugx@63766d4} The provided Interrogation Flow Decision Icon image is used as
346
+ the upper-left brand mark beside visible HTML text reading “IDD
347
+ Interrogation-Driven Development”; the Question Bubble Decision Flow image
348
+ is used as the favicon.
349
+ * {#s-3htunx <m-i0grng@584ee4f} The logo and favicon URLs referenced by the viewer return
350
+ their PNG image files with the `image/png` media type.
351
+ * {#s-gj59q3 <m-zanwxq@4e60fc3} The collapsed question history section is labeled
352
+ `Superseded questions`.
353
+ * {#s-fn4x75 <arch,m-h21kou@7fe10b2} The footer sentence `Questionnaires are stored
354
+ in their GitHub project repositories.` is not displayed.
355
+ * {#s-hun225 <arch,m-ec324x@c9504b3} Each hosted question displays the reserved X option
356
+ from `specs/project-files.md` last, using its fixed text. A legacy question
357
+ without X receives the same displayed option without changing its stored
358
+ question or id.
359
+ * {#s-qpdk8t <arch,m-ec324x@c9504b3} A question with no saved answer and no unsent
360
+ draft starts with no option selected. An existing answer or draft remains
361
+ selected when the form is revisited or refreshed.
362
+ * {#s-li6mcw <m-2cjvpr@8bfc299} Each answer option places its radio button in a left column and
363
+ all of its label text in a right column; wrapped lines start at the same
364
+ left edge as the first line of label text.
365
+ * {#s-1ci45n <m-w1kbnf@3fb9f61,m-5saq28@dd97235} Submitting an answer starts a visible vertical
366
+ collapse of its question box that lasts one to two seconds, with following
367
+ content rising as the box shrinks, while the network request runs at the
368
+ same time; a failed request restores the question box and its draft.
369
+ * {#s-ifpl8z <m-3jz9c9@647adb8} **Dashboard order.** Projects with an agent session
370
+ marked blocked appear first. Other projects with unanswered questions
371
+ follow, ordered by the creation time of their oldest unanswered question.
372
+ Projects with no unanswered questions appear last.
373
+ * {#s-yl7soe <arch} Projects with the same ordering priority are sorted by
374
+ repository full name and then code branch.
375
+ * {#s-3fmok8 <m-65v6r2@23373a9} When a person returns to All projects and
376
+ reopens a questionnaire during the same page session, the viewer preserves
377
+ any unsubmitted choice and note for each open question.
378
+ * {#s-vb6pz0 <m-loh9m9@271a655} Returning from a questionnaire to the dashboard displays the
379
+ available project branches.
380
+ * {#s-lqwhd5 <m-4fn63n@ead29bc} When project summaries saved in browser local storage exist for
381
+ the signed-in GitHub account, the dashboard displays them before fresh
382
+ repository data finishes loading, then updates the display and saved
383
+ summaries with the fetched project data.
384
+ * {#s-qv9ghz <arch} The dashboard cache is scoped to the signed-in GitHub account and
385
+ contains no access tokens, question text or answers.
386
+ * {#s-8j6gdw <m-c37rfq@5dbe195} While the viewer is open and signed in, it
387
+ automatically detects changes to IDD branches and refreshes their displayed
388
+ questionnaire data without requiring a page reload. It preserves unsent
389
+ answer drafts and the current dashboard or questionnaire view.
390
+ * {#s-1v9p2k <m-c37rfq@5dbe195} The GitHub App's push webhook is validated with
391
+ its configured HMAC secret. Only pushes to refs beginning
392
+ `refs/heads/idd-` trigger a viewer notification; webhook payloads are not
393
+ forwarded to browsers.
394
+ * {#s-jmz4e7 <m-c37rfq@5dbe195} The hosted service sends a generic invalidation
395
+ event to connected viewers and active command waiters over a same-origin
396
+ Server-Sent Events stream. The event contains no repository, branch,
397
+ commit, or answer data.
398
+ * {#s-mj541y <arch} When an agent is waiting for an answer through `idd wait`,
399
+ the hosted service's invalidation event makes that waiting command check
400
+ the remote IDD branch immediately; the answer is read from GitHub, not
401
+ from the event.
402
+ * {#s-9gymp2 <m-1nrz2d@b86ec13,m-g75yf0@44f7e6c} ChatGPT Work chats can
403
+ subscribe to the hosted `idd.data.changed` MCP event; when a matching
404
+ IDD-branch push arrives, ChatGPT delivers the event to that subscribed chat
405
+ and follows the user's instruction for what to do next.
406
+ * {#s-v65h8r <arch} The hosted MCP event contains only a generic change
407
+ indicator; it carries no repository, branch, commit, question, answer, or
408
+ user data.
409
+ * {#s-4vnngz <arch} The hosted MCP event is global: every active subscription is
410
+ notified for every push to any `idd-*` branch.
411
+ * {#s-fda7vp <arch} The `/mcp` endpoint advertises MCP Events during
412
+ initialization and lists one webhook-delivered `idd.data.changed` event
413
+ with no subscription arguments and a payload containing only
414
+ `{"changed":true}`.
415
+ * {#s-jzlic8 <arch} The `/mcp` endpoint exposes the standard MCP tool
416
+ `idd_wait_for_change`; an active call waits up to 240 seconds for an IDD
417
+ branch push and returns only whether a change occurred.
418
+ * {#s-udvxd8 <arch} The hosted service stores MCP event subscriptions durably,
419
+ including their callback URL, signing secret, event name, and expiration,
420
+ and retains them across Cloud Run restarts.
421
+ * {#s-zsz7sy <arch} The hosted service grants MCP event subscriptions a finite
422
+ expiration and refreshes an existing subscription idempotently when ChatGPT
423
+ repeats its subscription request.
424
+ * {#s-95yj75 <arch} The MCP event endpoint validates callback destinations as
425
+ public HTTPS addresses, verifies each callback with a fresh signed
426
+ challenge before storing a subscription, and signs event deliveries using
427
+ Standard Webhooks.
428
+ * {#s-mome2c <arch} A user can unsubscribe from an MCP event; repeated
429
+ unsubscribe requests succeed without changing other subscriptions.
430
+ * {#s-mter3r <arch} A Claude.ai custom connector can use
431
+ `idd_wait_for_change` to receive the generic change result while a tool call
432
+ is active; Claude.ai does not support the MCP Events subscription used for
433
+ unsolicited delivery to an idle chat.
434
+ * {#s-8sk5lv <m-c37rfq@5dbe195} A signed-in browser reloads its project data
435
+ directly from GitHub when it receives an invalidation event.
436
+ * {#s-6sl6e9 <m-c37rfq@5dbe195} When push notifications are unavailable or the
437
+ event stream is disconnected, the browser checks IDD branch heads every 30
438
+ seconds and refreshes when a head changes. A reconnected event stream causes
439
+ an immediate refresh to recover missed notifications.
440
+ * {#s-u8f4vi <m-umb15o@4ae4e2f,m-j48adi@77b2d25} A person can revisit an answered question in the
441
+ collapsed Answered section, see its current answer, and submit a changed
442
+ choice or note; the form starts with the current answer selected and note
443
+ filled in.
444
+ * {#s-46zdl6 <m-551a7e@e3167a4} Each option in the hosted questionnaire displays its key followed
445
+ by a period and a space before its text, such as `A. First`, so the person
446
+ can refer to the key in the answer note.
447
+ * {#s-ax24rw <arch} A project becomes visible in a user's dashboard when an IDD
448
+ questionnaire branch is pushed to a repository the user can read; no key
449
+ is copied into the viewer.
450
+ * {#s-foxumh <arch} The viewer places rejected answer submissions that differ from
451
+ the accepted answer in a Conflicts section, unanswered questions in an
452
+ Unanswered section, and accepted questions in a collapsed Answered section.
453
+ An omitted note and an empty note are the same answer for conflict detection.
454
+ * {#s-10icw5 <m-umb15o@4ae4e2f} A changed answer to a previously answered question
455
+ appears as a conflict while the currently committed answer remains visible
456
+ as the prior ruling.
457
+ * {#s-68mj1g <arch} A question with an unresolved answer conflict appears in the
458
+ Conflicts section and cannot be resubmitted from that card. When its
459
+ clarification answer is recorded, the agent resolves the conflict and the
460
+ question appears in the Answered section, even while the agent has not yet
461
+ carried out the ruling.
462
+ * {#s-4p12mq <m-4w4679@821d091} The collapsed Answered
463
+ section orders questions by accepted-answer timestamp, newest first.
464
+ * {#s-i9eyq7 <arch} Anyone who can read the GitHub repository can read its
465
+ questionnaire; only a user with repository write permission can submit an
466
+ answer.
467
+ * {#s-gu4cxa <arch} The project agent adds its questionnaire to
468
+ the viewer by pushing the `idd-<branch>` branch to the project repository;
469
+ no user copies a repository key or questionnaire token.
470
+ * {#s-0zk4qi <arch} Each project questionnaire has an always-visible “Thoughts and
471
+ observations” section with a text box that invites the person to share an
472
+ idea or observation. Submitting non-empty text appends a thought to that
473
+ project's current IDD branch; the form remains available for another
474
+ submission.
475
+ * {#s-zexwsh <arch} The section displays submitted thoughts with their stable ids,
476
+ submission times, and text as plain text. It does not display thought text
477
+ as HTML or treat thoughts as questions requiring an answer.
478
+ * {#s-pla1x4 <arch} Submitting a thought writes directly from the browser to the
479
+ repository's `idd/thoughts.json` on its IDD branch using GitHub access
480
+ already granted to the signed-in user. A user without repository write
481
+ permission cannot submit. Concurrent submissions are retried against the
482
+ latest file so each distinct thought is retained; no submission silently
483
+ overwrites another.
484
+ * {#s-x4v7f8 <arch} A successful thought submission gives the person visible
485
+ confirmation and triggers the same generic questionnaire-change
486
+ notification as other IDD branch updates.
487
+
488
+ ## Sign-in and project discovery
489
+
490
+ * {#s-6qd8cg <m-1um0ef@6d0079c} The landing-page introduction uses short sentences to say
491
+ the user gives the agent a specification, the agent starts coding and asks
492
+ asynchronously when decisions arise, and the user's answers guide the work.
493
+ * {#s-rle2e6 <m-jp4via@372ebc0} The landing page says human judgment is the scarce resource,
494
+ promises to surface critical decisions compactly and clearly, and says answers
495
+ are captured for the work to follow.
496
+ * {#s-ixb261 <m-3sqckb@be4a1af,m-ikc4ps@b94ec3a} The signed-out landing page uses a clean editorial style
497
+ inspired by OpenAI's About page: near-white surfaces, charcoal text, a
498
+ restrained cool accent, a sans-serif font, generous spacing, and a clear type
499
+ scale with a large hero and section headings, and smaller labels and support
500
+ text.
501
+ * {#s-a9y6kc <m-8drgj4@443e70b} On page load, a signed-in user goes directly to the
502
+ project dashboard, while a signed-out user sees an informational landing
503
+ page with a GitHub sign-in action.
504
+ * {#s-lxsmnv <m-hfp7kb@6afb5f9} After the human-judgment statement, the landing page shows
505
+ three compact boxes labeled Why, What, and How with these respective
506
+ messages: “Efficient capture of human judgment,” “No walls of text. Just
507
+ crisp questions,” and “Agent asks when it needs, you answer when you can.”
508
+ * {#s-q6l925 <m-nnxwab@b96d3e8} The landing page lists six capabilities in feature boxes,
509
+ separate from its questionnaire examples: secure use; question visibility
510
+ and answering governed by the same repository permissions as code; public
511
+ and private GitHub projects; use from phones, tablets, and laptops; no
512
+ server for the project owner to set up; and branch-aware question merging
513
+ and answer-conflict resolution.
514
+ * {#s-3z7br4 <m-nnxwab@b96d3e8} The landing page shows three fictional questionnaire
515
+ examples: a reminder-time choice, a package choice, and a follow-up asking
516
+ which answer to use when the user's earlier answer differs from Bob's.
517
+ * {#s-r6ac5z <m-nnxwab@b96d3e8,m-yj5thl@e055d58} The three questionnaire examples use different
518
+ built-in theme styles as decoration; the examples show question content
519
+ rather than mock screenshots of the IDD product.
520
+ * {#s-ry22kb <m-cpqj0v@055fe29} The bottom of the landing page says IDD can optionally be
521
+ paired with ConcordSTC and briefly describes its agentic engineering role.
522
+ * {#s-yaanwo <m-2cwth4@716df92} The public landing page includes a visible “Use IDD in your
523
+ project” block with a copyable prompt that tells an agent to visit
524
+ `https://interrogation.dev`, install `@debonet/idd`, resolve the installed
525
+ package's `INSTRUCTIONS.md` path with `require.resolve`, and follow those
526
+ instructions to set up IDD in the current project.
527
+ * {#s-nq82ty <arch} The viewer signs users in through the IDD
528
+ GitHub App's user authorization flow and requests only the app's repository
529
+ contents permission.
530
+ * {#s-7falz6 <arch} The Cloud Run application starts OAuth,
531
+ validates a short-lived state value at the callback, exchanges the authorization
532
+ code for a GitHub user access token, and returns that token only to the viewer
533
+ window that started the matching sign-in attempt, even when the browser severs
534
+ the popup's opener during GitHub's cross-origin redirects.
535
+ * {#s-1n1bgd <m-rhr8be@e22d43f} The sign-in-start unit test verifies that the authorization URL
536
+ uses the registered GitHub App client ID and the exact production callback
537
+ URL `https://interrogation.dev/auth/callback`.
538
+ * {#s-zapq64 <arch} The callback response is not cached; it sends the token to the
539
+ matching viewer window through a same-origin channel and closes its window
540
+ after delivery.
541
+ * {#s-gl226e <arch} The viewer accepts a callback token only for its current
542
+ sign-in attempt; an unrelated or stale callback cannot sign it in.
543
+ * {#s-g9fydo <arch} The browser keeps the active GitHub access token only in
544
+ memory and uses it to request repositories and questionnaire data directly
545
+ from GitHub; page scripts cannot read the persistent authentication cookie.
546
+ * {#s-9040av <arch} The dashboard lists repositories visible
547
+ through the signed-in user's GitHub App access and includes a repository only
548
+ when its default branch or another discovered code branch has a matching
549
+ `idd-<branch>` branch.
550
+ * {#s-qxpze6 <m-zgomvq@a9d3d33} While signed in, the dashboard offers a link to the IDD GitHub App's
551
+ installation page so the user can grant it access to additional repositories.
552
+ * {#s-14uprd <arch,m-zgomvq@a9d3d33} When the viewer regains focus after the user changes the app's
553
+ repository access, it re-enumerates repositories through GitHub and refreshes
554
+ the project list while preserving the current questionnaire and unsent answer
555
+ drafts.
556
+ * {#s-bhzh7h <arch} The viewer requires the GitHub App to be
557
+ installed on a repository before listing or changing that repository's IDD
558
+ data; GitHub enforces the user's and installation's repository permissions.
559
+
560
+ ## Browser and server boundary
561
+
562
+ * {#s-96h8gu <arch} The Cloud Run service serves the static
563
+ viewer and the OAuth start and callback routes; it does not proxy GitHub
564
+ repository reads or writes.
565
+ * {#s-xg63my <arch} The GitHub App client secret is supplied
566
+ to the Cloud Run service through its secret manager binding and is never
567
+ sent to a browser.
568
+ * {#s-ptm6ns <arch} OAuth state is random, short-lived, bound
569
+ to the browser by a secure, HttpOnly, SameSite cookie, checked at the
570
+ callback, and then cleared; the authorization code is exchanged only once.
571
+ * {#s-0ds89f <arch} The viewer uses a restrictive Content
572
+ Security Policy, disallows framing, and does not load third-party scripts.
573
+ * {#s-xb07h5 <arch} The GitHub access token used by page scripts is held only in
574
+ JavaScript memory and is discarded on sign-out, page close, or expiration.
575
+ * {#s-hcs0wx <m-t4tzrb@6d2bfbe} After GitHub authorization, the service seals the access token
576
+ and any refresh token into a Secure, HttpOnly, SameSite cookie scoped to
577
+ `/auth`; its lifetime does not exceed the refresh-token lifetime, or the
578
+ access-token lifetime when no refresh token is issued.
579
+ * {#s-s2hz7w <arch} The service encrypts and authenticates the authentication
580
+ cookie payload with a key derived from `IDD_OAUTH_STATE_SECRET`; it does not
581
+ store GitHub user tokens in server-side session storage.
582
+ * {#s-1nncya <arch} On page load, the viewer requests its session from the same-origin
583
+ service, which returns a still-valid access token or refreshes an expired
584
+ access token with GitHub and rotates the cookie after refresh; an invalid
585
+ session cookie requires the user to sign in again.
586
+ * {#s-c2kkp3 <arch} Signing out clears the persistent authentication cookie through
587
+ the same-origin service.
588
+ * {#s-4zoo4x <arch} The viewer requests GitHub's `offline_access` OAuth scope to
589
+ receive refreshable user tokens; this scope does not grant additional
590
+ repository permissions.
591
+
592
+ ## Answer file writes
593
+
594
+ * {#s-ntcb9t <arch} The browser reads an IDD branch's data
595
+ files with the GitHub Contents API and writes updated files directly through
596
+ that API using the user's GitHub token.
597
+ * {#s-4exg46 <arch} A submission includes the Git blob SHA
598
+ that the browser read; GitHub rejects the write if the file changed since
599
+ that read, and the viewer reloads and reports the accepted answer as a
600
+ conflict instead of overwriting it.
601
+ * {#s-pc0ev7 <arch} The browser validates that the selected
602
+ option belongs to the question before attempting a write; the GitHub SHA
603
+ check remains authoritative when concurrent submissions race.
604
+ * {#s-k4g9ud <m-2wp6gd@585ee48} An answer submission with the same choice and
605
+ note as the already accepted answer is idempotent: it does not create a
606
+ conflict, and the accepted answer remains visible as answered. A submission
607
+ with a different choice or note is rejected and recorded as a conflict.
608
+ * {#s-sjssy5 <arch} A conflicting submission is preserved in
609
+ `idd/conflicts.json` only when it can be committed without replacing an
610
+ existing accepted answer; if that conflict file also changed concurrently,
611
+ the viewer reloads the latest repository state and retries safely.
612
+ * {#s-104mmm <m-umb15o@4ae4e2f,m-j48adi@77b2d25,m-hvgu3e@374ddc6} Revisiting an answered question and submitting a
613
+ different choice or note preserves the current answer and records the new
614
+ submission as a conflict. The conflict remains visible until the human
615
+ answers a clarification question; after that answer is recorded, the agent
616
+ marks the conflict resolved before carrying out the ruling.
617
+ * {#s-aos2i9 <arch} Every file displayed in the viewer is
618
+ parsed as JSON and rendered using text nodes; no repository content is
619
+ inserted as HTML.
620
+
621
+ ## Repository data
622
+
623
+ * {#s-rkulmb <m-7wyw60@f28d6e5} The GitHub repository is the durable
624
+ source of questionnaire and answer data; the IDD web application does not
625
+ keep a second durable copy of either.
626
+ * {#s-34f36d <arch} For a code branch named `<branch>`, its questionnaire
627
+ data is stored on the Git branch `idd-<branch>`; the target branch's IDD
628
+ branch is named `idd-<target>`.
629
+ * {#s-z4lb0p <arch} The stable identity of a code branch is the lowercase SHA-256
630
+ digest of the UTF-8 JSON serialization of `[String(repositoryId),
631
+ fullGitRef]`, where `fullGitRef` is `refs/heads/<branch>`.
632
+ * {#s-r2o7ne <arch,m-q2caxw@e07030c} The hosted viewer accepts question ids computed
633
+ either with the reserved X option in the lowercase SHA-256 digest of the UTF-8
634
+ JSON serialization of `[question.branchHash, title, body, options]`, with each
635
+ option represented as `[key, text, tag-or-empty-string]`, or by the legacy
636
+ formula that omits the final reserved X option. It supplies X for display
637
+ without rewriting legacy question records.
638
+ * {#s-ru06vn <arch} Questions with the same text created on different
639
+ code branches have different ids.
640
+ * {#s-0399cx <arch} Each IDD branch stores its active questions in
641
+ `idd/questions.json`, accepted answers in `idd/answers.json`, rejected
642
+ answer conflicts in `idd/conflicts.json`, question history in
643
+ `idd/history.json`, and agent status in `idd/status.json`.
644
+ * {#s-30veoz <arch} Each question record in `idd/questions.json` contains `id`,
645
+ its origin `branchHash`, `title`, `body`, `options`, and ISO 8601
646
+ `createdAt` fields; inherited questions retain the branch hash where each
647
+ was first created.
648
+ * {#s-lzuk4v <arch} Each accepted answer in `idd/answers.json` contains `choice`,
649
+ `note`, and ISO 8601 `time` fields, keyed by question id.
650
+ * {#s-kwn5lt <arch} Each conflict record in `idd/conflicts.json` contains `id`,
651
+ `questionId`, `choice`, `note`, `time`, and `submittedBy` string fields;
652
+ `id` uniquely identifies that rejected submission.
653
+ * {#s-hgnnfg <arch} Each history record in `idd/history.json` contains a
654
+ removed or superseded `questionId`, a full `question` snapshot,
655
+ its replacement `replacedBy` question id, and an ISO 8601 `time` field.
656
+ Its accepted answer remains keyed by `questionId` in `idd/answers.json`.
657
+ * {#s-omsgq8 <arch} `idd/status.json` is an object keyed by active agent session
658
+ id; each value has exactly a boolean `blocked` field and an ISO 8601
659
+ `updatedAt` field.
660
+ * {#s-w9knti <arch} An agent session updates its entry on the
661
+ matching IDD branch when its blocked state changes, sets `blocked` true
662
+ only when it cannot continue without a human answer, refreshes `updatedAt`
663
+ when it reports progress, and removes its entry when the session ends.
664
+ * {#s-d3a5x5 <m-7wyw60@f28d6e5} The browser serializes a submitted answer
665
+ as JSON and sends it directly to GitHub to be committed on that project's
666
+ IDD branch.
667
+ * {#s-7xztbp <m-4as0w8@cf65a99} To submit an answer, the browser uses a short-lived
668
+ GitHub App user access token; it can write only to repositories the app
669
+ installation and user both have permission to access.
670
+ * {#s-sc65id <arch} An answer is accepted only if no answer has already
671
+ been committed for that question id; a rejected submission leaves the
672
+ accepted answer unchanged, records the rejected answer as a conflict, and
673
+ shows the accepted answer to the submitter.
674
+ * {#s-6hexmx <m-awh12l@a1b5037} Repeating the same rejected answer from the same GitHub user for
675
+ the same question is idempotent: IDD does not append another conflict entry.
676
+ The viewer displays only one entry for repeated records with the same
677
+ question id, submitter, choice, and note.
678
+ * {#s-kemef5 <arch} An accepted answer records its question id,
679
+ choice, note, and timestamp; the GitHub commit identifies the user who
680
+ submitted it.
681
+ * {#s-zqz4wj <arch} A rejected answer conflict records the
682
+ question id, submitted answer, and timestamp; the GitHub commit identifies
683
+ the user who submitted it.
684
+ * {#s-ewykyi <arch} Agent status records whether the agent is
685
+ blocked waiting for a human answer and when that status was last updated.
686
+
687
+ ## Text and credentials
688
+
689
+ * {#s-e8zu22 <m-ol5xyr@2c772e6} Question titles, question bodies, option
690
+ text, submitted answers, and prior answers are displayed as text; the page
691
+ never interprets their contents as HTML.
692
+ * {#s-m5duw4 <arch} The page keeps an access token only in memory
693
+ while the user is signed in; it does not put the token in questionnaire
694
+ data, answer data, local storage, or a URL.
695
+ * {#s-0js03o <arch} The Cloud Run application holds the GitHub App
696
+ credential needed to exchange an authorization code, but it does not
697
+ receive questionnaire submissions or persist user access tokens in
698
+ server-side session storage.
699
+ * {#s-v5f187 <arch} The user installs the GitHub App on repositories to add them to
700
+ the viewer; the app's user token can only access repositories the user
701
+ and the installation can access.
702
+ * {#s-pot7wd <arch} The browser reads and commits questionnaire files through the
703
+ GitHub REST API, and the IDD application does not proxy those file contents.
704
+
705
+ ## Branch reconciliation
706
+
707
+ * {#s-3980su <arch} Before completing a code-branch merge, the agent
708
+ merges the source IDD branch into the target IDD branch and compares their
709
+ question and answer records to identify duplicate, overlapping, and obsolete
710
+ questions.
711
+ * {#s-ay10ju <arch} When related questions have answers that do not
712
+ establish one decision, the agent creates one clarifying question on the
713
+ target IDD branch, preserves the earlier records in its history, and waits
714
+ for that answer before implementing the decision and completing the merge.
715
+ * {#s-xsxrgn <arch} When questions are duplicates or an earlier
716
+ question has been made obsolete, the target IDD branch presents the
717
+ consolidated or superseding question and retains links to the earlier
718
+ question and answer records.
719
+ * {#s-8kd709 <arch} When IDD branches merge, the target's
720
+ `idd/page.json` keeps the target code branch's `branchHash`; each question
721
+ keeps the `branchHash` from the code branch where it was created unless the
722
+ agent replaces it with a new clarifying question.
723
+ * {#s-fyoism <arch} A code-branch merge cannot complete until its source IDD history
724
+ is an ancestor of the target IDD branch and the agent has recorded a review
725
+ for the current code and IDD commits.
726
+ * {#s-vwyasy <arch} The merge process keeps one active copy of
727
+ duplicate questions and records which earlier question ids it replaces.
728
+ * {#s-3wklcj <arch} The merge process does not require ConcordSTC.
729
+
730
+ ## Dependencies
731
+
732
+ * {#p-weocqk >specs/project-files.md} The project's question and answer
733
+ data.
734
+ * {#p-21xm5l >specs/questions-page.md} The text displayed by the
735
+ questionnaire.
736
+ * {#p-di8ysg >specs/idd-page.md} How the agent waits for an answer notification.
737
+ * {#p-yjtzny >specs/build.md} How to build and deploy the Cloud Run web application.
738
+