@formigio/fazemos-cli 0.10.67 → 0.10.75
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/approvals.d.ts +1 -1
- package/dist/approvals.js +50 -19
- package/dist/approvals.js.map +1 -1
- package/dist/commands/preflight.d.ts +41 -0
- package/dist/commands/preflight.js +706 -0
- package/dist/commands/preflight.js.map +1 -0
- package/dist/commands/provision.d.ts +29 -0
- package/dist/commands/provision.js +382 -0
- package/dist/commands/provision.js.map +1 -0
- package/dist/index.js +124 -5
- package/dist/index.js.map +1 -1
- package/dist/pause.js +42 -11
- package/dist/pause.js.map +1 -1
- package/dist/preflight/repoRead.d.ts +65 -0
- package/dist/preflight/repoRead.js +194 -0
- package/dist/preflight/repoRead.js.map +1 -0
- package/dist/preflight/roster.d.ts +65 -0
- package/dist/preflight/roster.js +153 -0
- package/dist/preflight/roster.js.map +1 -0
- package/dist/preflight/row1_member.d.ts +8 -0
- package/dist/preflight/row1_member.js +64 -0
- package/dist/preflight/row1_member.js.map +1 -0
- package/dist/preflight/row2_roleRegistration.d.ts +18 -0
- package/dist/preflight/row2_roleRegistration.js +156 -0
- package/dist/preflight/row2_roleRegistration.js.map +1 -0
- package/dist/preflight/row3_persona.d.ts +24 -0
- package/dist/preflight/row3_persona.js +92 -0
- package/dist/preflight/row3_persona.js.map +1 -0
- package/dist/preflight/row3_playbook.d.ts +30 -0
- package/dist/preflight/row3_playbook.js +142 -0
- package/dist/preflight/row3_playbook.js.map +1 -0
- package/dist/preflight/row3_rolesJson.d.ts +12 -0
- package/dist/preflight/row3_rolesJson.js +38 -0
- package/dist/preflight/row3_rolesJson.js.map +1 -0
- package/dist/preflight/row3_workspace.d.ts +24 -0
- package/dist/preflight/row3_workspace.js +253 -0
- package/dist/preflight/row3_workspace.js.map +1 -0
- package/dist/preflight/row4_ssm.d.ts +57 -0
- package/dist/preflight/row4_ssm.js +235 -0
- package/dist/preflight/row4_ssm.js.map +1 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.d.ts +20 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.js +113 -0
- package/dist/preflight/row5_workerLambdaWakeConfig.js.map +1 -0
- package/dist/preflight/row6_ingest.d.ts +20 -0
- package/dist/preflight/row6_ingest.js +178 -0
- package/dist/preflight/row6_ingest.js.map +1 -0
- package/dist/preflight/schema.d.ts +175 -0
- package/dist/preflight/schema.js +62 -0
- package/dist/preflight/schema.js.map +1 -0
- package/dist/preflight/workerLambdas.d.ts +22 -0
- package/dist/preflight/workerLambdas.js +25 -0
- package/dist/preflight/workerLambdas.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 1 — Agent member exists in org with the target role_slug.
|
|
3
|
+
*
|
|
4
|
+
* Data source: GET /api/organizations/:orgId/members?type=agent
|
|
5
|
+
* Checks: (a) an agent member named agentName exists, (b) role_slug ∈ agent_config.roles.
|
|
6
|
+
*/
|
|
7
|
+
import { api } from '../api.js';
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a display name for fuzzy matching (case-insensitive, collapse separators).
|
|
10
|
+
*/
|
|
11
|
+
function normName(s) {
|
|
12
|
+
return s.toLowerCase().replace(/[-_\s]+/g, ' ').trim();
|
|
13
|
+
}
|
|
14
|
+
export async function checkRow1Member(orgId, agentName, roleSlug) {
|
|
15
|
+
const base = { id: '1', name: 'agent member + credential' };
|
|
16
|
+
try {
|
|
17
|
+
const data = (await api('GET', `/api/organizations/${orgId}/members?type=agent`, undefined, { noProjectHeader: true }));
|
|
18
|
+
const members = data.members ?? [];
|
|
19
|
+
const agent = members.find((m) => m.member_type === 'agent' && normName(m.display_name) === normName(agentName));
|
|
20
|
+
if (!agent) {
|
|
21
|
+
return {
|
|
22
|
+
...base,
|
|
23
|
+
status: 'fail',
|
|
24
|
+
detail: `No agent member named '${agentName}' found in org (${members.filter((m) => m.member_type === 'agent').length} total agents).`,
|
|
25
|
+
fix_command: `fazemos agents register --name "${agentName}" --model sonnet`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const roles = agent.agent_config?.roles ?? [];
|
|
29
|
+
if (!roles.includes(roleSlug)) {
|
|
30
|
+
return {
|
|
31
|
+
...base,
|
|
32
|
+
status: 'fail',
|
|
33
|
+
detail: `Agent '${agentName}' (id=${agent.id}) found but role '${roleSlug}' not in agent_config.roles: [${roles.join(', ') || 'empty'}].`,
|
|
34
|
+
fix_command: null,
|
|
35
|
+
fix_instruction: `Update agent '${agentName}' config to include role '${roleSlug}' in its roles array. Re-run: fazemos agents register --name "${agentName}" --roles ${roleSlug}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
...base,
|
|
40
|
+
status: 'pass',
|
|
41
|
+
detail: `${agentName} (id=${agent.id}), roles=[${roles.join(', ')}]`,
|
|
42
|
+
fix_command: null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err?.status === 403 || err?.status === 401) {
|
|
47
|
+
return {
|
|
48
|
+
...base,
|
|
49
|
+
status: 'tooling_error',
|
|
50
|
+
detail: 'Access denied — owner/admin role required to list agent members.',
|
|
51
|
+
fix_command: null,
|
|
52
|
+
fix_instruction: 'Contact your org admin to grant owner or admin role, then retry.',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
...base,
|
|
57
|
+
status: 'tooling_error',
|
|
58
|
+
detail: `API call failed: ${err?.message ?? String(err)}`,
|
|
59
|
+
fix_command: null,
|
|
60
|
+
fix_instruction: 'Check your Fazemos API credentials and active org, then retry.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=row1_member.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row1_member.js","sourceRoot":"","sources":["../../src/preflight/row1_member.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAchC;;GAEG;AACH,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,SAAiB,EACjB,QAAgB;IAEhB,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,2BAA2B,EAAE,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CACrB,KAAK,EACL,sBAAsB,KAAK,qBAAqB,EAChD,SAAS,EACT,EAAE,eAAe,EAAE,IAAI,EAAE,CAC1B,CAA8B,CAAC;QAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,QAAQ,CAAC,SAAS,CAAC,CACrF,CAAC;QAEF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,0BAA0B,SAAS,mBAAmB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,OAAO,CAAC,CAAC,MAAM,iBAAiB;gBACtI,WAAW,EAAE,mCAAmC,SAAS,kBAAkB;aAC5E,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,UAAU,SAAS,SAAS,KAAK,CAAC,EAAE,qBAAqB,QAAQ,iCAAiC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI;gBACzI,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,iBAAiB,SAAS,6BAA6B,QAAQ,iEAAiE,SAAS,aAAa,QAAQ,EAAE;aAClL,CAAC;QACJ,CAAC;QAED,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,SAAS,QAAQ,KAAK,CAAC,EAAE,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACpE,WAAW,EAAE,IAAI;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,EAAE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;YAC/C,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,eAAe;gBACvB,MAAM,EAAE,kEAAkE;gBAC1E,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,kEAAkE;aACpF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,oBAAoB,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;YACzD,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,gEAAgE;SAClF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 2 — role_registrations row exists, active, and bound to the correct
|
|
3
|
+
* (org_id, project_id). Also verifies resolver-key parity (r3 D8).
|
|
4
|
+
*
|
|
5
|
+
* Data source: GET /api/role-registrations/lookup?workspace=&role_slug=&org_id=<uuid>
|
|
6
|
+
* Outcome: PASS | FAIL(no_registration) | FAIL(bound_elsewhere) |
|
|
7
|
+
* FAIL(resolver_ambiguous) | FAIL(resolver_mismatch)
|
|
8
|
+
*/
|
|
9
|
+
import type { PreflightRow } from './schema.js';
|
|
10
|
+
export declare function checkRow2RoleRegistration(opts: {
|
|
11
|
+
workspace: string;
|
|
12
|
+
roleSlug: string;
|
|
13
|
+
orgId: string;
|
|
14
|
+
projectId: string | null;
|
|
15
|
+
orgSlug: string;
|
|
16
|
+
projectSlug: string;
|
|
17
|
+
env: string;
|
|
18
|
+
}): Promise<PreflightRow>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 2 — role_registrations row exists, active, and bound to the correct
|
|
3
|
+
* (org_id, project_id). Also verifies resolver-key parity (r3 D8).
|
|
4
|
+
*
|
|
5
|
+
* Data source: GET /api/role-registrations/lookup?workspace=&role_slug=&org_id=<uuid>
|
|
6
|
+
* Outcome: PASS | FAIL(no_registration) | FAIL(bound_elsewhere) |
|
|
7
|
+
* FAIL(resolver_ambiguous) | FAIL(resolver_mismatch)
|
|
8
|
+
*/
|
|
9
|
+
import { api } from '../api.js';
|
|
10
|
+
export async function checkRow2RoleRegistration(opts) {
|
|
11
|
+
const { workspace, roleSlug, orgId, projectId, orgSlug, projectSlug, env } = opts;
|
|
12
|
+
const base = { id: '2', name: 'role_registrations row' };
|
|
13
|
+
try {
|
|
14
|
+
const params = new URLSearchParams({ workspace, role_slug: roleSlug, org_id: orgId });
|
|
15
|
+
const data = (await api('GET', `/api/role-registrations/lookup?${params.toString()}`, undefined, { noProjectHeader: true }));
|
|
16
|
+
const reg = data.registration;
|
|
17
|
+
const candidates = data.resolver_candidates ?? null;
|
|
18
|
+
const resolverDeterministic = data.resolver_deterministic ?? false;
|
|
19
|
+
// ── No row or soft-deleted ──────────────────────────────────────────────
|
|
20
|
+
if (!data.found || !reg || !reg.active) {
|
|
21
|
+
const projFlag = projectId ? ` --project-id ${projectSlug}` : '';
|
|
22
|
+
return {
|
|
23
|
+
...base,
|
|
24
|
+
status: 'fail',
|
|
25
|
+
variant: 'no_registration',
|
|
26
|
+
detail: `No active role_registrations row for workspace='${workspace}', role_slug='${roleSlug}'.${!data.found ? '' : ' Row exists but active=false.'}`,
|
|
27
|
+
fix_command: `cd <workspace-repo> && fazemos --env ${env} roles sync --org-id ${orgSlug}${projFlag}`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// ── Bound to different (org, project) ───────────────────────────────────
|
|
31
|
+
const sameOrg = reg.org_id === orgId;
|
|
32
|
+
const sameProject = projectId ? reg.project_id === projectId : true;
|
|
33
|
+
if (!sameOrg || !sameProject) {
|
|
34
|
+
return {
|
|
35
|
+
...base,
|
|
36
|
+
status: 'fail',
|
|
37
|
+
variant: 'bound_elsewhere',
|
|
38
|
+
detail: `Row exists but bound to org=${reg.org_slug}, project=${reg.project_slug ?? 'null'} (caller wants org=${orgSlug}, project=${projectSlug}).`,
|
|
39
|
+
bound_to: {
|
|
40
|
+
org_slug: reg.org_slug,
|
|
41
|
+
org_id: reg.org_id,
|
|
42
|
+
project_slug: reg.project_slug,
|
|
43
|
+
project_id: reg.project_id,
|
|
44
|
+
},
|
|
45
|
+
fix_command: null,
|
|
46
|
+
fix_instruction: `role_registrations row for (workspace='${workspace}', role_slug='${roleSlug}') is already bound ` +
|
|
47
|
+
`to org=${reg.org_slug}, project=${reg.project_slug ?? 'null'}. ` +
|
|
48
|
+
`UNIQUE (workspace, role_slug) prevents holding both bindings — a sync attempt from ` +
|
|
49
|
+
`a different project would clobber the current binding, not add a second one. ` +
|
|
50
|
+
`See ROLE-REGISTRY-PROJECT-ADDRESSABILITY. ` +
|
|
51
|
+
`If you meant to migrate the binding, deactivate the old row first ` +
|
|
52
|
+
`(fazemos roles set-inactive --workspace ${workspace} --role-slug ${roleSlug}) ` +
|
|
53
|
+
`then re-run from the target project.`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// ── Resolver-parity checks (r3) ─────────────────────────────────────────
|
|
57
|
+
if (candidates === null) {
|
|
58
|
+
// API is pre-r3 — degrade gracefully to r2 tri-state PASS
|
|
59
|
+
return {
|
|
60
|
+
...base,
|
|
61
|
+
status: 'pass',
|
|
62
|
+
detail: `${reg.filler_identity}, active=true, bound=(org=${orgSlug}, project=${projectSlug}). Resolver parity check unavailable (API may be pre-r3).`,
|
|
63
|
+
fix_command: null,
|
|
64
|
+
resolver_parity_unavailable: true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// FAIL: ambiguous — N > 1 candidates for (role_slug, org_id) with no ORDER BY
|
|
68
|
+
if (candidates.length > 1) {
|
|
69
|
+
const candidateList = candidates
|
|
70
|
+
.map((c) => `${c.workspace} → ${c.project_slug ?? 'null'}`)
|
|
71
|
+
.join(', ');
|
|
72
|
+
return {
|
|
73
|
+
...base,
|
|
74
|
+
status: 'fail',
|
|
75
|
+
variant: 'resolver_ambiguous',
|
|
76
|
+
detail: `${candidates.length} active role_registrations rows for (role_slug='${roleSlug}', org_id=${orgSlug}); resolver picks nondeterministically.`,
|
|
77
|
+
resolver_candidates: candidates,
|
|
78
|
+
resolver_deterministic: resolverDeterministic,
|
|
79
|
+
fix_command: null,
|
|
80
|
+
fix_instruction: `${candidates.length} active role_registrations rows exist for ` +
|
|
81
|
+
`(role_slug='${roleSlug}', org_id=${orgSlug}), with candidates [${candidateList}]. ` +
|
|
82
|
+
`Dispatch resolution (dispatchesService.ts:345, :356, :1003, :1050) has no ORDER BY ` +
|
|
83
|
+
`and picks nondeterministically. ` +
|
|
84
|
+
`See ROLE-REGISTRY-PROJECT-ADDRESSABILITY (Stage 1 = resolver determinism, ` +
|
|
85
|
+
`Stage 0 = data repair for existing duplicates). F53 detects only.`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// FAIL: mismatch — the schema-key row is not the one dispatch would pick
|
|
89
|
+
if (candidates.length === 1 && candidates[0].id !== reg.id) {
|
|
90
|
+
return {
|
|
91
|
+
...base,
|
|
92
|
+
status: 'fail',
|
|
93
|
+
variant: 'resolver_mismatch',
|
|
94
|
+
detail: `Schema-key row (id=${reg.id}) ≠ resolver-candidate row (id=${candidates[0].id}).`,
|
|
95
|
+
resolver_candidates: candidates,
|
|
96
|
+
resolver_deterministic: resolverDeterministic,
|
|
97
|
+
fix_command: null,
|
|
98
|
+
fix_instruction: `role_registrations row (workspace='${workspace}', role_slug='${roleSlug}') hit by the schema key ` +
|
|
99
|
+
`does not match the row dispatch would resolve for (role_slug='${roleSlug}', org_id=${orgSlug}). ` +
|
|
100
|
+
`Schema row: id=${reg.id}, workspace=${reg.workspace}, project=${reg.project_slug ?? 'null'}. ` +
|
|
101
|
+
`Resolver row: id=${candidates[0].id}, workspace=${candidates[0].workspace}, ` +
|
|
102
|
+
`project=${candidates[0].project_slug ?? 'null'}. ` +
|
|
103
|
+
`See ROLE-REGISTRY-PROJECT-ADDRESSABILITY. F53 detects only.`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// ── PASS ────────────────────────────────────────────────────────────────
|
|
107
|
+
const resolverNote = candidates.length === 0
|
|
108
|
+
? ' (no resolver candidates — resolver would not resolve this role)'
|
|
109
|
+
: ` resolver deterministic: ${resolverDeterministic}`;
|
|
110
|
+
return {
|
|
111
|
+
...base,
|
|
112
|
+
status: 'pass',
|
|
113
|
+
detail: `${reg.filler_identity}, active=true, bound=(org=${orgSlug}, project=${projectSlug}).${resolverNote}`,
|
|
114
|
+
fix_command: null,
|
|
115
|
+
resolver_candidates: candidates.length > 0 ? candidates : undefined,
|
|
116
|
+
resolver_deterministic: resolverDeterministic,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (err?.status === 403 || err?.status === 401) {
|
|
121
|
+
return {
|
|
122
|
+
...base,
|
|
123
|
+
status: 'tooling_error',
|
|
124
|
+
detail: 'Access denied — owner/admin role required for role_registrations lookup.',
|
|
125
|
+
fix_command: null,
|
|
126
|
+
fix_instruction: 'Contact your org admin to grant owner or admin role, then retry.',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// 404 on this specific endpoint means it is not deployed on this env yet.
|
|
130
|
+
// Rule rul_f53_row2_404_is_tooling_error (AC13): a 404 from the lookup endpoint is
|
|
131
|
+
// TOOLING-ERROR (exit 2), NOT FAIL(no_registration). An unverifiable row must never
|
|
132
|
+
// carry an executable fix — roles sync upserts on (workspace, role_slug) and can
|
|
133
|
+
// silently clobber a working binding whose status cannot be confirmed (rul_f53_row2_clobber_guard).
|
|
134
|
+
if (err?.status === 404) {
|
|
135
|
+
return {
|
|
136
|
+
...base,
|
|
137
|
+
status: 'tooling_error',
|
|
138
|
+
detail: `GET /api/role-registrations/lookup returned HTTP 404 — ` +
|
|
139
|
+
`the endpoint is not yet deployed on env '${env}'. ` +
|
|
140
|
+
`The row_registrations row may already exist; it cannot be verified until the endpoint is deployed. ` +
|
|
141
|
+
`Running roles sync against an unverified binding risks clobber (rul_f53_row2_clobber_guard).`,
|
|
142
|
+
fix_command: null,
|
|
143
|
+
fix_instruction: `Deploy the updated fazemos-api to env '${env}' (the /api/role-registrations/lookup endpoint ` +
|
|
144
|
+
`must be present), then re-run: fazemos --env ${env} agents preflight ${orgSlug}/${projectSlug}/${roleSlug}`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...base,
|
|
149
|
+
status: 'tooling_error',
|
|
150
|
+
detail: `API call failed: ${err?.message ?? String(err)}`,
|
|
151
|
+
fix_command: null,
|
|
152
|
+
fix_instruction: 'Check your Fazemos API credentials and active org, then retry.',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=row2_roleRegistration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row2_roleRegistration.js","sourceRoot":"","sources":["../../src/preflight/row2_roleRegistration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3a (r3.2) — Effective persona non-empty assertion.
|
|
3
|
+
*
|
|
4
|
+
* r3.2 SUPERSEDES r3.1's file-presence check.
|
|
5
|
+
* Calls GET /api/organizations/:orgId/projects/:projectId/agents/:name
|
|
6
|
+
* (the existing project-scoped agent detail endpoint, which already applies
|
|
7
|
+
* the F18 file-layer over the F17 DB systemPrompt per AII Fix 3).
|
|
8
|
+
* Asserts response.agent.effective_config.systemPrompt.trim().length > 0.
|
|
9
|
+
*
|
|
10
|
+
* Three fixture classes (per rul_f53_row3a_verifies_effective_persona):
|
|
11
|
+
* (a) DB-only agent (ollie/cass/tessa) — no docs/agents/<name>.md file,
|
|
12
|
+
* non-empty DB systemPrompt → PASS. The missing file is HEALTHY
|
|
13
|
+
* fall-through; r3.1 false-FAILed here 3× on prod 2026-08-19.
|
|
14
|
+
* (b) BUG160 class — docs/agents/<name>.md exists but is empty/whitespace;
|
|
15
|
+
* F18 file clobbers DB with "". Effective persona empty → FAIL.
|
|
16
|
+
* (c) BUG161 class — no file AND DB empty → FAIL.
|
|
17
|
+
* (d) 404 from endpoint → INDETERMINATE (Row 1 catches the member miss).
|
|
18
|
+
*/
|
|
19
|
+
import type { PreflightRow } from './schema.js';
|
|
20
|
+
export declare function checkRow3aPersona(opts: {
|
|
21
|
+
agentName: string;
|
|
22
|
+
orgId: string;
|
|
23
|
+
projectId: string;
|
|
24
|
+
}): Promise<PreflightRow>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3a (r3.2) — Effective persona non-empty assertion.
|
|
3
|
+
*
|
|
4
|
+
* r3.2 SUPERSEDES r3.1's file-presence check.
|
|
5
|
+
* Calls GET /api/organizations/:orgId/projects/:projectId/agents/:name
|
|
6
|
+
* (the existing project-scoped agent detail endpoint, which already applies
|
|
7
|
+
* the F18 file-layer over the F17 DB systemPrompt per AII Fix 3).
|
|
8
|
+
* Asserts response.agent.effective_config.systemPrompt.trim().length > 0.
|
|
9
|
+
*
|
|
10
|
+
* Three fixture classes (per rul_f53_row3a_verifies_effective_persona):
|
|
11
|
+
* (a) DB-only agent (ollie/cass/tessa) — no docs/agents/<name>.md file,
|
|
12
|
+
* non-empty DB systemPrompt → PASS. The missing file is HEALTHY
|
|
13
|
+
* fall-through; r3.1 false-FAILed here 3× on prod 2026-08-19.
|
|
14
|
+
* (b) BUG160 class — docs/agents/<name>.md exists but is empty/whitespace;
|
|
15
|
+
* F18 file clobbers DB with "". Effective persona empty → FAIL.
|
|
16
|
+
* (c) BUG161 class — no file AND DB empty → FAIL.
|
|
17
|
+
* (d) 404 from endpoint → INDETERMINATE (Row 1 catches the member miss).
|
|
18
|
+
*/
|
|
19
|
+
import { api } from '../api.js';
|
|
20
|
+
export async function checkRow3aPersona(opts) {
|
|
21
|
+
const { agentName, orgId, projectId } = opts;
|
|
22
|
+
const base = { id: '3a', name: 'persona (effective)' };
|
|
23
|
+
try {
|
|
24
|
+
const data = (await api('GET', `/api/organizations/${orgId}/projects/${projectId}/agents/${encodeURIComponent(agentName)}`, undefined, { noProjectHeader: true }));
|
|
25
|
+
const systemPrompt = data.agent?.effective_config?.systemPrompt ?? '';
|
|
26
|
+
const trimmed = systemPrompt.trim();
|
|
27
|
+
if (trimmed.length === 0) {
|
|
28
|
+
// Distinguish BUG160 class (file exists but empty, clobbers DB) from
|
|
29
|
+
// BUG161 class (no file and DB empty) when role_doc_path is available.
|
|
30
|
+
const hasRoleDoc = data.agent?.role_doc_path != null;
|
|
31
|
+
const roleDocPath = data.agent?.role_doc_path;
|
|
32
|
+
const fixInstruction = hasRoleDoc
|
|
33
|
+
? `The F18 file layer at ${roleDocPath} is empty or whitespace-only and is ` +
|
|
34
|
+
`overriding the DB systemPrompt with an empty string. ` +
|
|
35
|
+
`Either delete the file to fall through to the DB systemPrompt, ` +
|
|
36
|
+
`or author non-empty persona content into it. (BUG160 class)`
|
|
37
|
+
: `Both the DB systemPrompt and any F18 file-layer override are empty — the agent ` +
|
|
38
|
+
`would wake promptless. Set the DB systemPrompt via \`fazemos agents update-config\` ` +
|
|
39
|
+
`or author docs/agents/${agentName}.md in the workspace repo with persona content. (BUG161 class)`;
|
|
40
|
+
return {
|
|
41
|
+
...base,
|
|
42
|
+
status: 'fail',
|
|
43
|
+
detail: `Effective persona for agent '${agentName}' is empty (trim length 0). ` +
|
|
44
|
+
`Agent would wake with no persona.`,
|
|
45
|
+
fix_command: null,
|
|
46
|
+
fix_instruction: fixInstruction,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
...base,
|
|
51
|
+
status: 'pass',
|
|
52
|
+
detail: `Effective persona for agent '${agentName}' is non-empty ` +
|
|
53
|
+
`(${trimmed.length} chars after trim). Agent runtime has an operative persona.`,
|
|
54
|
+
fix_command: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const status = err?.status ?? 0;
|
|
59
|
+
if (status === 404) {
|
|
60
|
+
// Agent not registered (or not visible) at this org/project level.
|
|
61
|
+
// INDETERMINATE: cannot classify the row — Row 1 will separately
|
|
62
|
+
// report the member miss. Exit contribution: 3 (INCOMPLETE).
|
|
63
|
+
// Per rul_f53_row_level_indeterminate_state + rul_f53_row3a_verifies_effective_persona.
|
|
64
|
+
return {
|
|
65
|
+
...base,
|
|
66
|
+
status: 'indeterminate',
|
|
67
|
+
detail: `Agent '${agentName}' not found (HTTP 404) — effective persona cannot be resolved ` +
|
|
68
|
+
`until the agent is registered at this org/project level.`,
|
|
69
|
+
fix_command: null,
|
|
70
|
+
fix_instruction: `Ensure the agent member exists first (Row 1 check). Register with: ` +
|
|
71
|
+
`\`fazemos agents register\` — then re-run preflight.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (status === 401 || status === 403) {
|
|
75
|
+
return {
|
|
76
|
+
...base,
|
|
77
|
+
status: 'tooling_error',
|
|
78
|
+
detail: `Access denied (HTTP ${status}) when fetching agent '${agentName}'.`,
|
|
79
|
+
fix_command: null,
|
|
80
|
+
fix_instruction: 'Check your Fazemos API credentials and org membership, then retry.',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
...base,
|
|
85
|
+
status: 'tooling_error',
|
|
86
|
+
detail: `API call failed (HTTP ${status}): ${err?.message ?? String(err)}`,
|
|
87
|
+
fix_command: null,
|
|
88
|
+
fix_instruction: 'Check your Fazemos API credentials and active org, then retry.',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=row3_persona.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row3_persona.js","sourceRoot":"","sources":["../../src/preflight/row3_persona.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAgBhC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAIvC;IACC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,qBAAqB,EAAW,CAAC;IAEhE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CACrB,KAAK,EACL,sBAAsB,KAAK,aAAa,SAAS,WAAW,kBAAkB,CAAC,SAAS,CAAC,EAAE,EAC3F,SAAS,EACT,EAAE,eAAe,EAAE,IAAI,EAAE,CAC1B,CAAwB,CAAC;QAE1B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,YAAY,IAAI,EAAE,CAAC;QACtE,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;QAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,qEAAqE;YACrE,uEAAuE;YACvE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI,IAAI,CAAC;YACrD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC;YAC9C,MAAM,cAAc,GAAG,UAAU;gBAC/B,CAAC,CAAC,yBAAyB,WAAW,sCAAsC;oBAC1E,uDAAuD;oBACvD,iEAAiE;oBACjE,6DAA6D;gBAC/D,CAAC,CAAC,iFAAiF;oBACjF,sFAAsF;oBACtF,yBAAyB,SAAS,gEAAgE,CAAC;YAEvG,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,MAAM;gBACd,MAAM,EACJ,gCAAgC,SAAS,8BAA8B;oBACvE,mCAAmC;gBACrC,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,cAAc;aAChC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM;YACd,MAAM,EACJ,gCAAgC,SAAS,iBAAiB;gBAC1D,IAAI,OAAO,CAAC,MAAM,6DAA6D;YACjF,WAAW,EAAE,IAAI;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,CAAC,CAAC;QAEhC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,mEAAmE;YACnE,iEAAiE;YACjE,6DAA6D;YAC7D,wFAAwF;YACxF,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,eAAe;gBACvB,MAAM,EACJ,UAAU,SAAS,gEAAgE;oBACnF,0DAA0D;gBAC5D,WAAW,EAAE,IAAI;gBACjB,eAAe,EACb,qEAAqE;oBACrE,sDAAsD;aACzD,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACrC,OAAO;gBACL,GAAG,IAAI;gBACP,MAAM,EAAE,eAAe;gBACvB,MAAM,EAAE,uBAAuB,MAAM,0BAA0B,SAAS,IAAI;gBAC5E,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,oEAAoE;aACtF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,yBAAyB,MAAM,MAAM,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE;YAC1E,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,gEAAgE;SAClF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3b (r3.2) — Cadence-aware playbook classifier.
|
|
3
|
+
*
|
|
4
|
+
* r3.2 SUPERSEDES r3.1's unconditional FAIL on missing playbook.
|
|
5
|
+
* Classifies each role as cadence-bearing vs. dispatch-driven via the
|
|
6
|
+
* SSM triggers allowlist (/fazemos/<env>/triggers/allowlist — same
|
|
7
|
+
* parameter Row 4c reads; Row 3b reuses Row 4c's read output to avoid
|
|
8
|
+
* a second SSM call via the `ssmContext` parameter).
|
|
9
|
+
*
|
|
10
|
+
* State machine (rul_f53_row3b_classifies_by_cadence_signal):
|
|
11
|
+
* playbook present → PASS (regardless of cadence classification)
|
|
12
|
+
* cadence-bearing + no playbook → FAIL (real miss)
|
|
13
|
+
* dispatch-driven + no playbook → SKIP "role is dispatch-driven; playbook not required by design"
|
|
14
|
+
* SSM unavailable + no playbook → INDETERMINATE (cannot classify)
|
|
15
|
+
* SSM unavailable + playbook present → PASS (classification not needed)
|
|
16
|
+
*
|
|
17
|
+
* This closes 7 of the 10 false FAILs from the 2026-08-19 prod run.
|
|
18
|
+
*/
|
|
19
|
+
import type { RoleEntry } from '../dispatch.js';
|
|
20
|
+
import type { PreflightRow } from './schema.js';
|
|
21
|
+
export interface SsmTriggersContext {
|
|
22
|
+
/** The role slugs in the SSM triggers allowlist, or 'unavailable' if Row 4c TOOLING-ERRORed. */
|
|
23
|
+
triggers_allowlist: string[] | 'unavailable';
|
|
24
|
+
}
|
|
25
|
+
export declare function checkRow3bPlaybook(opts: {
|
|
26
|
+
workspaceRoot: string;
|
|
27
|
+
roleSlug: string;
|
|
28
|
+
roleEntry: RoleEntry | undefined;
|
|
29
|
+
ssmContext: SsmTriggersContext;
|
|
30
|
+
}): Promise<PreflightRow>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3b (r3.2) — Cadence-aware playbook classifier.
|
|
3
|
+
*
|
|
4
|
+
* r3.2 SUPERSEDES r3.1's unconditional FAIL on missing playbook.
|
|
5
|
+
* Classifies each role as cadence-bearing vs. dispatch-driven via the
|
|
6
|
+
* SSM triggers allowlist (/fazemos/<env>/triggers/allowlist — same
|
|
7
|
+
* parameter Row 4c reads; Row 3b reuses Row 4c's read output to avoid
|
|
8
|
+
* a second SSM call via the `ssmContext` parameter).
|
|
9
|
+
*
|
|
10
|
+
* State machine (rul_f53_row3b_classifies_by_cadence_signal):
|
|
11
|
+
* playbook present → PASS (regardless of cadence classification)
|
|
12
|
+
* cadence-bearing + no playbook → FAIL (real miss)
|
|
13
|
+
* dispatch-driven + no playbook → SKIP "role is dispatch-driven; playbook not required by design"
|
|
14
|
+
* SSM unavailable + no playbook → INDETERMINATE (cannot classify)
|
|
15
|
+
* SSM unavailable + playbook present → PASS (classification not needed)
|
|
16
|
+
*
|
|
17
|
+
* This closes 7 of the 10 false FAILs from the 2026-08-19 prod run.
|
|
18
|
+
*/
|
|
19
|
+
import { checkGhAvailable, getWorkspaceGitHubRepo, listDirectoryFilenamesOnGitHub, ToolingError, } from './repoRead.js';
|
|
20
|
+
/**
|
|
21
|
+
* Derive the role's directory path from its inbox path.
|
|
22
|
+
* e.g. "projects/fazemos/roles/project-manager/inbox/" → "projects/fazemos/roles/project-manager"
|
|
23
|
+
* Falls back to "roles/<role_slug>" if inbox is not set.
|
|
24
|
+
*/
|
|
25
|
+
function deriveRoleDir(roleEntry, roleSlug) {
|
|
26
|
+
if (roleEntry?.inbox) {
|
|
27
|
+
const trimmed = roleEntry.inbox.replace(/\/+$/, '');
|
|
28
|
+
const parts = trimmed.split('/');
|
|
29
|
+
if (parts[parts.length - 1] === 'inbox') {
|
|
30
|
+
return parts.slice(0, -1).join('/');
|
|
31
|
+
}
|
|
32
|
+
return trimmed;
|
|
33
|
+
}
|
|
34
|
+
return `roles/${roleSlug}`;
|
|
35
|
+
}
|
|
36
|
+
export async function checkRow3bPlaybook(opts) {
|
|
37
|
+
const { workspaceRoot, roleSlug, roleEntry, ssmContext } = opts;
|
|
38
|
+
const base = { id: '3b', name: 'playbook file' };
|
|
39
|
+
const ssmAvailable = ssmContext.triggers_allowlist !== 'unavailable';
|
|
40
|
+
const triggersAllowlist = ssmAvailable ? ssmContext.triggers_allowlist : [];
|
|
41
|
+
const isCadenceBearing = ssmAvailable && triggersAllowlist.includes(roleSlug);
|
|
42
|
+
// ── Check gh CLI + resolve GitHub repo ──────────────────────────────────
|
|
43
|
+
let ghAvailable = true;
|
|
44
|
+
let ghError = '';
|
|
45
|
+
try {
|
|
46
|
+
checkGhAvailable();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
ghAvailable = false;
|
|
50
|
+
ghError = err instanceof ToolingError ? err.message : String(err);
|
|
51
|
+
}
|
|
52
|
+
const repoRef = ghAvailable ? getWorkspaceGitHubRepo(workspaceRoot) : null;
|
|
53
|
+
if (!ghAvailable || !repoRef) {
|
|
54
|
+
const detail = !ghAvailable
|
|
55
|
+
? ghError
|
|
56
|
+
: 'Cannot determine GitHub repo from workspace git remote.origin.url.';
|
|
57
|
+
// If we cannot read the repo, we cannot check for playbook files.
|
|
58
|
+
// Without playbook files, we also cannot classify the role if SSM is unavailable.
|
|
59
|
+
// Either way, this is a tooling error for the gh CLI dependency.
|
|
60
|
+
return {
|
|
61
|
+
...base,
|
|
62
|
+
status: 'tooling_error',
|
|
63
|
+
detail,
|
|
64
|
+
fix_command: null,
|
|
65
|
+
fix_instruction: 'Install and authenticate gh CLI: brew install gh && gh auth login',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const roleDir = deriveRoleDir(roleEntry, roleSlug);
|
|
69
|
+
// ── Enumerate playbook files in the role dir ────────────────────────────
|
|
70
|
+
let playbookFiles = [];
|
|
71
|
+
let dirMissing = false;
|
|
72
|
+
let ghReadError = null;
|
|
73
|
+
try {
|
|
74
|
+
const dirFiles = listDirectoryFilenamesOnGitHub(repoRef, roleDir);
|
|
75
|
+
if (dirFiles === null) {
|
|
76
|
+
dirMissing = true;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
playbookFiles = dirFiles.filter((f) => /^playbook-.+\.md$/.test(f));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
ghReadError = err instanceof ToolingError ? err.message : String(err);
|
|
84
|
+
}
|
|
85
|
+
if (ghReadError) {
|
|
86
|
+
return {
|
|
87
|
+
...base,
|
|
88
|
+
status: 'tooling_error',
|
|
89
|
+
detail: ghReadError,
|
|
90
|
+
fix_command: null,
|
|
91
|
+
fix_instruction: 'gh CLI authentication or network issue. Run: gh auth login',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// ── Playbook present → PASS (regardless of cadence classification) ──────
|
|
95
|
+
if (playbookFiles.length > 0) {
|
|
96
|
+
return {
|
|
97
|
+
...base,
|
|
98
|
+
status: 'pass',
|
|
99
|
+
detail: `Found ${playbookFiles.length} playbook file(s) in ${roleDir}/: ${playbookFiles.join(', ')}`,
|
|
100
|
+
fix_command: null,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ── No playbook found — apply cadence classifier ───────────────────────
|
|
104
|
+
// Dir missing: treat as no playbook files found (PASS/FAIL/SKIP/INDETERMINATE
|
|
105
|
+
// follow the same classifier — a missing dir means no playbook exists there).
|
|
106
|
+
const noPlaybookDetail = dirMissing
|
|
107
|
+
? `Role directory '${roleDir}/' not found on GitHub origin/main — no playbook files can exist there.`
|
|
108
|
+
: `No playbook-*.md files found in ${roleDir}/ on GitHub origin/main.`;
|
|
109
|
+
// SSM unavailable + no playbook → INDETERMINATE
|
|
110
|
+
// Cannot determine if role is cadence-bearing — can't FAIL or SKIP honestly.
|
|
111
|
+
if (!ssmAvailable) {
|
|
112
|
+
return {
|
|
113
|
+
...base,
|
|
114
|
+
status: 'indeterminate',
|
|
115
|
+
detail: noPlaybookDetail + ' SSM triggers allowlist unreadable (Row 4c TOOLING-ERROR) — cannot classify role as cadence-bearing vs. dispatch-driven.',
|
|
116
|
+
fix_command: null,
|
|
117
|
+
fix_instruction: `Fix the Row 4c SSM read error first (AWS credentials/SSO), then re-run preflight. ` +
|
|
118
|
+
`Once SSM is readable, Row 3b can determine whether a playbook is required for role '${roleSlug}'.`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Cadence-bearing + no playbook → FAIL (real miss)
|
|
122
|
+
if (isCadenceBearing) {
|
|
123
|
+
return {
|
|
124
|
+
...base,
|
|
125
|
+
status: 'fail',
|
|
126
|
+
detail: noPlaybookDetail + ` Role '${roleSlug}' IS in the SSM triggers allowlist (/fazemos/.../triggers/allowlist) and will fire on cadence with no playbook to read.`,
|
|
127
|
+
fix_command: null,
|
|
128
|
+
fix_instruction: `Author at least one playbook file in ${roleDir}/ ` +
|
|
129
|
+
`(e.g. ${roleDir}/playbook-daily.md or ${roleDir}/playbook-task.md) in the workspace repo. ` +
|
|
130
|
+
`Role '${roleSlug}' is in the SSM triggers allowlist and will be invoked on cadence — ` +
|
|
131
|
+
`it needs a playbook to follow. See docs/guides/agent-provisioning-runbook.md §3.`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Dispatch-driven + no playbook → SKIP (by design, not a defect)
|
|
135
|
+
return {
|
|
136
|
+
...base,
|
|
137
|
+
status: 'skip',
|
|
138
|
+
detail: `No playbook-*.md files found — role '${roleSlug}' is NOT in the SSM triggers allowlist; playbook not required by design.`,
|
|
139
|
+
fix_command: null,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=row3_playbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row3_playbook.js","sourceRoot":"","sources":["../../src/preflight/row3_playbook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3c — .fazemos/roles.json entry presence.
|
|
3
|
+
*
|
|
4
|
+
* Local check: does the workspace registry declare a filler for the role?
|
|
5
|
+
* A missing entry means `fazemos roles sync` will have nothing to sync.
|
|
6
|
+
*/
|
|
7
|
+
import type { RolesRegistry } from '../dispatch.js';
|
|
8
|
+
import type { PreflightRow } from './schema.js';
|
|
9
|
+
export declare function checkRow3cRolesJson(opts: {
|
|
10
|
+
roleSlug: string;
|
|
11
|
+
registry: RolesRegistry | null;
|
|
12
|
+
}): PreflightRow;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Row 3c — .fazemos/roles.json entry presence.
|
|
3
|
+
*
|
|
4
|
+
* Local check: does the workspace registry declare a filler for the role?
|
|
5
|
+
* A missing entry means `fazemos roles sync` will have nothing to sync.
|
|
6
|
+
*/
|
|
7
|
+
export function checkRow3cRolesJson(opts) {
|
|
8
|
+
const { roleSlug, registry } = opts;
|
|
9
|
+
const base = { id: '3c', name: 'roles.json entry' };
|
|
10
|
+
if (!registry || !registry.roles[roleSlug]) {
|
|
11
|
+
return {
|
|
12
|
+
...base,
|
|
13
|
+
status: 'fail',
|
|
14
|
+
detail: `Role '${roleSlug}' not found in .fazemos/roles.json (or no registry found).`,
|
|
15
|
+
fix_command: null,
|
|
16
|
+
fix_instruction: `Add a filler entry for '${roleSlug}' in the workspace .fazemos/roles.json, ` +
|
|
17
|
+
`then run: fazemos roles sync`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (!registry.roles[roleSlug].filler?.identity) {
|
|
21
|
+
return {
|
|
22
|
+
...base,
|
|
23
|
+
status: 'fail',
|
|
24
|
+
detail: `Role '${roleSlug}' in .fazemos/roles.json has no filler.identity.`,
|
|
25
|
+
fix_command: null,
|
|
26
|
+
fix_instruction: `Set filler.identity for '${roleSlug}' in .fazemos/roles.json (the agent's display name), ` +
|
|
27
|
+
`then run: fazemos roles sync`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const entry = registry.roles[roleSlug];
|
|
31
|
+
return {
|
|
32
|
+
...base,
|
|
33
|
+
status: 'pass',
|
|
34
|
+
detail: `${roleSlug}: filler.type=${entry.filler.type}, filler.identity=${entry.filler.identity}, scope=${entry.scope}`,
|
|
35
|
+
fix_command: null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=row3_rolesJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row3_rolesJson.js","sourceRoot":"","sources":["../../src/preflight/row3_rolesJson.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,UAAU,mBAAmB,CAAC,IAGnC;IACC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAW,CAAC;IAE7D,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS,QAAQ,4DAA4D;YACrF,WAAW,EAAE,IAAI;YACjB,eAAe,EACb,2BAA2B,QAAQ,0CAA0C;gBAC7E,8BAA8B;SACjC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC/C,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS,QAAQ,kDAAkD;YAC3E,WAAW,EAAE,IAAI;YACjB,eAAe,EACb,4BAA4B,QAAQ,uDAAuD;gBAC3F,8BAA8B;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,QAAQ,iBAAiB,KAAK,CAAC,MAAM,CAAC,IAAI,qBAAqB,KAAK,CAAC,MAAM,CAAC,QAAQ,WAAW,KAAK,CAAC,KAAK,EAAE;QACvH,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F53 Rows 3a/3b/3c — Workspace repo file checks.
|
|
3
|
+
*
|
|
4
|
+
* Checks performed via `gh api` against origin/main (D3: remote, not local copy).
|
|
5
|
+
* 3a — persona file exists (path from role.persona in roles.json)
|
|
6
|
+
* 3b — playbook file exists (derived from role.inbox path convention)
|
|
7
|
+
* 3c — .fazemos/roles.json has the role entry with a filler (local check)
|
|
8
|
+
*
|
|
9
|
+
* Row 3 rows do NOT run if `gh` is unavailable (whole group becomes tooling_error).
|
|
10
|
+
*/
|
|
11
|
+
import type { RoleEntry, RolesRegistry } from '../dispatch.js';
|
|
12
|
+
import type { PreflightRow } from './schema.js';
|
|
13
|
+
/**
|
|
14
|
+
* Run rows 3a, 3b, 3c for a given workspace/role.
|
|
15
|
+
*/
|
|
16
|
+
export declare function checkRow3Workspace(opts: {
|
|
17
|
+
workspaceRoot: string;
|
|
18
|
+
roleSlug: string;
|
|
19
|
+
/** Agent name (filler.identity), used to resolve the runtime persona path docs/agents/<name>.md */
|
|
20
|
+
agentName: string;
|
|
21
|
+
/** Role entry from the local registry (may be undefined if roles.json doesn't have it). */
|
|
22
|
+
roleEntry: RoleEntry | undefined;
|
|
23
|
+
registry: RolesRegistry | null;
|
|
24
|
+
}): Promise<PreflightRow[]>;
|