@agent-native/core 0.213.1 → 0.216.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action.js +54 -1
- package/dist/agent/actions/disconnect-chatgpt-subscription.js +5 -0
- package/dist/agent/actions/get-agentkit-capabilities.js +3 -3
- package/dist/agent/actions/manage-builder-connection.js +5 -0
- package/dist/agent/actions/manage-provider-key-policy.js +5 -0
- package/dist/agent/actions/manage-provider-models.js +5 -0
- package/dist/agent/actions/manage-service-providers.js +5 -0
- package/dist/agent/actions/select-chatgpt-subscription-account.js +5 -0
- package/dist/agent/context-xray/actions/context-evict.js +5 -0
- package/dist/agent/context-xray/actions/context-pin.js +5 -0
- package/dist/agent/context-xray/actions/context-report.js +5 -0
- package/dist/agent/context-xray/actions/context-restore.js +5 -0
- package/dist/agent/execution-fence.d.ts +1 -0
- package/dist/agent/execution-fence.js +5 -0
- package/dist/agent/production-agent.d.ts +35 -2
- package/dist/agent/production-agent.js +629 -32
- package/dist/agent/run-manager.d.ts +2 -0
- package/dist/agent/run-manager.js +397 -115
- package/dist/agent/run-slot-lock.d.ts +2 -0
- package/dist/agent/run-slot-lock.js +6 -0
- package/dist/agent/run-store.d.ts +5 -0
- package/dist/agent/run-store.js +423 -156
- package/dist/agent/thread-data-builder.js +27 -5
- package/dist/agent/types.d.ts +6 -12
- package/dist/agentkit/capabilities.d.ts +1 -1
- package/dist/appearance/actions/get-theme-family.d.ts +8 -0
- package/dist/appearance/actions/get-theme-family.js +38 -0
- package/dist/appearance/actions/set-theme-family.d.ts +7 -0
- package/dist/appearance/actions/set-theme-family.js +33 -0
- package/dist/appearance/theme-family.d.ts +13 -0
- package/dist/appearance/theme-family.js +38 -0
- package/dist/application-state/store.d.ts +5 -0
- package/dist/application-state/store.js +26 -0
- package/dist/chat-threads/schema-migrations.js +17 -0
- package/dist/chat-threads/store.d.ts +21 -1
- package/dist/chat-threads/store.js +223 -41
- package/dist/cli/skills-content/turn-into-app-skill.d.ts +1 -1
- package/dist/cli/skills-content/turn-into-app-skill.js +20 -18
- package/dist/cli/templates-meta.js +14 -0
- package/dist/client/analytics.js +167 -17
- package/dist/client/chat/agentkit-agent-native.js +79 -3
- package/dist/client/chat/agentkit-protocol.js +80 -42
- package/dist/client/chat/runtime.d.ts +5 -1
- package/dist/client/chat/runtime.js +46 -3
- package/dist/client/consent.d.ts +36 -0
- package/dist/client/consent.js +283 -0
- package/dist/client/review/use-review.d.ts +2 -0
- package/dist/client/review/use-review.js +28 -1
- package/dist/client/sharing/useResourceAccessGate.d.ts +3 -2
- package/dist/client/sharing/useResourceAccessGate.js +9 -1
- package/dist/client/theme-family.d.ts +35 -0
- package/dist/client/theme-family.js +223 -0
- package/dist/client/theme.d.ts +1 -1
- package/dist/client/theme.js +5 -2
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/client/use-chat-thread-list.d.ts +2 -0
- package/dist/client/use-chat-thread-list.js +12 -2
- package/dist/client/use-chat-threads.d.ts +1 -0
- package/dist/client/use-chat-threads.js +2 -0
- package/dist/connections/catalog.d.ts +5 -5
- package/dist/connections/catalog.js +22 -3
- package/dist/data-widgets/index.d.ts +374 -5
- package/dist/data-widgets/index.js +242 -11
- package/dist/db/migrations.js +4 -1
- package/dist/db/schema-snapshot.generated.js +8 -1
- package/dist/feature-flags/actions/set-feature-flag.js +5 -0
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +12 -0
- package/dist/feature-flags/store.js +79 -7
- package/dist/file-upload/actions/manage-file-storage.js +5 -0
- package/dist/file-upload/actions/upload-image.js +5 -0
- package/dist/framework-tools.js +2 -0
- package/dist/history/actions/create-resource-version.js +5 -0
- package/dist/history/actions/restore-resource-version.js +5 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/pptx.d.ts +11 -0
- package/dist/ingestion/pptx.js +81 -1
- package/dist/integrations/actions/manage-messaging-channel.js +5 -0
- package/dist/jobs/scheduler.js +17 -1
- package/dist/labs/actions/set-lab.js +5 -0
- package/dist/localization/actions/set-localization-preference.js +5 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/observability/actions/save-observability-instruction-update.js +5 -0
- package/dist/observability/actions/save-observability-review-summary.js +5 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +19 -19
- package/dist/provider-api/actions/provider-api.d.ts +10 -10
- package/dist/provider-api/index.js +9 -2
- package/dist/review/actions/consume-review-feedback.js +5 -0
- package/dist/review/actions/create-review-comment.js +5 -0
- package/dist/review/actions/delete-review-comment.js +5 -0
- package/dist/review/actions/react-to-review-comment.js +5 -0
- package/dist/review/actions/reply-review-comment.js +5 -0
- package/dist/review/actions/resolve-review-thread.js +5 -0
- package/dist/review/actions/send-review-thread-to-agent.js +5 -0
- package/dist/review/actions/set-review-status.js +5 -0
- package/dist/review/actions/set-review-thread-muted.js +5 -0
- package/dist/review/actions/set-review-thread-unread.js +5 -0
- package/dist/review/actions/set-review-threads-unread.js +5 -0
- package/dist/review/actions/update-review-comment-anchor.js +5 -0
- package/dist/review/actions/update-review-comment.js +5 -0
- package/dist/review/suggestions/actions.js +60 -21
- package/dist/review/suggestions/store.d.ts +2 -0
- package/dist/review/suggestions/store.js +28 -0
- package/dist/secrets/actions/delete-api-key.js +5 -0
- package/dist/secrets/routes.d.ts +10 -10
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/agent-chat/context-tools.js +105 -2
- package/dist/server/agent-chat-plugin.d.ts +2 -0
- package/dist/server/agent-chat-plugin.js +242 -54
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/application-state-maintenance.d.ts +2 -0
- package/dist/server/application-state-maintenance.js +2 -0
- package/dist/server/attribution.d.ts +14 -0
- package/dist/server/attribution.js +62 -2
- package/dist/server/auth.js +7 -0
- package/dist/server/consent-route.d.ts +41 -0
- package/dist/server/consent-route.js +102 -0
- package/dist/server/first-touch-route.d.ts +39 -0
- package/dist/server/first-touch-route.js +115 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/queued-submission-inbox-drain.d.ts +9 -0
- package/dist/server/queued-submission-inbox-drain.js +12 -0
- package/dist/server/request-origin.d.ts +6 -0
- package/dist/server/request-origin.js +12 -0
- package/dist/settings/org-settings.d.ts +2 -1
- package/dist/settings/org-settings.js +4 -1
- package/dist/settings/store.d.ts +8 -0
- package/dist/settings/store.js +14 -5
- package/dist/shared/consent.d.ts +31 -0
- package/dist/shared/consent.js +145 -0
- package/dist/shared/first-touch-persistence.d.ts +31 -0
- package/dist/shared/first-touch-persistence.js +53 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +5 -0
- package/dist/sharing/actions/share-resource.js +5 -0
- package/dist/sharing/actions/unshare-resource.js +5 -0
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
- package/dist/usage/actions/get-usage-metrics.js +27 -4
- package/dist/usage/actions/manage-usage-alert.js +5 -0
- package/dist/vite/client.js +8 -6
- package/dist/workspace-connections/actions/bulk-update-workspace-user-groups.js +5 -0
- package/dist/workspace-connections/actions/delete-workspace-user-group.js +5 -0
- package/dist/workspace-connections/actions/upsert-workspace-user-group.js +5 -0
- package/docs/content/actions-access-control.mdx +8 -8
- package/docs/content/actions-defining.mdx +9 -8
- package/docs/content/template-design-developers.mdx +9 -9
- package/docs/content/template-design-features.mdx +1 -3
- package/docs/content/turn-into-app.mdx +4 -0
- package/package.json +4 -3
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie consent for the regions that need it. The regions and categories
|
|
3
|
+
* follow builder.io's consent banner: visitors in these countries opt in, and
|
|
4
|
+
* every other visitor is tracked as before, with no banner.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Countries that see the banner: builder.io's "GDPR" rule, i.e. the EU, the
|
|
8
|
+
* rest of the EEA, Monaco, San Marino, Åland and France's overseas regions.
|
|
9
|
+
* The UK and Switzerland are not on it, matching builder.io.
|
|
10
|
+
*/
|
|
11
|
+
const CONSENT_REGION_COUNTRY_CODES = new Set([
|
|
12
|
+
"AT",
|
|
13
|
+
"AX",
|
|
14
|
+
"BE",
|
|
15
|
+
"BG",
|
|
16
|
+
"CY",
|
|
17
|
+
"CZ",
|
|
18
|
+
"DE",
|
|
19
|
+
"DK",
|
|
20
|
+
"EE",
|
|
21
|
+
"ES",
|
|
22
|
+
"FI",
|
|
23
|
+
"FR",
|
|
24
|
+
"GF",
|
|
25
|
+
"GP",
|
|
26
|
+
"GR",
|
|
27
|
+
"HR",
|
|
28
|
+
"HU",
|
|
29
|
+
"IE",
|
|
30
|
+
"IS",
|
|
31
|
+
"IT",
|
|
32
|
+
"LI",
|
|
33
|
+
"LT",
|
|
34
|
+
"LU",
|
|
35
|
+
"LV",
|
|
36
|
+
"MC",
|
|
37
|
+
"MF",
|
|
38
|
+
"MQ",
|
|
39
|
+
"MT",
|
|
40
|
+
"NL",
|
|
41
|
+
"NO",
|
|
42
|
+
"PL",
|
|
43
|
+
"PT",
|
|
44
|
+
"RE",
|
|
45
|
+
"RO",
|
|
46
|
+
"SE",
|
|
47
|
+
"SI",
|
|
48
|
+
"SK",
|
|
49
|
+
"SM",
|
|
50
|
+
"YT",
|
|
51
|
+
]);
|
|
52
|
+
/** The IANA zones of those countries, for a request with no country header. */
|
|
53
|
+
const CONSENT_REGION_TIME_ZONES = new Set([
|
|
54
|
+
"Africa/Ceuta",
|
|
55
|
+
"America/Cayenne",
|
|
56
|
+
"America/Guadeloupe",
|
|
57
|
+
"America/Marigot",
|
|
58
|
+
"America/Martinique",
|
|
59
|
+
"Asia/Famagusta",
|
|
60
|
+
"Asia/Nicosia",
|
|
61
|
+
"Atlantic/Azores",
|
|
62
|
+
"Atlantic/Canary",
|
|
63
|
+
"Atlantic/Madeira",
|
|
64
|
+
"Atlantic/Reykjavik",
|
|
65
|
+
"Europe/Amsterdam",
|
|
66
|
+
"Europe/Athens",
|
|
67
|
+
"Europe/Berlin",
|
|
68
|
+
"Europe/Bratislava",
|
|
69
|
+
"Europe/Brussels",
|
|
70
|
+
"Europe/Bucharest",
|
|
71
|
+
"Europe/Budapest",
|
|
72
|
+
"Europe/Busingen",
|
|
73
|
+
"Europe/Copenhagen",
|
|
74
|
+
"Europe/Dublin",
|
|
75
|
+
"Europe/Helsinki",
|
|
76
|
+
"Europe/Lisbon",
|
|
77
|
+
"Europe/Ljubljana",
|
|
78
|
+
"Europe/Luxembourg",
|
|
79
|
+
"Europe/Madrid",
|
|
80
|
+
"Europe/Malta",
|
|
81
|
+
"Europe/Mariehamn",
|
|
82
|
+
"Europe/Monaco",
|
|
83
|
+
"Europe/Nicosia",
|
|
84
|
+
"Europe/Oslo",
|
|
85
|
+
"Europe/Paris",
|
|
86
|
+
"Europe/Prague",
|
|
87
|
+
"Europe/Riga",
|
|
88
|
+
"Europe/Rome",
|
|
89
|
+
"Europe/San_Marino",
|
|
90
|
+
"Europe/Sofia",
|
|
91
|
+
"Europe/Stockholm",
|
|
92
|
+
"Europe/Tallinn",
|
|
93
|
+
"Europe/Vaduz",
|
|
94
|
+
"Europe/Vienna",
|
|
95
|
+
"Europe/Vilnius",
|
|
96
|
+
"Europe/Warsaw",
|
|
97
|
+
"Europe/Zagreb",
|
|
98
|
+
"Indian/Mayotte",
|
|
99
|
+
"Indian/Reunion",
|
|
100
|
+
"CET",
|
|
101
|
+
"EET",
|
|
102
|
+
"Eire",
|
|
103
|
+
"Iceland",
|
|
104
|
+
"MET",
|
|
105
|
+
"Poland",
|
|
106
|
+
"Portugal",
|
|
107
|
+
"WET",
|
|
108
|
+
]);
|
|
109
|
+
export function isConsentRegionCountry(code) {
|
|
110
|
+
return CONSENT_REGION_COUNTRY_CODES.has(code?.trim().toUpperCase() ?? "");
|
|
111
|
+
}
|
|
112
|
+
export function isConsentRegionTimeZone(timeZone) {
|
|
113
|
+
return !!timeZone && CONSENT_REGION_TIME_ZONES.has(timeZone);
|
|
114
|
+
}
|
|
115
|
+
export const CONSENT_COOKIE_NAME = "an_consent";
|
|
116
|
+
/** Asked again a year later, like builder.io. */
|
|
117
|
+
export const CONSENT_COOKIE_LIFETIME_SECONDS = 365 * 24 * 60 * 60;
|
|
118
|
+
export const CONSENT_REGION_PATH = "/_agent-native/auth/consent-region";
|
|
119
|
+
export const CONSENT_PATH = "/_agent-native/auth/consent";
|
|
120
|
+
/**
|
|
121
|
+
* One choice covers the site and every app on agent-native.com. The browser
|
|
122
|
+
* and the server must agree, or the two copies become two cookies.
|
|
123
|
+
*/
|
|
124
|
+
export function consentCookieDomain(hostname) {
|
|
125
|
+
const host = hostname.toLowerCase();
|
|
126
|
+
return host === "agent-native.com" || host.endsWith(".agent-native.com")
|
|
127
|
+
? "agent-native.com"
|
|
128
|
+
: null;
|
|
129
|
+
}
|
|
130
|
+
const CONSENT_COOKIE_VERSION = "1";
|
|
131
|
+
/** `1.p1.t0`: version, then one flag per category. */
|
|
132
|
+
export function serializeConsent(choice) {
|
|
133
|
+
return [
|
|
134
|
+
CONSENT_COOKIE_VERSION,
|
|
135
|
+
`p${choice.performance ? 1 : 0}`,
|
|
136
|
+
`t${choice.targeting ? 1 : 0}`,
|
|
137
|
+
].join(".");
|
|
138
|
+
}
|
|
139
|
+
/** The stored choice, or `null` when there is none this version can read. */
|
|
140
|
+
export function parseConsent(value) {
|
|
141
|
+
const match = /^1\.p([01])\.t([01])$/.exec(value?.trim() ?? "");
|
|
142
|
+
if (!match)
|
|
143
|
+
return null;
|
|
144
|
+
return { performance: match[1] === "1", targeting: match[2] === "1" };
|
|
145
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type AttributionTouch } from "./attribution-source.js";
|
|
2
|
+
/**
|
|
3
|
+
* The durable copy of first touch. Our server sets it, because Safari caps
|
|
4
|
+
* cookies written by page JavaScript at seven days; the browser's own `an_ft`
|
|
5
|
+
* cookie and localStorage copy stay the immediate, 30-day copies. Signup and
|
|
6
|
+
* the browser both pick between the copies with `preferFirstTouch`, so they
|
|
7
|
+
* agree on which visit is first touch.
|
|
8
|
+
*/
|
|
9
|
+
export declare const FIRST_TOUCH_SERVER_COOKIE_NAME = "an_fts";
|
|
10
|
+
export declare const FIRST_TOUCH_SERVER_COOKIE_VERSION = "1";
|
|
11
|
+
export declare const FIRST_TOUCH_SERVER_PATH = "/_agent-native/auth/attribution";
|
|
12
|
+
/** Counted from the first visit, never extended by later ones. */
|
|
13
|
+
export declare const FIRST_TOUCH_SERVER_LIFETIME_SECONDS: number;
|
|
14
|
+
/** `name=value` budget, so this and the browser's cookies fit one header. */
|
|
15
|
+
export declare const FIRST_TOUCH_SERVER_COOKIE_MAX_BYTES = 1500;
|
|
16
|
+
export interface TimedFirstTouch extends AttributionTouch {
|
|
17
|
+
landed_at?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Which of two records is first touch: the first visit that had a source,
|
|
21
|
+
* else the first visit. `incumbent` wins a tie, so a copy never displaces the
|
|
22
|
+
* value it came from.
|
|
23
|
+
*/
|
|
24
|
+
export declare function preferFirstTouch<T extends TimedFirstTouch>(incumbent: T | null | undefined, challenger: T | null | undefined): T | null;
|
|
25
|
+
/** Whether two records are the same visit, however each copy was trimmed. */
|
|
26
|
+
export declare function isSameFirstTouch(a: TimedFirstTouch | null | undefined, b: TimedFirstTouch | null | undefined): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* When the durable copy expires: a year after the visit, or `null` once that
|
|
29
|
+
* year is over. A missing or future visit time counts from now.
|
|
30
|
+
*/
|
|
31
|
+
export declare function firstTouchServerExpiry(touch: TimedFirstTouch, now?: number): Date | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { hasAttributionSource, } from "./attribution-source.js";
|
|
2
|
+
/**
|
|
3
|
+
* The durable copy of first touch. Our server sets it, because Safari caps
|
|
4
|
+
* cookies written by page JavaScript at seven days; the browser's own `an_ft`
|
|
5
|
+
* cookie and localStorage copy stay the immediate, 30-day copies. Signup and
|
|
6
|
+
* the browser both pick between the copies with `preferFirstTouch`, so they
|
|
7
|
+
* agree on which visit is first touch.
|
|
8
|
+
*/
|
|
9
|
+
export const FIRST_TOUCH_SERVER_COOKIE_NAME = "an_fts";
|
|
10
|
+
export const FIRST_TOUCH_SERVER_COOKIE_VERSION = "1";
|
|
11
|
+
export const FIRST_TOUCH_SERVER_PATH = "/_agent-native/auth/attribution";
|
|
12
|
+
/** Counted from the first visit, never extended by later ones. */
|
|
13
|
+
export const FIRST_TOUCH_SERVER_LIFETIME_SECONDS = 365 * 24 * 60 * 60;
|
|
14
|
+
/** `name=value` budget, so this and the browser's cookies fit one header. */
|
|
15
|
+
export const FIRST_TOUCH_SERVER_COOKIE_MAX_BYTES = 1500;
|
|
16
|
+
// A record with no readable visit time was trimmed to fit its cookie, so it
|
|
17
|
+
// was stored before any dated record it is compared with.
|
|
18
|
+
function landedAtMs(touch) {
|
|
19
|
+
const time = Date.parse(touch.landed_at ?? "");
|
|
20
|
+
return Number.isFinite(time) ? time : Number.NEGATIVE_INFINITY;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Which of two records is first touch: the first visit that had a source,
|
|
24
|
+
* else the first visit. `incumbent` wins a tie, so a copy never displaces the
|
|
25
|
+
* value it came from.
|
|
26
|
+
*/
|
|
27
|
+
export function preferFirstTouch(incumbent, challenger) {
|
|
28
|
+
if (!incumbent)
|
|
29
|
+
return challenger ?? null;
|
|
30
|
+
if (!challenger)
|
|
31
|
+
return incumbent;
|
|
32
|
+
const incumbentSourced = hasAttributionSource(incumbent);
|
|
33
|
+
if (incumbentSourced !== hasAttributionSource(challenger)) {
|
|
34
|
+
return incumbentSourced ? incumbent : challenger;
|
|
35
|
+
}
|
|
36
|
+
return landedAtMs(challenger) < landedAtMs(incumbent)
|
|
37
|
+
? challenger
|
|
38
|
+
: incumbent;
|
|
39
|
+
}
|
|
40
|
+
/** Whether two records are the same visit, however each copy was trimmed. */
|
|
41
|
+
export function isSameFirstTouch(a, b) {
|
|
42
|
+
return !!a?.landed_at && a.landed_at === b?.landed_at;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* When the durable copy expires: a year after the visit, or `null` once that
|
|
46
|
+
* year is over. A missing or future visit time counts from now.
|
|
47
|
+
*/
|
|
48
|
+
export function firstTouchServerExpiry(touch, now = Date.now()) {
|
|
49
|
+
const landed = Date.parse(touch.landed_at ?? "");
|
|
50
|
+
const start = Number.isFinite(landed) && landed <= now ? landed : now;
|
|
51
|
+
const expires = start + FIRST_TOUCH_SERVER_LIFETIME_SECONDS * 1000;
|
|
52
|
+
return expires > now ? new Date(expires) : null;
|
|
53
|
+
}
|
|
@@ -2,7 +2,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
2
2
|
resourceType: string;
|
|
3
3
|
resourceId: string;
|
|
4
4
|
}, {
|
|
5
|
-
role?: undefined;
|
|
6
5
|
ownerEmail: any;
|
|
7
6
|
visibility: any;
|
|
8
7
|
shares: any[];
|
|
@@ -12,6 +11,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
12
11
|
supportsGroupShares?: boolean;
|
|
13
12
|
};
|
|
14
13
|
orgId?: undefined;
|
|
14
|
+
role?: undefined;
|
|
15
15
|
agentReadable?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
ownerEmail: string;
|
|
@@ -29,6 +29,11 @@ export default defineAction({
|
|
|
29
29
|
const access = await assertAccess(args.resourceType, args.resourceId, "admin", undefined, { skipResourceBody: true });
|
|
30
30
|
return access.resource.visibility !== "public";
|
|
31
31
|
},
|
|
32
|
+
mcpAnnotations: {
|
|
33
|
+
readOnlyHint: false,
|
|
34
|
+
destructiveHint: true,
|
|
35
|
+
openWorldHint: true,
|
|
36
|
+
},
|
|
32
37
|
run: async (args, ctx) => {
|
|
33
38
|
assertWidgetShareWriteGrant(ctx, "set-resource-visibility", args);
|
|
34
39
|
const reg = requireShareableResource(args.resourceType);
|
|
@@ -124,6 +124,11 @@ export default defineAction({
|
|
|
124
124
|
.describe("Optional short note included in the notification email to an individual recipient."),
|
|
125
125
|
}),
|
|
126
126
|
needsApproval: needsExternalShareApproval,
|
|
127
|
+
mcpAnnotations: {
|
|
128
|
+
readOnlyHint: false,
|
|
129
|
+
destructiveHint: true,
|
|
130
|
+
openWorldHint: true,
|
|
131
|
+
},
|
|
127
132
|
run: async (args, ctx) => {
|
|
128
133
|
assertWidgetShareWriteGrant(ctx, "share-resource", args);
|
|
129
134
|
const reg = requireShareableResource(args.resourceType);
|
|
@@ -26,6 +26,11 @@ export default defineAction({
|
|
|
26
26
|
principalType: z.enum(["user", "group", "org"]),
|
|
27
27
|
principalId: z.string(),
|
|
28
28
|
}),
|
|
29
|
+
mcpAnnotations: {
|
|
30
|
+
readOnlyHint: false,
|
|
31
|
+
destructiveHint: true,
|
|
32
|
+
openWorldHint: false,
|
|
33
|
+
},
|
|
29
34
|
run: async (args, ctx) => {
|
|
30
35
|
assertWidgetShareWriteGrant(ctx, "unshare-resource", args);
|
|
31
36
|
const reg = requireShareableResource(args.resourceType);
|
|
@@ -140,6 +140,6 @@ export default defineAction({
|
|
|
140
140
|
|
|
141
141
|
When the gate is truthy and the call isn't yet approved, the loop emits an `approval_required` event and **stops the turn — `run()` never executes**. A predicate gates conditionally (e.g. only external recipients) and **fails closed**: a throw is treated as "approval required". It receives its own copy of the prepared snapshot of the validated arguments, defaults applied, and the approval binds to the snapshot's hash, so an approved call runs only with the arguments that were approved (a Date binds by its time). The human approves via the chat UI's Approve affordance, which re-issues the turn with the call's `approvalKey`, and only then does the action run.
|
|
142
142
|
|
|
143
|
-
Approval is given in the app, so HTTP never grants it. The HTTP action route and the generated Workers entry run a gated call only for the proven app UI (a frontend call from the signed-in user, same origin, holding the short-lived UI capability; `isProvenUiRequest`, the proof `uiOnly` uses) or the app's MCP directory widget. Every other HTTP caller (bearer or API key, MCP OAuth token, org service token,
|
|
143
|
+
Approval is given in the app, so HTTP never grants it. The HTTP action route and the generated Workers entry run a gated call only for the proven app UI (a frontend call from the signed-in user, same origin, holding the short-lived UI capability; `isProvenUiRequest`, the proof `uiOnly` uses) or the app's MCP directory widget. Every other direct HTTP caller (bearer or API key, MCP OAuth token, org service token, extension iframe, or mobile app) gets `409 approval_required`, and a service identity can never approve. A2A tasks use their separate approval flow. The task pauses until its owner approves, then replays the approved tool call under its approval lease. The shared client presents the capability with every write from a signed-in session (minted once per user, reused for nine minutes, never for reads or public pages), so a gated button works on its first request. A call without proof gets `403 ui_capability_required`; the client then re-mints and retries once, which is only the fallback for an expired or rejected capability. The agent loop, plan mode registry, HTTP action route, generated Workers entry, and MCP dispatch evaluate the gate through `preparedCallNeedsApproval`, so a throwing predicate asks there too. The local `pnpm action ...` CLI calls `handler.run()` directly and does not evaluate `needsApproval`. Treat it as a local development tool, not an approval boundary. A caller that must run unattended needs a different action, never a bypass of the gate.
|
|
144
144
|
|
|
145
145
|
**Keep approvals rare** — the default is off and almost every action should leave it off. The canonical example is Mail's `send-email` (`needsApproval: true`). See the `security` skill and the Human Approval doc.
|
|
@@ -140,6 +140,6 @@ export default defineAction({
|
|
|
140
140
|
|
|
141
141
|
When the gate is truthy and the call isn't yet approved, the loop emits an `approval_required` event and **stops the turn — `run()` never executes**. A predicate gates conditionally (e.g. only external recipients) and **fails closed**: a throw is treated as "approval required". It receives its own copy of the prepared snapshot of the validated arguments, defaults applied, and the approval binds to the snapshot's hash, so an approved call runs only with the arguments that were approved (a Date binds by its time). The human approves via the chat UI's Approve affordance, which re-issues the turn with the call's `approvalKey`, and only then does the action run.
|
|
142
142
|
|
|
143
|
-
Approval is given in the app, so HTTP never grants it. The HTTP action route and the generated Workers entry run a gated call only for the proven app UI (a frontend call from the signed-in user, same origin, holding the short-lived UI capability; `isProvenUiRequest`, the proof `uiOnly` uses) or the app's MCP directory widget. Every other HTTP caller (bearer or API key, MCP OAuth token, org service token,
|
|
143
|
+
Approval is given in the app, so HTTP never grants it. The HTTP action route and the generated Workers entry run a gated call only for the proven app UI (a frontend call from the signed-in user, same origin, holding the short-lived UI capability; `isProvenUiRequest`, the proof `uiOnly` uses) or the app's MCP directory widget. Every other direct HTTP caller (bearer or API key, MCP OAuth token, org service token, extension iframe, or mobile app) gets `409 approval_required`, and a service identity can never approve. A2A tasks use their separate approval flow. The task pauses until its owner approves, then replays the approved tool call under its approval lease. The shared client presents the capability with every write from a signed-in session (minted once per user, reused for nine minutes, never for reads or public pages), so a gated button works on its first request. A call without proof gets `403 ui_capability_required`; the client then re-mints and retries once, which is only the fallback for an expired or rejected capability. The agent loop, plan mode registry, HTTP action route, generated Workers entry, and MCP dispatch evaluate the gate through `preparedCallNeedsApproval`, so a throwing predicate asks there too. The local `pnpm action ...` CLI calls `handler.run()` directly and does not evaluate `needsApproval`. Treat it as a local development tool, not an approval boundary. A caller that must run unattended needs a different action, never a bypass of the gate.
|
|
144
144
|
|
|
145
145
|
**Keep approvals rare** — the default is off and almost every action should leave it off. The canonical example is Mail's `send-email` (`needsApproval: true`). See the `security` skill and the Human Approval doc.
|
|
@@ -21,25 +21,15 @@ Four phases, in order. Phase 0 comes before any investigation, not after.
|
|
|
21
21
|
2. **Fix** what the evidence actually proves, at the owning boundary.
|
|
22
22
|
3. **Reply** with useful questions, then recap.
|
|
23
23
|
|
|
24
|
-
Output is fixes. For every unheld in-scope report root this task owns, keep one
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
request. Keep the reaction as history after that action is completed,
|
|
34
|
-
answered, or abandoned; the current reply must say whether the action is
|
|
35
|
-
still open or historical.
|
|
36
|
-
- Every owned root needs one current same-actor reply after the latest human
|
|
37
|
-
reply. Reuse it while the disposition and evidence remain current; do not
|
|
38
|
-
send a duplicate progress reply on every sweep. The reply names verified
|
|
39
|
-
scopes, open scopes, human actions and owners, and why either `✅` or `🎫` is
|
|
40
|
-
absent. An eye-only root is correct when no scope is verified and no separate
|
|
41
|
-
human action is pending; say whether the next step is this workflow's
|
|
42
|
-
investigation or no further action.
|
|
24
|
+
Output is fixes. For every unheld in-scope report root this task owns, keep one
|
|
25
|
+
current same-actor status reply after the latest human message. Write one short
|
|
26
|
+
sentence in plain, non-technical language. Say what changed. Use `🎫` only for
|
|
27
|
+
unresolved work; when you use it, briefly say what still needs investigation or
|
|
28
|
+
what action is needed, and name its owner when known. Do not mention or explain
|
|
29
|
+
absent reactions. Keep scope details and proof in the internal ledger. Add and
|
|
30
|
+
read back root reactions as soon as their proof bar passes, preserve reaction
|
|
31
|
+
history, and follow [`slack-reaction-replies.md`](references/slack-reaction-replies.md).
|
|
32
|
+
Do not reply on held, person-assigned, or `:mag:` items.
|
|
43
33
|
|
|
44
34
|
## Slack channels and ownership
|
|
45
35
|
|
|
@@ -133,11 +123,13 @@ source window, the three matching owned-mark searches, and older roots linked
|
|
|
133
123
|
by in-window replies. For every unheld owned root, compare the latest human
|
|
134
124
|
message, current status reply, verified scopes, open scopes, and root marks.
|
|
135
125
|
Add and read back `✅` for each newly verified scope and `🎫` for each distinct
|
|
136
|
-
pending human action;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
126
|
+
pending human action; keep evidence, scopes, and full actions/owners in the
|
|
127
|
+
internal ledger. The status reply must follow the latest human message and use
|
|
128
|
+
the concise reply rule above: say what changed, and when `🎫` applies, briefly
|
|
129
|
+
name the unresolved action and its owner when known. A verified scope missing
|
|
130
|
+
`✅`, a pending human action missing `🎫`, or no current status is unfinished.
|
|
131
|
+
Finish the complete bounded set once, then stop; do not chase unrelated
|
|
132
|
+
historical marks.
|
|
141
133
|
|
|
142
134
|
Split reports into distinct scopes. Add root `✅` as soon as any named scope
|
|
143
135
|
passes direct post-change proof, even while its PR is open; say **Verified
|
|
@@ -146,9 +138,10 @@ proof. Add root `🎫` for each distinct unfinished action another human must ta
|
|
|
146
138
|
including a requested reporter URL, access grant, evidence, or clarification.
|
|
147
139
|
The mark tracks an outstanding human action, not an accepted team handoff.
|
|
148
140
|
Record reporter requests in `reporterRequests[]`, separately from
|
|
149
|
-
team/engineering `handoffs[]`.
|
|
150
|
-
|
|
151
|
-
|
|
141
|
+
team/engineering `handoffs[]`. Keep verified scopes, open scopes, reporter
|
|
142
|
+
requests, and handoffs in the internal ledger; keep the Slack reply focused on
|
|
143
|
+
the current outcome and any `🎫` follow-up. Keep marks after completion and
|
|
144
|
+
never remove them. For a closed reporter request,
|
|
152
145
|
preserve its request and closure evidence in the historical ticket record; see
|
|
153
146
|
[`slack-reaction-replies.md`](references/slack-reaction-replies.md).
|
|
154
147
|
|
|
@@ -382,29 +375,22 @@ instruction or prompt exception.
|
|
|
382
375
|
Thank issue reporters for opening issues and Slack reporters for sharing.
|
|
383
376
|
Before posting, inspect the full thread and follow the one-reply gate in
|
|
384
377
|
`address-feedback-with-replies` and the [Slack reply reference](references/slack-reaction-replies.md):
|
|
385
|
-
send one
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
Keep publisher and beta checks in the internal recap after the disposition;
|
|
402
|
-
they do not trigger a second reporter reply.
|
|
403
|
-
|
|
404
|
-
### After a PR merges
|
|
405
|
-
|
|
406
|
-
Track publisher state and beta verification in the internal recap. Do not send
|
|
407
|
-
a routine post-merge reporter reply; answer only a direct reporter follow-up.
|
|
378
|
+
send one short sentence in plain, non-technical language, then end with the
|
|
379
|
+
exact bot disclosure `this was sent from a bot.` Say what changed. Use `🎫`
|
|
380
|
+
only for unresolved work; when it is used, briefly say what still needs
|
|
381
|
+
investigation or action and name its owner when known. Do not explain absent
|
|
382
|
+
reactions or mention a closed, historical `🎫`. Keep hashes, branches, CI,
|
|
383
|
+
publisher details, and proof in the internal recap. Never explain workflow
|
|
384
|
+
mechanics or external tracker tickets in Slack. Never send **Open**/**pending**
|
|
385
|
+
or a symptom recap. Ask for reporter input only when it changes the next step.
|
|
386
|
+
|
|
387
|
+
Every root this actor marks with `👀`, `✅`, or `🎫` also needs a current
|
|
388
|
+
same-actor status reply after the latest human reply. One concise reply can
|
|
389
|
+
answer the reporter and record the disposition. Keep verified scopes, open
|
|
390
|
+
scopes, reaction history, and evidence in the internal ledger; do not enumerate
|
|
391
|
+
them or explain absent reactions in Slack. A Slack `🎫` reaction tracks a
|
|
392
|
+
distinct human action, not an external ticket, and remains as history after the
|
|
393
|
+
action closes. Never imply that an external ticket was created or assigned.
|
|
408
394
|
|
|
409
395
|
For a fixed behavior with a Slack `🎫` handoff, state the done behavior and
|
|
410
396
|
remaining action/owner separately; don't imply the fixed scope is open. The
|
|
@@ -453,36 +439,6 @@ otherwise draft the reply, leave the feedback unresolved, and link it in the
|
|
|
453
439
|
recap. This exception is only for PR review feedback, not proactive PR comments
|
|
454
440
|
or issue comments.
|
|
455
441
|
|
|
456
|
-
## Publishing
|
|
457
|
-
|
|
458
|
-
Use this worktree's branch. Batch fixes with one
|
|
459
|
-
`corepack pnpm ship:push -m "<specific fix>"`; each head reruns CI. Sync
|
|
460
|
-
`origin/main` only for GitHub conflicts during review-only work. If the same
|
|
461
|
-
task is already running an explicitly authorized `/ship`, follow that skill's
|
|
462
|
-
safe-sync rule for a confirmed required-check fix on `origin/main`; do not ask
|
|
463
|
-
for another approval. Behind/pending alone never justify syncing.
|
|
464
|
-
|
|
465
|
-
Use `/ship` for PR ownership, push, and merge checks. Never push to another
|
|
466
|
-
person's PR without explicit authorization for that exact PR in this request.
|
|
467
|
-
Push-only authorization means `ship_mode=ready-only`; merging requires separate
|
|
468
|
-
authorization for that PR. Without push authorization, hand off as pending.
|
|
469
|
-
Carry feedback evidence and dispositions into PRs; reference only issues the
|
|
470
|
-
PR fixes.
|
|
471
|
-
Keep source-tested, built, deployed, and observed-live claims separate.
|
|
472
|
-
|
|
473
|
-
Carry exact tracker row ids and the reproduction ledger into the PR or release
|
|
474
|
-
recap; tracker status is not shipping evidence. Mark each row independently: a
|
|
475
|
-
reaction, checkmark, or "reviewed" cannot cover multiple rows, including
|
|
476
|
-
expected, docs-owned, cross-team, or duplicate items. Link each source/docs
|
|
477
|
-
change to its exact PR or commit, and each non-coding disposition to its
|
|
478
|
-
evidence or owner.
|
|
479
|
-
|
|
480
|
-
If no fix is verified, recap why shipping did not start. Unavailable connectors
|
|
481
|
-
and external failures are not shipping blockers.
|
|
482
|
-
While waiting, **Clarification needed** stays open with `👀` and no `✅`; it
|
|
483
|
-
must not block independent fixes unless it could affect a PR change. Later runs
|
|
484
|
-
skip the eye under the ownership gate.
|
|
485
|
-
|
|
486
442
|
## Recap
|
|
487
443
|
|
|
488
444
|
Every eligible item gets a row. Report gated skips by count only, without
|
package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md
CHANGED
|
@@ -329,10 +329,26 @@ chase arrivals or expand a finite catch-up request into an all-history audit.
|
|
|
329
329
|
administrative post or duplicate; record the reason and link a duplicate to
|
|
330
330
|
its canonical report. Include
|
|
331
331
|
the root `threadParentTs`, reply timestamp, author ID, matching disposition,
|
|
332
|
-
evidence, and read-back text.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
evidence, and read-back text. Keep exact scope, proof, and handoff details in
|
|
333
|
+
the ledger. For `Owned elsewhere`, keep the owner's full proof in
|
|
334
|
+
`otherOwnerEvidence.statusReply.evidence`; set its `publicEvidenceSummary` to
|
|
335
|
+
a brief plain-language phrase (2–12 words) that appears in both the evidence
|
|
336
|
+
and the owner's captured reply. Do not require the full internal evidence in
|
|
337
|
+
their Slack text. For active `🎫` actions, add a short plain-language
|
|
338
|
+
`pendingActionSummary` to `statusReply` that names every open action and its
|
|
339
|
+
known owner, and include it in the reply; omit it when no tracked action
|
|
340
|
+
remains open. Keep the exact action in the internal ledger. When that wording
|
|
341
|
+
is too technical or long for Slack, add a
|
|
342
|
+
concise plain-language `publicActionSummary` using the opening words of the
|
|
343
|
+
action and leaving trailing implementation detail out. It must have at least
|
|
344
|
+
two meaningful words and no more than 12 words; the checker requires the
|
|
345
|
+
phrase to match the action. Use the summary in public status replies and
|
|
346
|
+
other readbacks that do not prove owner acceptance. For an accepted handoff,
|
|
347
|
+
the owner's explicit acceptance and the direct request before contextual
|
|
348
|
+
assent must name the full recorded action, even when a shorter public
|
|
349
|
+
summary exists. Every
|
|
350
|
+
distinct unfinished team action gets this actor's root `🎫`, even when no
|
|
351
|
+
person has accepted it. For `status: "unassigned"`, record the responsible team/role or
|
|
336
352
|
`unassigned`; omit the owner Slack ID and acceptance. If this actor asked a
|
|
337
353
|
named person to take the action but they have not accepted, record the exact
|
|
338
354
|
request and keep the handoff unassigned. For `status: "accepted"` or
|
|
@@ -363,7 +379,19 @@ chase arrivals or expand a finite catch-up request into an all-history audit.
|
|
|
363
379
|
replies and bot messages. The status reply must be newer than this human
|
|
364
380
|
reply. If a human answers later, update the disposition and status before
|
|
365
381
|
reconciling it.
|
|
366
|
-
Record each verified `fixedScopes` entry with its proof
|
|
382
|
+
Record each verified `fixedScopes` entry with its proof. For a status with
|
|
383
|
+
fixed scopes, also set `statusReply.publicEvidenceSummary` to a brief,
|
|
384
|
+
plain-language phrase (2–12 words) that can appear in the public reply. For
|
|
385
|
+
every fixed scope, put that scope and the summary together in one sentence of
|
|
386
|
+
its `verification`. Include the summary in both `statusReply.evidence` and
|
|
387
|
+
the captured `statusReply.text`; keep detailed proof in the ledger. The
|
|
388
|
+
summary may paraphrase the internal scope. Record each
|
|
389
|
+
`unfinishedScopes` entry in the ledger. When any remain, set
|
|
390
|
+
`statusReply.unfinishedScopeSummary` to a brief plain-language summary
|
|
391
|
+
(3–12 words) that names remaining work using wording grounded in its recorded
|
|
392
|
+
scope or evidence, and says it is still open; include it in the public status
|
|
393
|
+
even when no separate `🎫` action exists. Omit this field when no unfinished
|
|
394
|
+
scope remains. Record each
|
|
367
395
|
unfinished team/engineering action in `handoffs[]` and each outstanding
|
|
368
396
|
reporter input request in `reporterRequests[]` with its scope, exact action,
|
|
369
397
|
and exact `requestReply`. For
|
|
@@ -386,9 +414,9 @@ chase arrivals or expand a finite catch-up request into an all-history audit.
|
|
|
386
414
|
action is completed, keep it in `handoffs[]` with
|
|
387
415
|
`status: "completed"` and `completion: { evidence, sourceUrl }` or an exact
|
|
388
416
|
owner `reply` (`ts`, `threadParentTs`, `actorId`, and verbatim `text`). The
|
|
389
|
-
|
|
390
|
-
history; completed actions are not open follow-ups and do not block a
|
|
391
|
-
disposition. Only an owner withdrawal moves an accepted action to
|
|
417
|
+
`statusReply.evidence` must cite that completion evidence. Keep the root
|
|
418
|
+
`🎫` as history; completed actions are not open follow-ups and do not block a
|
|
419
|
+
closed disposition. Only an owner withdrawal moves an accepted action to
|
|
392
420
|
`historicalReactionMarks[]`. As soon as direct post-change proof passes, add this actor's
|
|
393
421
|
`✅` to the root and read it back before moving to another scope or report,
|
|
394
422
|
including while its PR is open. Before merge, record **Verified locally** and
|
|
@@ -403,9 +431,10 @@ chase arrivals or expand a finite catch-up request into an all-history audit.
|
|
|
403
431
|
mark remains as history after completion. For an eligible open scope this
|
|
404
432
|
workflow takes, retain the root `👀` as permanent history; do not use it to
|
|
405
433
|
infer whether work remains.
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
434
|
+
Keep the same-thread status reply to one short, plain-language paragraph.
|
|
435
|
+
Say what changed; when an active `🎫` remains, name its next action through
|
|
436
|
+
`pendingActionSummary`. Do not list every scope or explain absent reactions.
|
|
437
|
+
A reply does not replace a
|
|
409
438
|
reaction, and a reaction does not replace a reply. Do not add status
|
|
410
439
|
requirements or reactions to another actor's eye. When later evidence
|
|
411
440
|
invalidates a retained `✅`, remove that scope from active `fixedScopes[]`
|
|
@@ -415,9 +444,17 @@ chase arrivals or expand a finite catch-up request into an all-history audit.
|
|
|
415
444
|
withdraws, move that action out of current `handoffs[]` and record a historical
|
|
416
445
|
`🎫` with its earlier accepted `handoff` plus the owner's exact
|
|
417
446
|
`withdrawalReply` (`ts`, `threadParentTs`, `actorId`, and verbatim `text`).
|
|
418
|
-
|
|
419
|
-
preserve it without presenting it as current proof or an active
|
|
420
|
-
|
|
447
|
+
Record why each retained mark is historical in the internal reaction
|
|
448
|
+
decision; preserve it without presenting it as current proof or an active
|
|
449
|
+
handoff. Keep detailed proof in `previousStatus.evidence` in the internal
|
|
450
|
+
ledger. For a historical `✅`, also record a brief, non-sensitive
|
|
451
|
+
`publicEvidenceSummary` (2–12 words) drawn from that proof. It may paraphrase
|
|
452
|
+
the exact scope, but the scope and summary must appear together in one proof
|
|
453
|
+
sentence. Include the summary in the captured `previousStatus.text`; the
|
|
454
|
+
checker verifies that it is tied to proof for the recorded scope.
|
|
455
|
+
Never put secrets, customer details, or raw logs in the summary. For a
|
|
456
|
+
historical `🎫`, the prior reply must name both the accepted action and its
|
|
457
|
+
owner. The checker validates these details against the captured thread. When every report scope
|
|
421
458
|
and follow-up is closed, post or reuse the final same-thread status and read
|
|
422
459
|
back the status and reactions. Preserve every reaction; disposition and
|
|
423
460
|
status show that work is closed even when the root still has `👀`.
|
|
@@ -481,8 +518,9 @@ back `🎫` even when it is unassigned or unaccepted. Record acceptance only
|
|
|
481
518
|
after a named person's exact reply; otherwise state `owner: unassigned` and
|
|
482
519
|
`status: unassigned`. For reporter evidence, access, or clarification
|
|
483
520
|
requests, record `reporterRequests[]` and add/read back `🎫`; explain that it
|
|
484
|
-
tracks requested input, not a team handoff. In the
|
|
485
|
-
exact proof gap, blocker, and next owner/action.
|
|
521
|
+
tracks requested input, not a team handoff. In the internal ledger, record the
|
|
522
|
+
exact proof gap, blocker, and next owner/action. Keep the current status brief
|
|
523
|
+
and plain-language. An
|
|
486
524
|
eye-only root with unfinished work is pending; an eye-only root with a closed
|
|
487
525
|
verified disposition may retain the eye as history. Never remove or clean up a
|
|
488
526
|
reaction. Slack thread replies appear under the root's reply count, not as
|