{"hash":"bc8da9326284ed5d84d6fa6bdde3a147207ee3da773c2adebb990b3d9f1ff195","short_code":"2026-05-20T16:15:21+00:00","title":"PERMIT — LEADER_CAPABILITY_PACKAGE for espadvisorygroup (rename_team + announce_to_team)","kind":"capability_package","principal":"doctortheisen","scope_tag":"espadvisorygroup_leader_capabilities","tier":"architect","issued_at":"2026-05-20T16:15:21+00:00","expires_at":"","surface":"espadvisorygroup.com","chain_hash":"72b14546b54338f6196681a564809851aefb770628bb5e92fdf60fde4bae6048","conditions":[["VERSION","v1"],["CAPABILITIES",[[["NAME","rename_team"],["UI_HTML_FRAGMENT","<div class=\"composer cap-pkg-composer\" id=\"cap-rename-team\" data-capability=\"rename_team\">\n  <h3>Rename team</h3>\n  <p class=\"current\">Current name: <span class=\"current-name-slot\">—</span></p>\n  <label>proposed new name</label>\n  <input type=\"text\" maxlength=\"120\" class=\"new-name-input\" placeholder=\"e.g. Pioneers\">\n  <button class=\"compose-btn\" type=\"button\">compose rename request</button>\n  <div class=\"preview\"></div>\n</div>\n"],["UI_JS_FRAGMENT","(function(){\n  const root = document.getElementById('cap-rename-team');\n  if(!root) return;\n  const v = window._viewer || {};\n  const team = window._team || {};\n  const currentName = team.name;\n  const slot = root.querySelector('.current-name-slot');\n  if(Array.isArray(currentName) && currentName.length === 0){\n    slot.innerHTML = '<span class=\"team__hole\">unfilled</span>';\n  } else {\n    slot.textContent = currentName || '—';\n  }\n  root.querySelector('.compose-btn').addEventListener('click', () => {\n    const input = root.querySelector('.new-name-input');\n    const newVal = input.value.trim();\n    if(!newVal){ alert('enter a proposed name'); return; }\n    const cmd = 'python3 ~/.ko/services/espadvisorygroup/architect_execute.py rename_team --actor ' + v.principal + ' --new-name ' + JSON.stringify(newVal);\n    const payload = {\n      type:'CAPABILITY_REQUEST',\n      capability:'rename_team',\n      scope_tag:'espadvisorygroup',\n      field:'NAME',\n      new_value:newVal,\n      requested_by:{principal:v.principal, display_name:v.displayName, tier:v.tier, permit_short_code:v.permit},\n      composed_at: new Date().toISOString(),\n      architect_command: cmd\n    };\n    const previewText = JSON.stringify(payload, null, 2);\n    const mailto = window._buildMailto('Rename request — ' + newVal, previewText);\n    const preview = root.querySelector('.preview');\n    preview.innerHTML = '<span class=\"preview-label\">request preview</span>\\n' + window._esc(previewText) +\n      '<div style=\"margin-top:14px\"><a class=\"mailto-btn\" href=\"' + mailto + '\">✉ send to architect</a></div>';\n    preview.classList.add('show');\n  });\n})();\n"],["SERVER_ACTION","architect_execute.py rename_team"],["DOC","Compose a request to rename the team's display name. The leader composes; the architect executes via YubiKey-attested ceremony. Latest-by-DESC on the NAME typed_hole wins."],["PERMITTED_RUNGS",["project_lead","architect"]],["INPUT_SCHEMA",[["new_name","text","Proposed team name (display)",120]]],["ANNOUNCEMENT_TEMPLATE","<actor_display> as team <actor_tier> renamed the group to \"<new_name>\"."]],[["NAME","announce_to_team"],["UI_HTML_FRAGMENT","<div class=\"composer cap-pkg-composer\" id=\"cap-announce-team\" data-capability=\"announce_to_team\">\n  <h3>Announce to team</h3>\n  <label>subject</label>\n  <input type=\"text\" maxlength=\"160\" class=\"ann-subject-input\" placeholder=\"brief subject line\">\n  <label>body</label>\n  <textarea class=\"ann-body-input\" placeholder=\"message body — what you would like the team to know\"></textarea>\n  <p class=\"recipients\">recipients: <em class=\"recipients-slot\">(loading)</em></p>\n  <button class=\"compose-btn\" type=\"button\">compose announcement request</button>\n  <div class=\"preview\"></div>\n</div>\n"],["UI_JS_FRAGMENT","(function(){\n  const root = document.getElementById('cap-announce-team');\n  if(!root) return;\n  const v = window._viewer || {};\n  const team = window._team || {};\n  const members = team.members || [];\n  const slot = root.querySelector('.recipients-slot');\n  if(members.length === 0){\n    slot.textContent = '(team members not loaded)';\n  } else {\n    const tags = members.map(m => {\n      const g = (k) => (m.find && m.find(x => Array.isArray(x) && x[0]===k) || [])[1] || '';\n      return g('display_name') || g('principal');\n    });\n    slot.textContent = '(' + members.length + ') ' + tags.join(', ');\n  }\n  root.querySelector('.compose-btn').addEventListener('click', () => {\n    const subj = root.querySelector('.ann-subject-input').value.trim();\n    const body = root.querySelector('.ann-body-input').value.trim();\n    if(!subj || !body){ alert('subject and body both required'); return; }\n    const recips = members.map(m => {\n      const g = (k) => (m.find && m.find(x => Array.isArray(x) && x[0]===k) || [])[1] || '';\n      return {principal:g('principal'), display_name:g('display_name'), rung:g('rung')};\n    });\n    const cmd = 'python3 ~/.ko/services/espadvisorygroup/architect_execute.py announce_to_team --actor ' + v.principal +\n                ' --subject ' + JSON.stringify(subj) + ' --body ' + JSON.stringify(body);\n    const payload = {\n      type:'CAPABILITY_REQUEST',\n      capability:'announce_to_team',\n      scope_tag:'espadvisorygroup',\n      subject: subj,\n      body: body,\n      recipients: recips,\n      requested_by:{principal:v.principal, display_name:v.displayName, tier:v.tier, permit_short_code:v.permit},\n      composed_at: new Date().toISOString(),\n      architect_command: cmd\n    };\n    const previewText = JSON.stringify(payload, null, 2);\n    const mailto = window._buildMailto('Announcement request — ' + subj, previewText);\n    const preview = root.querySelector('.preview');\n    preview.innerHTML = '<span class=\"preview-label\">request preview</span>\\n' + window._esc(previewText) +\n      '<div style=\"margin-top:14px\"><a class=\"mailto-btn\" href=\"' + mailto + '\">✉ send to architect</a></div>';\n    preview.classList.add('show');\n  });\n})();\n"],["SERVER_ACTION","architect_execute.py announce_to_team"],["DOC","Compose an announcement to the team. INSERTs to v_announcements + rebuilds /pages/announcements_feed.json + dispatches email per current mode toggles."],["PERMITTED_RUNGS",["project_lead","architect"]],["INPUT_SCHEMA",[["subject","text","Subject line",160],["body","textarea","Message body",4000]]],["ANNOUNCEMENT_TEMPLATE",null]]]],["MODE_DEPENDENCY_SCOPE","espadvisorygroup"],["DESCRIPTION","Capability package for project_lead/architect rungs at espadvisorygroup. Each entry in CAPABILITIES is a List of [NAME, UI_HTML_FRAGMENT, UI_JS_FRAGMENT, SERVER_ACTION, DOC, PERMITTED_RUNGS, INPUT_SCHEMA, ANNOUNCEMENT_TEMPLATE]. The SPA fetches this package after token validation, filters entries by PERMITTED_RUNGS intersection with viewer rung, and inlines UI_HTML_FRAGMENT + evaluates UI_JS_FRAGMENT. Without this permit, the leader area is empty in the SPA — the toggle is the permit's presence at view time."]],"hash_short":"bc8da9326284","register_source":"espadvisorygroup_sister","register_genesis":"f3363f614347023565e0916ed13eff0c6ca42d830b60f2a56c56612975b2f91c","federation_note":"v_permit row from sister register; mint event sha256 preserved in main FIELD.db; bundler declaration at 110b3009"}