create-agdf 0.8.5 → 0.8.7

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.
Files changed (23) hide show
  1. package/bin/create-agdf.js +141 -10
  2. package/generated/.agdf/control/templates/artefacts/VERIFIED_CHANGE.md +10 -0
  3. package/generated/.github/skills/agdf-brownfield-analysis/SKILL.md +3 -3
  4. package/generated/.github/skills/agdf-gate-check/SKILL.md +31 -7
  5. package/generated/.github/skills/agdf-interaction-locales.json +98 -6
  6. package/generated/.github/skills/agdf-release-or/SKILL.md +4 -3
  7. package/generated/.github/skills/agdf-runtime-contract.md +104 -8
  8. package/generated/.opencode/agdf-interaction-locales.json +98 -6
  9. package/generated/.opencode/agdf-runtime-contract.md +104 -8
  10. package/generated/.opencode/skills/agdf-brownfield-analysis/SKILL.md +3 -3
  11. package/generated/.opencode/skills/agdf-gate-check/SKILL.md +31 -7
  12. package/generated/.opencode/skills/agdf-release-or/SKILL.md +4 -3
  13. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  14. package/generated/plugins/agdf/control/templates/artefacts/VERIFIED_CHANGE.md +10 -0
  15. package/generated/plugins/agdf/meta/agdf-interaction-locales.json +98 -6
  16. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +9 -5
  17. package/generated/plugins/agdf/meta/agdf-runtime-contract.md +104 -8
  18. package/generated/plugins/agdf/skills/brownfield-analysis/SKILL.md +3 -3
  19. package/generated/plugins/agdf/skills/gate-check/SKILL.md +31 -7
  20. package/generated/plugins/agdf/skills/release-or/SKILL.md +4 -3
  21. package/lib/control-state/run-state-parser.js +30 -3
  22. package/lib/interaction-presentation.js +88 -2
  23. package/package.json +1 -1
@@ -2,6 +2,7 @@ const REQUIRED_GATES = ["UR", "PRD", "SD", "TP", "QA", "UAT"];
2
2
  const ARTEFACT_ORDER = ["UR", "PRD", "SD", "TP"];
3
3
  const OUTCOMES = new Set(["approve", "revise", "decline", "cancel", "no_response", "timeout", "empty", "invalid", "stale"]);
4
4
  const ATTEMPT_OUTCOMES = new Set(["presented", "unavailable_before_invocation", "attempted_not_applied", "unsafe_to_wait"]);
5
+ const APPROVAL_VALUE_TRANSPORTS = new Set(["exact_option_value", "separate_label_and_value", "decorated_label_only", "unknown"]);
5
6
  const APPROVAL_SEQUENCE = Object.freeze(["run_status_card", "gate_transition_card", "approval_interaction"]);
6
7
  const QUALITY_STATUS_RANK = { pass: 0, warn: 1, revise: 2, block: 3 };
7
8
  const QUALITY_DIMENSIONS = Object.freeze([
@@ -63,7 +64,7 @@ export function validateLocaleRegistry(registry) {
63
64
  for (const [key, value] of visibleStrings(pack)) {
64
65
  if (!value.trim()) errors.push(`empty_copy:${locale}:${key}`);
65
66
  const budget = key.startsWith("gateTitles.") ? budgets.title
66
- : key.includes("Description") || key.includes("fallbackReasons") || key.startsWith("primary.actions.") || key.startsWith("primary.afterApproval.") || key === "primary.quality"
67
+ : key.includes("Description") || key.includes("fallbackReasons") || key.startsWith("primary.actions.") || key.startsWith("primary.afterApproval.") || key.startsWith("primary.narration.") || key.startsWith("gateRationale.") || key.startsWith("interaction.why.") || key === "primary.quality"
67
68
  ? budgets.description
68
69
  : budgets.label;
69
70
  if (Number.isInteger(budget) && value.length > budget) errors.push(`length_budget:${locale}:${key}`);
@@ -96,6 +97,10 @@ export function gateTitle(registry, requestedLocale, gate) {
96
97
  return localePack(registry, requestedLocale).gateTitles[gate] || String(gate || "");
97
98
  }
98
99
 
100
+ export function gateRationale(registry, requestedLocale, gate) {
101
+ return localePack(registry, requestedLocale).gateRationale?.[gate] || String(gate || "");
102
+ }
103
+
99
104
  function stripMarkdown(value) {
100
105
  return String(value ?? "")
101
106
  .replace(/^#+\s*/, "")
@@ -180,10 +185,31 @@ export function reconcileRunScope({ requestText = "", scopeKey = "", runs = [] }
180
185
  return Object.freeze({ outcome: matches[0].lifecycle === "active" ? "active_match" : "completed_match", matches, reason: "exact_match" });
181
186
  }
182
187
 
183
- export function executeNativeApprovalAttempt({ ready = false, orientationSnapshot, invokeNative, fallback } = {}) {
188
+ export function evaluateNativeApprovalCapability({ staticCapability, runtimeCapability } = {}) {
189
+ const staticValue = staticCapability?.approvalValueTransport;
190
+ const runtimeValue = runtimeCapability?.approvalValueTransport;
191
+ if (runtimeCapability && staticCapability && (runtimeValue !== staticValue || runtimeCapability.waitSafety !== staticCapability.waitSafety)) {
192
+ return Object.freeze({ eligible: false, native_attempt_required: false, preflight_outcome: "unavailable_before_invocation", reason: "capability_conflict", evidence_source: "runtime" });
193
+ }
194
+ const capability = runtimeCapability ?? staticCapability;
195
+ const evidenceSource = runtimeCapability ? "runtime" : staticCapability ? "static" : "none";
196
+ if (!capability || !APPROVAL_VALUE_TRANSPORTS.has(capability.approvalValueTransport)) return Object.freeze({ eligible: false, native_attempt_required: false, preflight_outcome: "unavailable_before_invocation", reason: "capability_missing", evidence_source: evidenceSource });
197
+ if (capability.waitSafety === "unsafe") return Object.freeze({ eligible: false, native_attempt_required: false, preflight_outcome: "unsafe_to_wait", reason: "unsafe_wait", evidence_source: evidenceSource });
198
+ if (capability.waitSafety !== "deliberate_no_auto_resolution") return Object.freeze({ eligible: false, native_attempt_required: false, preflight_outcome: "unavailable_before_invocation", reason: "capability_missing", evidence_source: evidenceSource });
199
+ if (!new Set(["exact_option_value", "separate_label_and_value"]).has(capability.approvalValueTransport)) return Object.freeze({ eligible: false, native_attempt_required: false, preflight_outcome: "unavailable_before_invocation", reason: capability.approvalValueTransport === "decorated_label_only" ? "decorated_only" : "capability_missing", evidence_source: evidenceSource });
200
+ return Object.freeze({ eligible: true, native_attempt_required: true, preflight_outcome: "eligible_for_invocation", reason: capability.approvalValueTransport === "exact_option_value" ? "exact_transport" : "separate_value_transport", evidence_source: evidenceSource });
201
+ }
202
+
203
+ export function executeNativeApprovalAttempt({ ready = false, orientationSnapshot, capabilityPreflight, invokeNative, fallback } = {}) {
184
204
  if (!ready) return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "gate_not_ready", authorizes: false });
185
205
  const preflight = validateApprovalOrientationSnapshot(orientationSnapshot);
186
206
  if (!preflight.valid) return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "orientation_preflight_failed", authorizes: false });
207
+ if (!capabilityPreflight?.eligible) {
208
+ const outcome = capabilityPreflight?.preflight_outcome === "unsafe_to_wait" ? "unsafe_to_wait" : "unavailable_before_invocation";
209
+ const reason = capabilityPreflight?.reason || "capability_missing";
210
+ if (typeof fallback === "function") fallback({ outcome, reason });
211
+ return Object.freeze({ attempted: false, outcome, reason, authorizes: false });
212
+ }
187
213
  if (typeof invokeNative !== "function") return Object.freeze({ attempted: false, outcome: "unavailable_before_invocation", reason: "adapter_unavailable", authorizes: false });
188
214
  let adapterResult;
189
215
  try {
@@ -395,6 +421,66 @@ export function buildQualityReadiness({
395
421
  });
396
422
  }
397
423
 
424
+ export function collapseInternalState(
425
+ { modeSliceDecision = "", verifiedChangeState = "", contextGraphRequiredAction = "", multiScopeState = "" } = {},
426
+ registry,
427
+ requestedLocale,
428
+ ) {
429
+ const pack = localePack(registry, requestedLocale);
430
+ const labels = pack.internalStateLabels || {};
431
+ const result = {};
432
+ if (modeSliceDecision === "verified_change") {
433
+ if (verifiedChangeState === "escalated") {
434
+ result.verified_change = labels.verifiedChangeEscalated || "Escalated to structured delivery";
435
+ } else if (["missing", "draft", "invalid", "eligible", "executed"].includes(verifiedChangeState)) {
436
+ result.verified_change = labels.verifiedChange || "Compact change under review";
437
+ }
438
+ }
439
+ if (contextGraphRequiredAction === "open_gap") {
440
+ result.context_graph = labels.contextGraphOpenGap || "Graph gap open";
441
+ } else if (["link", "update", "create", "resolve_drift"].includes(contextGraphRequiredAction)) {
442
+ result.context_graph = labels.contextGraphMaintained || "Project memory maintained";
443
+ }
444
+ if (multiScopeState === "blocked") {
445
+ result.multi_scope = labels.multiScopeBlocked || "Ambiguous scope, clarification needed";
446
+ }
447
+ return result;
448
+ }
449
+
450
+ export function buildBreadcrumb(breadcrumb, registry, requestedLocale) {
451
+ if (!Array.isArray(breadcrumb)) return "";
452
+ const pack = localePack(registry, requestedLocale);
453
+ const cardLabels = pack.statusCard || {};
454
+ const titles = pack.gateTitles || {};
455
+ const sep = cardLabels.breadcrumbSeparator || " \u00b7 ";
456
+ const symbols = {
457
+ fulfilled: cardLabels.breadcrumbFulfilled || "\u2713",
458
+ current: cardLabels.breadcrumbCurrent || "\u25cf",
459
+ open: cardLabels.breadcrumbOpen || "\u25cb",
460
+ };
461
+ return breadcrumb
462
+ .map((entry) => {
463
+ const title = titles[entry.gate] || entry.gate;
464
+ const symbol = symbols[entry.status] || symbols.open;
465
+ return `${title} ${symbol}`;
466
+ })
467
+ .join(sep);
468
+ }
469
+
470
+ export function buildTransitionNarration(gate, registry, requestedLocale) {
471
+ const pack = localePack(registry, requestedLocale);
472
+ const narration = pack.primary?.narration || {};
473
+ const gateTitles = pack.gateTitles || {};
474
+ const gateTitle = gateTitles[gate] || gate;
475
+ const gateConfig = narration.gates?.[gate] || {};
476
+ const agentNext = gateConfig.agentNext || "";
477
+ const userAction = gateConfig.userAction || narration.noAction || "no user action required now";
478
+ if (!agentNext) return "";
479
+ const gateSatisfiedTemplate = narration.gateSatisfied || "{gate} approved";
480
+ const gateSatisfied = gateSatisfiedTemplate.replace("{gate}", gateTitle);
481
+ return `${gateSatisfied} \u2192 ${agentNext} \u2192 ${userAction}`;
482
+ }
483
+
398
484
  export const interactionPresentationConstants = Object.freeze({
399
485
  artefactOrder: Object.freeze([...ARTEFACT_ORDER]),
400
486
  outcomes: Object.freeze([...OUTCOMES]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agdf",
3
- "version": "0.8.5",
3
+ "version": "0.8.7",
4
4
  "description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
5
5
  "type": "module",
6
6
  "files": [