@agentwhy/cli 0.2.1 → 0.3.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/dist/adapter/codex/contract/assumptions.js +4 -4
- package/dist/adapter/codex/contract/deliveries.js +12 -0
- package/dist/adapter/codex/contract/messages.js +8 -1
- package/dist/adapter/codex/events/cell-commands.js +191 -0
- package/dist/adapter/codex/events/delivered-output.js +30 -0
- package/dist/adapter/codex/events/rollout-scan.js +99 -7
- package/dist/core/access/command-line.js +4 -1
- package/dist/core/access/listing.js +10 -3
- package/dist/core/access/protected-access.js +94 -1
- package/dist/core/access/recorded-effect.js +22 -1
- package/dist/report/build-report.js +125 -19
- package/dist/report/render/report-page/file-story.js +33 -2
- package/dist/report/render/report-page/files-view.js +176 -55
- package/dist/report/render/report-page/files.js +51 -8
- package/dist/report/render/report-page/fix-wizard-script.js +17 -7
- package/dist/report/render/report-page/fix-wizard.js +4 -1
- package/dist/report/render/report-page/helpers.js +2 -1
- package/dist/report/render/report-page/report-page-renderer.js +51 -12
- package/dist/report/render/report-page/story-window.js +33 -12
- package/dist/report/render/report-page/to-do-view.js +42 -10
- package/dist/report/render/ui/app-sidebar.js +31 -2
- package/dist/report/render/ui/confirm-dialog.js +69 -4
- package/dist/report/render/ui/fold-line.js +2 -0
- package/dist/report/render/ui/popup.js +1 -1
- package/dist/report/render/ui/project-list.js +49 -10
- package/dist/report/render/ui/words/app-words.js +6 -0
- package/dist/report/render/ui/words/conversations-words.js +12 -0
- package/dist/report/render/ui/words/projects-words.js +9 -0
- package/dist/report/render/ui/words/report-words.js +114 -12
- package/dist/report/render/ui/words/settings-words.js +12 -9
- package/dist/report/start/conversations/calendar-view.js +1 -1
- package/dist/report/start/conversations/conversation-columns.js +6 -4
- package/dist/report/start/conversations/period-section.js +33 -17
- package/dist/report/start/conversations/periods.js +7 -1
- package/dist/report/start/render/session-status.js +14 -9
- package/dist/report/start/session-start.js +6 -3
- package/dist/report/start/settings/alerts-tab.js +2 -1
- package/package.json +1 -1
|
@@ -21,9 +21,9 @@ export const SETTINGS_WORDS = {
|
|
|
21
21
|
'set.card.optional': 'Optional',
|
|
22
22
|
'set.card.read.when': 'So you can change the keys the same day, before anyone uses them. You’ll see what to do.',
|
|
23
23
|
'set.card.read.answer': 'Heads up: while working, I read the passwords for your live app. See what to do →',
|
|
24
|
-
'set.card.stopped.name': 'When my AI
|
|
25
|
-
'set.card.stopped.when': '
|
|
26
|
-
'set.card.stopped.answer': '
|
|
24
|
+
'set.card.stopped.name': 'When my AI opens a private file, or is stopped',
|
|
25
|
+
'set.card.stopped.when': 'Everything but the keys: your AI opened a private file and nothing was read out of it, or a block stopped it in time. There will be more notes, and agentwhy writes them itself, in English.',
|
|
26
|
+
'set.card.stopped.answer': 'CHECK: This conversation reached 1 protected file; no value found in its messages.',
|
|
27
27
|
'set.card.fine.name': 'Once per conversation, even when all is fine',
|
|
28
28
|
'set.card.fine.when': 'Peace of mind: a quick sign that we’re watching.',
|
|
29
29
|
'set.card.fine.answer': 'All good — I didn’t open anything private.',
|
|
@@ -32,6 +32,7 @@ export const SETTINGS_WORDS = {
|
|
|
32
32
|
'set.system.name': 'A notification in the corner of the screen',
|
|
33
33
|
'set.system.when': 'It shows for a moment, whichever app your AI runs in. Without it, agentwhy speaks only in the conversation. On a Mac only.',
|
|
34
34
|
'set.chat.ai': 'AI',
|
|
35
|
+
'set.chat.line': '✦',
|
|
35
36
|
'set.state.local': 'On — for just you',
|
|
36
37
|
'set.state.shared': 'On — for everyone on this project',
|
|
37
38
|
'set.state.on': 'On',
|
|
@@ -227,9 +228,9 @@ export const SETTINGS_WORDS = {
|
|
|
227
228
|
'set.card.optional': 'Opcjonalne',
|
|
228
229
|
'set.card.read.when': 'Żeby zmienić klucze tego samego dnia, zanim ktoś ich użyje. Zobaczysz, co zrobić.',
|
|
229
230
|
'set.card.read.answer': 'Uwaga: w trakcie pracy przeczytałem hasła do twojej działającej aplikacji. Zobacz, co zrobić →',
|
|
230
|
-
'set.card.stopped.name': 'Gdy moje AI
|
|
231
|
-
'set.card.stopped.when': '
|
|
232
|
-
'set.card.stopped.answer': '
|
|
231
|
+
'set.card.stopped.name': 'Gdy moje AI otworzy prywatny plik albo zostanie zatrzymane',
|
|
232
|
+
'set.card.stopped.when': 'Wszystko poza kluczami: AI otworzyło prywatny plik i nic z niego nie przeczytało albo blokada zatrzymała je w porę. Wiadomości będzie więcej, a agentwhy pisze je sam, po angielsku.',
|
|
233
|
+
'set.card.stopped.answer': 'CHECK: This conversation reached 1 protected file; no value found in its messages.',
|
|
233
234
|
'set.card.fine.name': 'Raz na rozmowę, nawet gdy wszystko jest w porządku',
|
|
234
235
|
'set.card.fine.when': 'Dla spokoju: krótki znak, że czuwamy.',
|
|
235
236
|
'set.card.fine.answer': 'Wszystko w porządku — nie otwierałem niczego prywatnego.',
|
|
@@ -238,6 +239,7 @@ export const SETTINGS_WORDS = {
|
|
|
238
239
|
'set.system.name': 'Powiadomienie w rogu ekranu',
|
|
239
240
|
'set.system.when': 'Pojawia się na chwilę, w jakiejkolwiek aplikacji działa twoje AI. Bez niego agentwhy mówi tylko w rozmowie. Tylko na Macu.',
|
|
240
241
|
'set.chat.ai': 'AI',
|
|
242
|
+
'set.chat.line': '✦',
|
|
241
243
|
'set.state.local': 'Włączone — tylko dla ciebie',
|
|
242
244
|
'set.state.shared': 'Włączone — dla wszystkich w projekcie',
|
|
243
245
|
'set.state.on': 'Włączone',
|
|
@@ -443,9 +445,9 @@ export const SETTINGS_WORDS = {
|
|
|
443
445
|
'set.card.optional': 'Optional',
|
|
444
446
|
'set.card.read.when': 'Damit du die Schlüssel noch am selben Tag ändern kannst, bevor jemand sie nutzt. Du siehst, was zu tun ist.',
|
|
445
447
|
'set.card.read.answer': 'Achtung: Bei der Arbeit habe ich die Passwörter deiner Live-App gelesen. Sieh dir an, was zu tun ist →',
|
|
446
|
-
'set.card.stopped.name': 'Wenn meine KI
|
|
447
|
-
'set.card.stopped.when': '
|
|
448
|
-
'set.card.stopped.answer': '
|
|
448
|
+
'set.card.stopped.name': 'Wenn meine KI eine private Datei öffnet oder gestoppt wird',
|
|
449
|
+
'set.card.stopped.when': 'Alles außer den Schlüsseln: Deine KI hat eine private Datei geöffnet und nichts daraus gelesen, oder eine Blockierung hat sie rechtzeitig gestoppt. Es werden mehr Nachrichten, und agentwhy schreibt sie selbst, auf Englisch.',
|
|
450
|
+
'set.card.stopped.answer': 'CHECK: This conversation reached 1 protected file; no value found in its messages.',
|
|
449
451
|
'set.card.fine.name': 'Einmal pro Unterhaltung, auch wenn alles gut ist',
|
|
450
452
|
'set.card.fine.when': 'Zur Beruhigung: ein kurzes Zeichen, dass wir aufpassen.',
|
|
451
453
|
'set.card.fine.answer': 'Alles gut — ich habe nichts Privates geöffnet.',
|
|
@@ -454,6 +456,7 @@ export const SETTINGS_WORDS = {
|
|
|
454
456
|
'set.system.name': 'Eine Benachrichtigung in der Bildschirmecke',
|
|
455
457
|
'set.system.when': 'Sie erscheint kurz, egal in welcher App deine KI läuft. Ohne sie spricht agentwhy nur im Chat. Nur auf dem Mac.',
|
|
456
458
|
'set.chat.ai': 'KI',
|
|
459
|
+
'set.chat.line': '✦',
|
|
457
460
|
'set.state.local': 'An — nur für dich',
|
|
458
461
|
'set.state.shared': 'An — für alle in diesem Projekt',
|
|
459
462
|
'set.state.on': 'An',
|
|
@@ -46,7 +46,7 @@ export function dayTile(day, label, parts = {}) {
|
|
|
46
46
|
: day.toCheck > 0 ? inLanguages((t) => t('conv.day.toCheck', { n: day.toCheck }))
|
|
47
47
|
: day.fixed > 0 ? inLanguages((t) => t('conv.day.fixed', { n: day.fixed }))
|
|
48
48
|
// F17: a day whose unchecked conversations were all read, with gaps, says that, as their list's heading does.
|
|
49
|
-
: day.unchecked > 0 ? inLanguages((t) => t(
|
|
49
|
+
: day.unchecked > 0 ? inLanguages((t) => t(day.partial === day.unchecked ? 'conv.day.partial' : 'conv.day.unchecked', { n: day.unchecked }))
|
|
50
50
|
: inLanguages((t) => t('conv.day.good'));
|
|
51
51
|
const count = tone === 'future' && ahead ? ' ' : tone === 'yet' ? '0' : empty ? '—' : String(day.conversations);
|
|
52
52
|
const opens = parts.opens;
|
|
@@ -64,7 +64,7 @@ export function conversationRow(item, widen, include = false) {
|
|
|
64
64
|
// X28: every row names the AI the conversation was with, in the badge that says where something came from (§9.2).
|
|
65
65
|
'<span class="cw-ask">' + ask + '</span><span class="cw-ai">' + tag(e(PROVIDER_NAMES[entry.provider]), 'grey', 'badge') + '</span>' + tech,
|
|
66
66
|
whatHappened(item, report),
|
|
67
|
-
fixedCell(item.look),
|
|
67
|
+
fixedCell(item.look, item.partial),
|
|
68
68
|
'<span class="cw-action">' + action + '</span>',
|
|
69
69
|
],
|
|
70
70
|
// A read of files the person let it read is put before them too, with its bar, and leads to its report (F57a).
|
|
@@ -88,7 +88,7 @@ function whatHappened(item, report) {
|
|
|
88
88
|
// A gap does not erase what the record established. Keep the uncertain look, and name its positive observation
|
|
89
89
|
// separately; the title only says what the person asked, while this count comes from confirmed file evidence.
|
|
90
90
|
const knownNames = item.look === 'unchecked' && item.entry.report.kind === 'generated'
|
|
91
|
-
? (item.entry.report.files ?? []).filter((file) => file.kind === 'named' || file.kind === 'result').length : 0;
|
|
91
|
+
? (item.entry.report.files ?? []).filter((file) => file.kind === 'named' || file.kind === 'result' || file.kind === 'told').length : 0;
|
|
92
92
|
const known = knownNames === 0 ? '' : '<span class="cw-known">' + inLanguages((t) => t('conv.did.partial.name', { n: knownNames })) + '</span>';
|
|
93
93
|
const n = item.reached ?? 0;
|
|
94
94
|
const all = report === undefined || n === 0 ? '' :
|
|
@@ -101,7 +101,7 @@ function whatHappened(item, report) {
|
|
|
101
101
|
* the person chose Track for was never something to fix, and is not "nothing" either (the maintainer, 2026-09-25): it
|
|
102
102
|
* says the mode, with Settings' eye and words, in the sand of its look (F57a).
|
|
103
103
|
*/
|
|
104
|
-
function fixedCell(look) {
|
|
104
|
+
function fixedCell(look, partial) {
|
|
105
105
|
const say = (key) => inLanguages((t) => t(key));
|
|
106
106
|
if (look === 'fixed')
|
|
107
107
|
return glyphIcon('✓', 'mint', say('conv.fixed.yes'));
|
|
@@ -109,7 +109,9 @@ function fixedCell(look) {
|
|
|
109
109
|
return glyphIcon('✕', 'coral', say('conv.fixed.no'));
|
|
110
110
|
if (look === 'allowed')
|
|
111
111
|
return glyphIcon(MODE_SVG.tell, 'sand', say('set.mode.tell'));
|
|
112
|
-
|
|
112
|
+
// F17 is about this cell: a record with gaps is never told there is nothing to fix, whatever its badge says. The
|
|
113
|
+
// badge now names the file such a record did reach, and only this cell knows that the rest of it is missing.
|
|
114
|
+
return '<span class="cw-fixed-plain">' + say(LOOKS[look].known && !partial ? 'conv.fixed.na' : 'conv.fixed.unknown') + '</span>';
|
|
113
115
|
}
|
|
114
116
|
/** What the Check it button says as it works, in every language: one attribute cannot hold three. */
|
|
115
117
|
function includeWords() {
|
|
@@ -15,6 +15,7 @@ import { LOOKS } from '../../render/ui/status-look.js';
|
|
|
15
15
|
import { AIR_DATEPICKER_SCRIPT, AIR_DATEPICKER_STYLE } from '../render/air-datepicker-vendor.js';
|
|
16
16
|
import { CALENDAR_VIEW_STYLE } from './calendar-view.js';
|
|
17
17
|
import { CONVERSATION_COLUMNS_STYLE, CONVERSATION_ROW_SCRIPT, conversationRow, CONVERSATION_TABLE } from './conversation-columns.js';
|
|
18
|
+
import { unchecked } from './periods.js';
|
|
18
19
|
import { PERIODS_SCRIPT } from './periods-script.js';
|
|
19
20
|
/**
|
|
20
21
|
* One week or one month (`for-people-who-build-with-ai.md` F8-F14): the answer first, then where to start, then the
|
|
@@ -33,8 +34,8 @@ export function periodSection(periods, at, index, spec) {
|
|
|
33
34
|
const asks = fix.length > 0;
|
|
34
35
|
// What this run did not read, or read with gaps, is neither to fix nor "nothing private": it is listed apart, with
|
|
35
36
|
// the command that includes it, and never folded under the line that says there is nothing to fix (F17, O4).
|
|
36
|
-
const
|
|
37
|
-
const others = period.conversations.filter((item) =>
|
|
37
|
+
const listedApart = period.conversations.filter(unchecked);
|
|
38
|
+
const others = period.conversations.filter((item) => !unchecked(item) && !LOOKS[item.look].attention);
|
|
38
39
|
// F8, changed 2026-09-25: what was read and then fixed is still counted as read - it happened - and asks for nothing;
|
|
39
40
|
// so is what the person let it read (F57a).
|
|
40
41
|
const fixed = period.conversations.filter((item) => item.look === 'fixed').length;
|
|
@@ -44,9 +45,9 @@ export function periodSection(periods, at, index, spec) {
|
|
|
44
45
|
const after = fixed > 0 && allowed > 0 ? 'fixedAllowed' : fixed > 0 ? 'fixed' : allowed > 0 ? 'allowed' : undefined;
|
|
45
46
|
// F8, changed 2026-09-24: a period whose every conversation was checked and none read anything says so in mint - and,
|
|
46
47
|
// since 2026-09-25, one whose every read was fixed.
|
|
47
|
-
const clean = total > 0 && need.length === 0 &&
|
|
48
|
+
const clean = total > 0 && need.length === 0 && listedApart.length === 0;
|
|
48
49
|
// F17: conversations read with gaps alone - every Codex record has one - are named as that, not as ones never checked.
|
|
49
|
-
const lead = uncheckedLead(
|
|
50
|
+
const lead = uncheckedLead(listedApart, index.shared);
|
|
50
51
|
const partial = lead === 'conv.unchecked.partial';
|
|
51
52
|
// Every period opens whole (F10, changed 2026-09-24); a day is chosen only by a tap.
|
|
52
53
|
const open = '<section class="cw' + (at === 0 ? ' cw-current' : '') + '" id="' + spec.kind + '-' + period.ago + '" data-period-at="' + at + '"' +
|
|
@@ -62,14 +63,14 @@ export function periodSection(periods, at, index, spec) {
|
|
|
62
63
|
eyebrow: spec.eyebrow,
|
|
63
64
|
fact: inLanguages((t) => (total === 0 ? t(spec.zero) : t('conv.hero.fact', { n: total }))),
|
|
64
65
|
action: inLanguages((t) => (need.length > 0 ? t('conv.hero.times', { n: read })
|
|
65
|
-
:
|
|
66
|
+
: listedApart.length > 0 ? t(partial ? 'conv.hero.partial' : 'conv.hero.unchecked', { n: listedApart.length })
|
|
66
67
|
: read > 0 ? t('conv.hero.times', { n: read }) : t('conv.hero.none'))),
|
|
67
68
|
// "The ones marked in coral" only where one is: a period with nothing to fix says so, and what is grey.
|
|
68
|
-
lead: inLanguages((t) => t(asks ? 'conv.hero.lead' :
|
|
69
|
+
lead: inLanguages((t) => t(asks ? 'conv.hero.lead' : listedApart.length > 0 ? 'conv.hero.lead.unchecked'
|
|
69
70
|
: after === undefined ? 'conv.hero.lead.clean' : 'conv.hero.lead.' + after)),
|
|
70
71
|
...(clean ? { calm: true } : {}),
|
|
71
72
|
}) +
|
|
72
|
-
(spec.clean === undefined ? '' : guideCard(guideOf(period, spec.clean, after,
|
|
73
|
+
(spec.clean === undefined ? '' : guideCard(guideOf(period, spec.clean, after, listedApart.length, index.widen, lead, spec.lists))) +
|
|
73
74
|
spec.view +
|
|
74
75
|
(!spec.lists ? '' : dayChip(spec.whole)) +
|
|
75
76
|
(!spec.lists || fix.length === 0 ? '' :
|
|
@@ -78,12 +79,7 @@ export function periodSection(periods, at, index, spec) {
|
|
|
78
79
|
dataTable({ ...CONVERSATION_TABLE, rows: fix.map((item) => conversationRow(item, index.widen, !index.shared)) }) +
|
|
79
80
|
'</section>') +
|
|
80
81
|
(!spec.lists || info.length === 0 ? '' : forYourInfo(info, index)) +
|
|
81
|
-
(!spec.lists ||
|
|
82
|
-
'<section class="cw-need cw-unchecked" data-need><div class="cw-need-head"><span class="cw-need-dot" aria-hidden="true"></span>' +
|
|
83
|
-
'<h2 class="cw-h2">' + inLanguages((t) => t(partial ? 'look.unchecked' : 'conv.unchecked')) + '</h2><span class="cw-need-count" data-need-count>' + unchecked.length + '</span></div>' +
|
|
84
|
-
'<p class="cw-unchecked-lead">' + inLanguages((t) => t(lead, { command: '<code>' + e(index.widen) + '</code>' })) + '</p>' +
|
|
85
|
-
dataTable({ ...CONVERSATION_TABLE, rows: unchecked.map((item) => conversationRow(item, index.widen, !index.shared)) }) +
|
|
86
|
-
'</section>') +
|
|
82
|
+
(!spec.lists || listedApart.length === 0 ? '' : notFullyChecked(listedApart, partial, lead, index)) +
|
|
87
83
|
(!spec.lists || others.length === 0 ? '' : theRest(others, need.length === 0, index)) +
|
|
88
84
|
'</section>';
|
|
89
85
|
}
|
|
@@ -101,6 +97,27 @@ function forYourInfo(info, index) {
|
|
|
101
97
|
body: dataTable({ ...CONVERSATION_TABLE, rows: info.map((item) => conversationRow(item, index.widen, !index.shared)) }),
|
|
102
98
|
}) + '</section>';
|
|
103
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* "Couldn't check fully (n)" (the maintainer, 2026-10-05): what this run could not read, or read with gaps, in a fold
|
|
102
|
+
* of its own - a solid grey line with the look's ?, shut, and opened with **Show**. Every Codex record has a gap
|
|
103
|
+
* (`2026-09-27-what-codex-wrote.md` X23), so on a project worked in with Codex this list holds the whole week, asks
|
|
104
|
+
* for nothing, and was the longest thing on the page; the maintainer asked for it shut on arrival (2026-10-05), not
|
|
105
|
+
* only shuttable. Shut it still says all of it the page owes: the heading, how many, and in brief why - and the
|
|
106
|
+
* period's card above says the number too. The sentence of the reason and the command that would include them go
|
|
107
|
+
* inside, with the rows; the list is still apart from what is to fix and is never a group of the rest's table
|
|
108
|
+
* (F17, F13, O4). The script narrows it to the day chosen as it does the other lists (`data-need`), and the count it
|
|
109
|
+
* rewrites is the one in the line, which is in view whether the fold is open or not.
|
|
110
|
+
*/
|
|
111
|
+
function notFullyChecked(unchecked, partial, lead, index) {
|
|
112
|
+
return '<section class="cw-need cw-unchecked" data-need>' + foldLine({
|
|
113
|
+
summary: '<strong>' + inLanguages((t) => t(partial ? 'look.unchecked' : 'conv.unchecked')) +
|
|
114
|
+
' (<span data-need-count>' + unchecked.length + '</span>)</strong> <span class="fold-rest">' +
|
|
115
|
+
inLanguages((t) => t(lead + '.rest')) + '</span>',
|
|
116
|
+
mark: { glyph: LOOKS.unchecked.glyph, tone: 'grey' },
|
|
117
|
+
body: '<p class="cw-unchecked-lead">' + inLanguages((t) => t(lead, { command: '<code>' + e(index.widen) + '</code>' })) + '</p>' +
|
|
118
|
+
dataTable({ ...CONVERSATION_TABLE, rows: unchecked.map((item) => conversationRow(item, index.widen, !index.shared)) }),
|
|
119
|
+
}) + '</section>';
|
|
120
|
+
}
|
|
104
121
|
/** The looks of the rest, in the order of F16's ladder: the groups of F13 and F14, and the order they are listed in. */
|
|
105
122
|
const REST = ['fixed', 'name', 'stopped', 'none'];
|
|
106
123
|
/** A group's table rows past this many wait behind "Show all" while the whole period is shown (F14). */
|
|
@@ -207,11 +224,11 @@ function guideOf(period, clean, after, unchecked, widen, lead, listed) {
|
|
|
207
224
|
function uncheckedLead(unchecked, shared) {
|
|
208
225
|
// F17: a record with gaps was read - what it cannot show is said, never that the run did not read it. Every Codex record
|
|
209
226
|
// is one (`2026-09-27-what-codex-wrote.md` X23), so a list of them alone is common.
|
|
210
|
-
if (unchecked.every((item) => item.
|
|
227
|
+
if (unchecked.every((item) => item.partial))
|
|
211
228
|
return 'conv.unchecked.partial';
|
|
212
229
|
if (!shared && unchecked.every((item) => item.look === 'outside'))
|
|
213
230
|
return 'conv.unchecked.check';
|
|
214
|
-
return unchecked.some((item) => item.
|
|
231
|
+
return unchecked.some((item) => item.partial) ? 'conv.unchecked.mixed' : 'conv.unchecked.lead';
|
|
215
232
|
}
|
|
216
233
|
/**
|
|
217
234
|
* A count the script may change - the day chosen narrows the rest of the period to that day - written with every
|
|
@@ -237,8 +254,7 @@ export const PERIOD_SECTION_STYLE = String.raw `
|
|
|
237
254
|
.cw-need-head{display:flex;align-items:baseline;gap:10px;margin-bottom:12px}
|
|
238
255
|
.cw-need-dot{width:10px;height:10px;border-radius:50%;background:var(--coral);align-self:center}
|
|
239
256
|
.cw-need-count{font-size:15px;font-weight:650;color:var(--coral-text)}
|
|
240
|
-
.cw-unchecked
|
|
241
|
-
.cw-unchecked-lead{margin:-4px 0 12px;font-size:14px;line-height:1.5;color:var(--text-2)}
|
|
257
|
+
.cw-unchecked-lead{margin:0 0 12px;font-size:14px;line-height:1.5;color:var(--text-2)}
|
|
242
258
|
.cw-unchecked-lead code,.guide code{font-family:var(--mono);font-size:13px;color:var(--text);background:var(--white-07);border-radius:6px;padding:1px 6px}
|
|
243
259
|
.cw-tools{display:none;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:16px}
|
|
244
260
|
.js .cw-tools{display:flex}
|
|
@@ -41,8 +41,9 @@ export function period(ago, first, last, today, conversations) {
|
|
|
41
41
|
// A read of files the person let the AI read is to check too: it is put before them, as a read is (F57a).
|
|
42
42
|
toCheck: those.filter((item) => LOOKS[item.look].attention).length,
|
|
43
43
|
fixed: those.filter((item) => item.look === 'fixed').length,
|
|
44
|
-
unchecked: those.filter(
|
|
44
|
+
unchecked: those.filter(unchecked).length,
|
|
45
45
|
looks,
|
|
46
|
+
partial: those.filter((item) => item.partial).length,
|
|
46
47
|
future: number > today,
|
|
47
48
|
today: number === today,
|
|
48
49
|
};
|
|
@@ -108,5 +109,10 @@ function conversation(entry, local, today, done) {
|
|
|
108
109
|
files: files.map((file) => file.path),
|
|
109
110
|
read: files.filter((file) => file.kind === 'seen').length,
|
|
110
111
|
...(entry.report.kind === 'generated' && entry.report.reached !== undefined ? { reached: entry.report.reached } : {}),
|
|
112
|
+
partial: look === 'unchecked',
|
|
111
113
|
};
|
|
112
114
|
}
|
|
115
|
+
/** Not checked, or read with gaps: what is listed apart, and never counted as nothing to fix (F17, O4). */
|
|
116
|
+
export function unchecked(item) {
|
|
117
|
+
return !LOOKS[item.look].known || item.partial;
|
|
118
|
+
}
|
|
@@ -14,19 +14,24 @@ export function statusOf(entry) {
|
|
|
14
14
|
const { tally, incomplete } = entry.report;
|
|
15
15
|
if (tally.contentsSeen > 0)
|
|
16
16
|
return 'seen';
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
// `codex-blocks-too` CK12, amended 2026-10-05 by the maintainer: an attempt agentwhy stopped is a fact in its own
|
|
18
|
+
// words, and outranks a name seen - the agent found the file, was stopped from opening it, and the rule held. Never
|
|
19
|
+
// where an attempt has no known end: then what happened to it is not known.
|
|
20
|
+
if (tally.refusedAttempts > 0 && tally.unknownAttempts === 0)
|
|
21
|
+
return 'blocked';
|
|
22
|
+
// F17, X10: an attempt with no known end, on a record with gaps, leaves what the agent saw not known, whatever names
|
|
23
|
+
// it saw beside it - and so does a file's text a process printed that no agent is shown to have received (X14).
|
|
24
|
+
if (incomplete && (tally.unknownAttempts > 0 || (tally.printedUnseen ?? 0) > 0))
|
|
25
|
+
return 'unknown';
|
|
26
|
+
// A gap does not unmake what the record did establish: a name seen is said, as the report's headline says it
|
|
27
|
+
// (amended 2026-10-05 - every Codex record has a gap, and each reach of theirs short of a read was hidden behind it).
|
|
24
28
|
if (tally.filesReached > 0 && tally.onlyThroughResult === tally.filesReached)
|
|
25
29
|
return 'result';
|
|
26
30
|
if (tally.filesReached > 0)
|
|
27
31
|
return 'named';
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
// F17: short of a reach, a record with gaps cannot say nothing needs doing.
|
|
33
|
+
if (incomplete)
|
|
34
|
+
return 'unknown';
|
|
30
35
|
return 'clean';
|
|
31
36
|
}
|
|
32
37
|
/**
|
|
@@ -910,7 +910,7 @@ function entryOf(name, title, session, report) {
|
|
|
910
910
|
* call named it, it only appeared in a result, or its outcome is not recorded. The same four the row's badge
|
|
911
911
|
* climbs, so a row and the files under it never disagree.
|
|
912
912
|
*/
|
|
913
|
-
function filesOf(actions) {
|
|
913
|
+
export function filesOf(actions) {
|
|
914
914
|
const strongest = new Map();
|
|
915
915
|
const add = (path, kind) => {
|
|
916
916
|
if (!strongest.has(path))
|
|
@@ -922,10 +922,13 @@ function filesOf(actions) {
|
|
|
922
922
|
add(route.path, 'named');
|
|
923
923
|
for (const path of actions.onlyInResults)
|
|
924
924
|
add(path, 'result');
|
|
925
|
-
for
|
|
926
|
-
|
|
925
|
+
// F57a: a file the record shows was read, and that the person chose Track for, is told whatever else was tried on it.
|
|
926
|
+
// `actionsOf` keeps a told path off every other list but `unknown`, so read after it, a search that matched nothing
|
|
927
|
+
// made a tracked file read through `head` an unknown one, and its row asked for a fix (found 2026-10-05).
|
|
927
928
|
for (const path of actions.told ?? [])
|
|
928
929
|
add(path, 'told');
|
|
930
|
+
for (const path of actions.unknown)
|
|
931
|
+
add(path, 'unknown');
|
|
929
932
|
return [...strongest.values()];
|
|
930
933
|
}
|
|
931
934
|
/** A policy as one comparable value: what it protects, how, and its exceptions (F57). */
|
|
@@ -40,6 +40,7 @@ export function alertsTab(view) {
|
|
|
40
40
|
row({
|
|
41
41
|
tone: 'mint',
|
|
42
42
|
key: 'stopped',
|
|
43
|
+
says: 'line',
|
|
43
44
|
locked: view.stopped.locked,
|
|
44
45
|
state: optional(view.stopped.on, view.stopped.locked),
|
|
45
46
|
control: view.stopped.locked ? lockedSwitch('stopped', turnOn) : toggleSwitch({
|
|
@@ -100,7 +101,7 @@ function row(spec) {
|
|
|
100
101
|
? tag(inLanguages((t) => t('set.card.read.badge')), 'mint', 'badge')
|
|
101
102
|
: tag(inLanguages((t) => t('set.card.optional')), 'grey', 'badge')) + '</div>' +
|
|
102
103
|
'<p class="set-msg-why">' + word('when') + '</p>' +
|
|
103
|
-
chatExample({ tone: spec.tone, ai: inLanguages((t) => t('set.chat.ai')), answer: word('answer') }) +
|
|
104
|
+
chatExample({ tone: spec.tone, ai: inLanguages((t) => t(spec.says === 'line' ? 'set.chat.line' : 'set.chat.ai')), answer: word('answer') }) +
|
|
104
105
|
(spec.state === undefined ? '' : stateLine(spec.state)) +
|
|
105
106
|
'<p class="set-say" data-set-say hidden></p>' +
|
|
106
107
|
'</div>' + spec.control + '</article>';
|