refactor: update agent sync behavior, improve freshness detection patterns, and add diagnostic troubleshooting script

This commit is contained in:
2026-05-05 07:43:45 -06:00
parent f685ac37dd
commit 63e784cc97
11 changed files with 168 additions and 61 deletions

View File

@@ -13,11 +13,44 @@ Use this when the user asks for:
Run sync: Run sync:
!`if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi` !`start=$(date +%s); if [ -n "$AIW_MATTERMOST_SYNC_CMD" ]; then bash -lc "$AIW_MATTERMOST_SYNC_CMD"; elif [ -n "$FIDELITY_MATTERMOST_SYNC_CMD" ]; then bash -lc "$FIDELITY_MATTERMOST_SYNC_CMD"; elif [ -f scripts/mattermost/sync.sh ]; then bash scripts/mattermost/sync.sh; else echo "No Mattermost sync command is configured."; fi; status=$?; end=$(date +%s); echo "__MATTERMOST_SYNC_SECONDS__=$((end - start))"; exit "$status"`
Read refreshed Mattermost context: Read a focused slice of refreshed Mattermost context:
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No Mattermost context available after sync."; fi` !`python3 - <<'PY'
import json
from pathlib import Path
paths = [
Path("ai/inbox/mattermost-latest.md"),
Path("scripts/mattermost/generated/mattermost_context.jsonl"),
]
source = next((path for path in paths if path.is_file() and path.stat().st_size > 0), None)
if not source:
print("No Mattermost context available after sync.")
raise SystemExit(0)
records = []
for line in source.read_text().splitlines():
line = line.strip()
if not line:
continue
try:
records.append(json.loads(line))
except json.JSONDecodeError:
continue
manager_names = {"jeff", "jeff.dewitte"}
manager_records = [
record for record in records
if str(record.get("username", "")).lower() in manager_names
]
focused = manager_records[-10:] if manager_records else records[-15:]
for record in focused:
print(json.dumps(record, ensure_ascii=False))
PY`
User request: User request:
@@ -26,15 +59,18 @@ $ARGUMENTS
Instructions: Instructions:
- Do not answer from old conversation memory. - Do not answer from old conversation memory.
- Use only the refreshed Mattermost output above. - Use only the focused refreshed Mattermost output above.
- If the user asks for the current manager/stakeholder, filter messages by the profile mapping when visible; for the Fidelity profile, also match `jeff` and `jeff.dewitte`. - If the user asks for the current manager/stakeholder, filter messages by the profile mapping when visible; for the Fidelity profile, also match `jeff` and `jeff.dewitte`.
- If multiple messages match, return the newest matching message first. - If multiple messages match, return the newest matching message first.
- Include timestamp, channel, sender, and concise summary. - Include timestamp, channel, sender, and concise summary.
- If the message changes project context, update the appropriate workspace memory after answering, writing to `project-knowledge/` first. - Do not edit workspace memory in this command.
- If the message appears to change project context, report it as a memory update candidate and name the likely target file.
- Use `/communication-sync` or an explicit user request to promote the fact after the latest-message answer is complete.
- If sync fails or no refreshed context is available, say that directly and do not infer from stale context. - If sync fails or no refreshed context is available, say that directly and do not infer from stale context.
- If a write or patch attempt fails in this flow, stop immediately and return the latest-message answer plus the failed target; do not retry.
Return: Return:
1. Latest matching message 1. Latest matching message
2. Why it matters 2. Why it matters
3. Any memory update made 3. Memory update candidate, if any

View File

@@ -4,37 +4,63 @@ description: Draft a standup from the latest Fidelity workspace context
Generate a standup update using the latest workspace state. Generate a standup update using the latest workspace state.
First, refresh previous-workday Mattermost context before drafting: Temporal context. Read this before interpreting `today`, `yesterday`, `previous workday`, or `last workday`:
!`python3 - <<'PY'
from datetime import datetime, timedelta
now = datetime.now().astimezone()
today = now.date()
calendar_yesterday = today - timedelta(days=1)
default_previous_workday = calendar_yesterday
while default_previous_workday.weekday() >= 5:
default_previous_workday -= timedelta(days=1)
print("## Temporal Context")
print(f"current_time: {now.isoformat()}")
print(f"today: {today.isoformat()} ({today.strftime('%A')})")
print(f"calendar_yesterday: {calendar_yesterday.isoformat()} ({calendar_yesterday.strftime('%A')})")
print(f"default_previous_workday: {default_previous_workday.isoformat()} ({default_previous_workday.strftime('%A')})")
print("standup_rule: Generate the report for today. The previous-work section must describe work from calendar_yesterday when it was a workday; otherwise use the latest prior day with Mattermost activity.")
PY`
First, refresh Mattermost before drafting. This is mandatory for start-of-day standups and must not be skipped:
!`python3 - <<'PY' !`python3 - <<'PY'
import os import os
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from datetime import date from datetime import datetime
cmd = os.environ.get("AIW_MATTERMOST_SYNC_CMD") or os.environ.get("FIDELITY_MATTERMOST_SYNC_CMD") cmd = os.environ.get("AIW_MATTERMOST_SYNC_CMD") or os.environ.get("FIDELITY_MATTERMOST_SYNC_CMD")
today = date.today().isoformat() today = datetime.now().astimezone().date().isoformat()
commands = []
if Path("scripts/mattermost/sync.sh").is_file(): if Path("scripts/mattermost/sync.sh").is_file():
result = subprocess.run( commands.append(("latest", ["bash", "scripts/mattermost/sync.sh"]))
["bash", "scripts/mattermost/sync.sh", "--previous-workday", "--today", today], commands.append(("previous-workday", ["bash", "scripts/mattermost/sync.sh", "--previous-workday", "--today", today]))
capture_output=True,
text=True,
)
elif cmd: elif cmd:
result = subprocess.run(["bash", "-lc", cmd], capture_output=True, text=True) commands.append(("configured", ["bash", "-lc", cmd]))
else:
if not commands:
print("No Mattermost sync command configured.") print("No Mattermost sync command configured.")
raise SystemExit(0) raise SystemExit(0)
failed = False
for label, command in commands:
result = subprocess.run(command, capture_output=True, text=True)
print(f"__MATTERMOST_SYNC_LABEL__={label}")
print(f"__MATTERMOST_SYNC_RETURN_CODE__={result.returncode}")
if result.returncode != 0: if result.returncode != 0:
failed = True
print("__MATTERMOST_SYNC_FAILED__") print("__MATTERMOST_SYNC_FAILED__")
if result.stdout:
print(result.stdout.strip())
if result.stderr:
print(result.stderr.strip())
else:
if result.stdout.strip(): if result.stdout.strip():
print(result.stdout.strip()) print(result.stdout.strip())
if result.stderr.strip():
print(result.stderr.strip())
if failed:
raise SystemExit(0)
PY` PY`
Read: Read:
@@ -51,6 +77,10 @@ Today's log, if present:
!`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi` !`if [ -f project-knowledge/06-daily/$(date +%F).md ]; then cat project-knowledge/06-daily/$(date +%F).md; else echo "No daily note exists for today yet."; fi`
Latest refreshed Mattermost context, if present:
!`if [ -s ai/inbox/mattermost-latest.md ]; then cat ai/inbox/mattermost-latest.md; elif [ -s scripts/mattermost/generated/mattermost_context.jsonl ]; then cat scripts/mattermost/generated/mattermost_context.jsonl; else echo "No refreshed Mattermost context available."; fi`
Detailed active work item files, if available: Detailed active work item files, if available:
!`python3 - <<'PY' !`python3 - <<'PY'
@@ -79,6 +109,7 @@ PY`
Before drafting: Before drafting:
- use `status-reporting` when available - use `status-reporting` when available
- Mattermost refresh is mandatory for standup; do not draft from stale workspace memory if the refresh did not run
- update workspace memory if the refreshed context introduced clear high-confidence project facts - update workspace memory if the refreshed context introduced clear high-confidence project facts
- prefer existing memory when the latest context is ambiguous - prefer existing memory when the latest context is ambiguous
- treat the previous workday Mattermost context as the source for the `Yesterday` section, even when the previous calendar day was a weekend, holiday, or OOO day - treat the previous workday Mattermost context as the source for the `Yesterday` section, even when the previous calendar day was a weekend, holiday, or OOO day

View File

@@ -26,6 +26,7 @@ Behavior rules:
- Daily notes should include `focus`, `work-items`, and `blockers` when those values are clear. - Daily notes should include `focus`, `work-items`, and `blockers` when those values are clear.
- Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history. - Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history.
- If the prompt asks for the latest Mattermost message, the last message from Jeff/current manager, or what someone just said, force a Mattermost refresh before answering and do not rely on stale inbox context. - If the prompt asks for the latest Mattermost message, the last message from Jeff/current manager, or what someone just said, force a Mattermost refresh before answering and do not rely on stale inbox context.
- Treat latest-message prompts as read-first: answer from refreshed evidence and report memory update candidates instead of editing canonical memory by default.
- For learning-style questions, answer from known context and verified facts only; explicitly label unknowns, assumptions, and inferences. - For learning-style questions, answer from known context and verified facts only; explicitly label unknowns, assumptions, and inferences.
- For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status. - For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status.
- If the user asks what to clarify, ask 3 to 5 high-leverage questions that would help a senior iOS engineer ramp into the project; include why each question matters. - If the user asks what to clarify, ask 3 to 5 high-leverage questions that would help a senior iOS engineer ramp into the project; include why each question matters.
@@ -56,6 +57,7 @@ Behavior rules:
- Do not wait for a dedicated sync command if the correct memory update is already obvious. - Do not wait for a dedicated sync command if the correct memory update is already obvious.
- For analysis, drafting, review, or translation prompts, answer first and persist second unless saving the fact is required to produce the answer safely. - For analysis, drafting, review, or translation prompts, answer first and persist second unless saving the fact is required to produce the answer safely.
- Avoid creating brand-new canonical notes in the middle of a response unless the user explicitly asked for persistence or the new note is the smallest correct update. - Avoid creating brand-new canonical notes in the middle of a response unless the user explicitly asked for persistence or the new note is the smallest correct update.
- If a non-essential memory patch fails verification, stop retrying and return the answer plus the intended target file.
- Do not leave behavior-only corrections only in daily logs. If a correction should affect future output, update the tool or instruction that produces that output. - Do not leave behavior-only corrections only in daily logs. If a correction should affect future output, update the tool or instruction that produces that output.
- If the memory interface or Obsidian adapter fails, continue with direct Markdown operations when safe and do not promote the failure as project memory. - If the memory interface or Obsidian adapter fails, continue with direct Markdown operations when safe and do not promote the failure as project memory.
- Do not over-promote uncertain information. Keep uncertain items in the daily log. - Do not over-promote uncertain information. Keep uncertain items in the daily log.

View File

@@ -13,6 +13,12 @@ function nowIso() {
return new Date().toISOString() return new Date().toISOString()
} }
function envFlag(name, defaultValue = false) {
const value = process.env[name]
if (value === undefined) return defaultValue
return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase())
}
async function resolveSyncCommand(directory) { async function resolveSyncCommand(directory) {
const configured = const configured =
process.env.AIW_MATTERMOST_SYNC_CMD?.trim() || process.env.AIW_MATTERMOST_SYNC_CMD?.trim() ||
@@ -66,30 +72,16 @@ function requiresFreshMattermost(promptText) {
.replace(/[\u0300-\u036f]/g, "") .replace(/[\u0300-\u036f]/g, "")
.toLowerCase() .toLowerCase()
const freshnessTerms = [ const freshnessPatterns = [
"ultimo", /\bultimo(?:s|a|as)?\s+(?:mensaje|mensajes|respuesta|respuestas|update|updates)\b/,
"ultimos", /\bmensaje(?:s)?\s+(?:mas\s+)?reciente(?:s)?\b/,
"ultima", /\bque\s+(?:dijo|menciono|respondio|contesto)\b/,
"ultimas", /\b(?:dijo|menciono|respondio|contesto)\s+(?:jeff|manager|supervisor)\b/,
"latest", /\b(?:latest|last|recent)\s+(?:message|messages|reply|replies|update|updates)\b/,
"last", /\bwhat\s+did\s+.+\s+(?:say|mention|reply)\b/,
"reciente", /\b(?:said|mentioned|replied)\s+(?:jeff|manager|supervisor)\b/,
"recent", /\b(?:sync|refresh|sincroniza|actualiza)\s+(?:mattermost|mensajes|messages|inbox)\b/,
"nuevo", /\b(?:revisa|check|look\s+at)\s+(?:mattermost|mensajes|messages|inbox)\b/,
"new",
"actualiza",
"sync",
"sincroniza",
"revisa",
"dijo",
"menciono",
"respondio",
"contesto",
"check",
"look at",
"said",
"mentioned",
"replied",
] ]
const mattermostTerms = [ const mattermostTerms = [
@@ -123,10 +115,8 @@ function requiresFreshMattermost(promptText) {
...configuredTerms, ...configuredTerms,
] ]
return ( return freshnessPatterns.some((pattern) => pattern.test(text)) &&
freshnessTerms.some((term) => text.includes(term)) &&
sourceTerms.some((term) => text.includes(term)) sourceTerms.some((term) => text.includes(term))
)
} }
export const MattermostInbox = async ({ $, directory, client }) => { export const MattermostInbox = async ({ $, directory, client }) => {
@@ -152,6 +142,7 @@ export const MattermostInbox = async ({ $, directory, client }) => {
if (!options.force && now - lastSyncAt < minIntervalMs) return if (!options.force && now - lastSyncAt < minIntervalMs) return
lastSyncAt = now lastSyncAt = now
const syncStartedAt = Date.now()
const inboxDir = path.join(directory, "ai/inbox") const inboxDir = path.join(directory, "ai/inbox")
const latestPath = path.join(inboxDir, "mattermost-latest.md") const latestPath = path.join(inboxDir, "mattermost-latest.md")
@@ -179,6 +170,7 @@ export const MattermostInbox = async ({ $, directory, client }) => {
await writeStatus(statusPath, { await writeStatus(statusPath, {
syncedAt: nowIso(), syncedAt: nowIso(),
durationMs: Date.now() - syncStartedAt,
reason, reason,
forced: Boolean(options.force), forced: Boolean(options.force),
changed: previous !== `${output}\n` && previous !== output, changed: previous !== `${output}\n` && previous !== output,
@@ -188,6 +180,7 @@ export const MattermostInbox = async ({ $, directory, client }) => {
} else { } else {
await writeStatus(statusPath, { await writeStatus(statusPath, {
syncedAt: nowIso(), syncedAt: nowIso(),
durationMs: Date.now() - syncStartedAt,
reason, reason,
forced: Boolean(options.force), forced: Boolean(options.force),
changed: false, changed: false,
@@ -199,6 +192,7 @@ export const MattermostInbox = async ({ $, directory, client }) => {
} catch (error) { } catch (error) {
await writeStatus(statusPath, { await writeStatus(statusPath, {
syncedAt: nowIso(), syncedAt: nowIso(),
durationMs: Date.now() - syncStartedAt,
reason, reason,
forced: Boolean(options.force), forced: Boolean(options.force),
changed: false, changed: false,
@@ -223,13 +217,20 @@ export const MattermostInbox = async ({ $, directory, client }) => {
return { return {
event: async ({ event }) => { event: async ({ event }) => {
if (event.type === "session.created") { if (
event.type === "session.created" &&
envFlag("AIW_MATTERMOST_SYNC_ON_SESSION", false)
) {
await sync("session.created") await sync("session.created")
} }
if (event.type === "tui.prompt.append") { if (event.type === "tui.prompt.append") {
const promptText = extractPromptText(event) const promptText = extractPromptText(event)
const forceFreshMattermost = requiresFreshMattermost(promptText) const forceFreshMattermost = requiresFreshMattermost(promptText)
const allowPromptSync = envFlag("AIW_MATTERMOST_SYNC_ON_PROMPT", false)
if (!forceFreshMattermost && !allowPromptSync) return
await sync( await sync(
forceFreshMattermost forceFreshMattermost
? "tui.prompt.append:fresh-mattermost-request" ? "tui.prompt.append:fresh-mattermost-request"

View File

@@ -46,6 +46,7 @@ Do not preemptively load broad context sets, all work-item files, or all process
- If `ai/inbox/mattermost-latest.md` exists, inspect it for fresher communication context before answering standup, status, or manager-message prompts. - If `ai/inbox/mattermost-latest.md` exists, inspect it for fresher communication context before answering standup, status, or manager-message prompts.
- If the user asks for the latest/last/recent Mattermost message, the latest message from Jeff/current manager, or what someone just said, synchronize Mattermost first instead of relying on existing inbox context. - If the user asks for the latest/last/recent Mattermost message, the latest message from Jeff/current manager, or what someone just said, synchronize Mattermost first instead of relying on existing inbox context.
- If automatic refresh is uncertain, use the explicit latest-message flow: run the Mattermost sync command, then answer from the refreshed inbox only. - If automatic refresh is uncertain, use the explicit latest-message flow: run the Mattermost sync command, then answer from the refreshed inbox only.
- Treat latest-message flows as read-first. Report memory update candidates, but do not edit canonical memory from that command unless the user explicitly asks to promote the fact.
- For learning-style questions, answer from known context and verified facts only; label unknowns, assumptions, and inferences instead of inventing missing details. - For learning-style questions, answer from known context and verified facts only; label unknowns, assumptions, and inferences instead of inventing missing details.
- For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status. - For learning sessions, prioritize durable architecture, process, ownership, debugging strategy, release mechanics, domain concepts, and decision rules over transient ticket status.
- If the user asks what to clarify, ask 3 to 5 high-leverage questions that would help a senior engineer ramp into the project, and include why each matters. - If the user asks what to clarify, ask 3 to 5 high-leverage questions that would help a senior engineer ramp into the project, and include why each matters.
@@ -57,6 +58,7 @@ Do not preemptively load broad context sets, all work-item files, or all process
- Prefer updating existing canonical files over creating new files during the critical path of a user-facing answer. - Prefer updating existing canonical files over creating new files during the critical path of a user-facing answer.
- If a sync command, extraction script, or inbox refresh fails, do not update logs, state, or context files from that failed attempt. - If a sync command, extraction script, or inbox refresh fails, do not update logs, state, or context files from that failed attempt.
- Treat sync failures as operational errors, not project context. - Treat sync failures as operational errors, not project context.
- If a patch or edit verification fails while making a non-essential memory update, stop retrying and return the user-facing answer with the failed target noted.
- `mattermost-sync` should automatically promote high-confidence project facts without asking what to promote. - `mattermost-sync` should automatically promote high-confidence project facts without asking what to promote.
- Prefer `project-knowledge/06-daily/` as the default destination for new Mattermost-derived facts. - Prefer `project-knowledge/06-daily/` as the default destination for new Mattermost-derived facts.
- Promote to `project-knowledge/01-current/current-work.md` only when the fact materially changes active work over the next few days. - Promote to `project-knowledge/01-current/current-work.md` only when the fact materially changes active work over the next few days.

View File

@@ -21,6 +21,12 @@ Mattermost is the current live communication connector.
- Generated extraction artifacts stay under `scripts/mattermost/generated/`. - Generated extraction artifacts stay under `scripts/mattermost/generated/`.
- Failed syncs must not update project knowledge. - Failed syncs must not update project knowledge.
- Latest-message requests must refresh Mattermost before answering. - Latest-message requests must refresh Mattermost before answering.
- Latest-message requests are read-first. The agent may identify a memory update candidate, but should not edit `project-knowledge/` from the latest-message command unless the user explicitly asks to promote the fact.
- Standup generation is a separate required-refresh flow: it must fetch Mattermost before drafting, even though general prompts should not sync automatically.
- Do not refresh Mattermost just because a prompt mentions a manager or stakeholder.
- Treat document review, message polishing, translation, and "does this align with Jeff's expectations?" prompts as normal drafting tasks unless the user explicitly asks for the latest message or fresh Mattermost evidence.
- The OpenCode plugin syncs automatically only for explicit latest-message requests by default.
- Optional aggressive sync can be enabled with `AIW_MATTERMOST_SYNC_ON_SESSION=true` or `AIW_MATTERMOST_SYNC_ON_PROMPT=true`, but these should stay off for low-latency daily use.
--- ---
@@ -31,4 +37,3 @@ Slack export import is the current historical archive connector.
- Archive evidence stays outside `project-knowledge/`. - Archive evidence stays outside `project-knowledge/`.
- Promote only durable project facts, people context, process rules, or historical architecture lessons. - Promote only durable project facts, people context, process rules, or historical architecture lessons.
- Do not promote dated status details unless they explain current context. - Do not promote dated status details unless they explain current context.

View File

@@ -27,6 +27,8 @@ Capture reusable prompting lessons so the agent does not need to re-research the
- Use concrete anti-patterns when a recurring failure mode is known; models respond better to explicit "do not do X" guidance than to general advice alone. - Use concrete anti-patterns when a recurring failure mode is known; models respond better to explicit "do not do X" guidance than to general advice alone.
- Prefer source-bound selection rules when stale or overly broad context can pollute the answer. - Prefer source-bound selection rules when stale or overly broad context can pollute the answer.
- If a task depends on chronology, state chronology explicitly as an output rule. - If a task depends on chronology, state chronology explicitly as an output rule.
- If a task depends on dates, inject an explicit temporal context block near the top of the command: current timestamp, today, calendar yesterday, and the default previous workday. Do not rely on the model to infer this from session history.
- Delegate date arithmetic to code or shell commands and feed the result back to the model as data.
- If concision matters, define how to compress: what should be merged, what should remain split, and what should be omitted. - If concision matters, define how to compress: what should be merged, what should remain split, and what should be omitted.
- If the output is meant to be sent directly, make "copy/paste ready" part of the contract. - If the output is meant to be sent directly, make "copy/paste ready" part of the contract.
- Avoid mixing task logic with human-facing project documentation; reusable prompting logic belongs in prompts, commands, skills, or agent memory. - Avoid mixing task logic with human-facing project documentation; reusable prompting logic belongs in prompts, commands, skills, or agent memory.
@@ -36,6 +38,7 @@ Capture reusable prompting lessons so the agent does not need to re-research the
## Standup-Specific Lessons ## Standup-Specific Lessons
- The model should not infer "worked yesterday" from durable status alone. - The model should not infer "worked yesterday" from durable status alone.
- The standup command should anchor `today`, `yesterday`, and `previous workday` with absolute dates before reading logs or Mattermost evidence.
- `Yesterday` should be tied to previous-workday evidence first, then disambiguated with current memory. - `Yesterday` should be tied to previous-workday evidence first, then disambiguated with current memory.
- Only active work items should be expanded by default; avoid loading every ticket note when generating short status output. - Only active work items should be expanded by default; avoid loading every ticket note when generating short status output.
- Future-sprint work should be excluded from `Today` unless it is a real blocker or the user explicitly wants forward-looking planning. - Future-sprint work should be excluded from `Today` unless it is a real blocker or the user explicitly wants forward-looking planning.

View File

@@ -53,6 +53,8 @@ tags:
- Deeper Discourse / FTTransfer analysis now points to presentation-layer SwiftUI identity/lifecycle churn around `BankInformationView` and `BankSetupWebView`: XFlow eventing appears to set shared consumer-observed state, but current evidence does not show it directly mutating view identity, host lifecycle, or alert state. - Deeper Discourse / FTTransfer analysis now points to presentation-layer SwiftUI identity/lifecycle churn around `BankInformationView` and `BankSetupWebView`: XFlow eventing appears to set shared consumer-observed state, but current evidence does not show it directly mutating view identity, host lifecycle, or alert state.
- The working non-XFlow route appears to avoid the issue because it bypasses the extra XFlow destination presentation layer and associated state-coupling surface, while the failing playground path keeps the alert/popup transition and cover lifecycle coupled in the same reactive chain. - The working non-XFlow route appears to avoid the issue because it bypasses the extra XFlow destination presentation layer and associated state-coupling surface, while the failing playground path keeps the alert/popup transition and cover lifecycle coupled in the same reactive chain.
- The next implementation direction for the Discourse / FTTransfer issue is a pure SwiftUI fix that decouples alert state from the cover identity chain, avoiding unnecessary UIKit dependencies - The next implementation direction for the Discourse / FTTransfer issue is a pure SwiftUI fix that decouples alert state from the cover identity chain, avoiding unnecessary UIKit dependencies
- `PDIAP-16167 - AccountLink - XFlow causing web view rewrites investigation` was created for the FTTransfer AccountLink investigation and root-cause report
- Include in the `PDIAP-16167` report that the issue persists when rolling back `XFlowSDK` to `v0.1.0`, predating REST and modern architecture changes; Jeff explicitly asked David to include this in the document
- Before closing out the AO thread, send one more working-group Teams reply that summarizes the original iOS issue, links the Jira comment, Discourse comment, and PR, and separates the remaining `HybridBrokerageAccountOpening` / `JointIdentityCheck` service-side issue - Before closing out the AO thread, send one more working-group Teams reply that summarizes the original iOS issue, links the Jira comment, Discourse comment, and PR, and separates the remaining `HybridBrokerageAccountOpening` / `JointIdentityCheck` service-side issue
- The `HybridBrokerageAccountOpening` / `JointIdentityCheck` rule-content issue appears unchanged between QA and Production in Cogstore and should be treated as the remaining service-side follow-up - The `HybridBrokerageAccountOpening` / `JointIdentityCheck` rule-content issue appears unchanged between QA and Production in Cogstore and should be treated as the remaining service-side follow-up

View File

@@ -25,3 +25,7 @@ Update the per-ticket files first when scope, status, sequencing, or communicati
- `PDIAP-15836` - Modernize dismissal delegate lifecycle sequencing for pure SwiftUI environment - `PDIAP-15836` - Modernize dismissal delegate lifecycle sequencing for pure SwiftUI environment
Detail: `project-knowledge/02-work-items/pdiap-15836.md` Detail: `project-knowledge/02-work-items/pdiap-15836.md`
Current note: approved at `8` points, rooted in the AccountLink dismissal sequencing investigation, and sequenced after `PDIAP-15838`. Current note: approved at `8` points, rooted in the AccountLink dismissal sequencing investigation, and sequenced after `PDIAP-15838`.
- `PDIAP-16167` - AccountLink - XFlow causing web view rewrites investigation
Detail: `project-knowledge/02-work-items/pdiap-16167.md`
Current note: active documentation/root-cause story for the FTTransfer AccountLink issue. The report should include the `XFlowSDK v0.1.0` rollback evidence and the minimal presentation-anchor fix.

View File

@@ -1,10 +1,10 @@
--- ---
type: daily type: daily
project: fidelity project: fidelity
date: 2026-05-04 date: 2026-05-01
status: active status: active
focus: [] focus: [ao-discourse, xflow-debugging]
work-items: [] work-items: [pdiap-16167]
blockers: [] blockers: []
tags: tags:
- daily - daily
@@ -12,35 +12,41 @@ tags:
updated: 2026-05-04 updated: 2026-05-04
--- ---
# 2026-05-04 # 2026-05-01
## Focus ## Focus
- - Verify and document the root cause for the FTTransfer AccountLink web-view reload issue.
--- ---
## Work Done ## Work Done
- - Created `PDIAP-16167 - AccountLink - XFlow causing web view rewrites investigation`.
- Prepared the root-cause report for the FTTransfer AccountLink issue.
- Verified that XFlow eventing does not appear to be the direct cause of the reload.
- Verified that the issue persists when rolling back `XFlowSDK` to `v0.1.0`, which predates REST and modern architecture changes.
- Identified a minimal presentation-anchor change that resolves the alert auto-dismiss and web-view reload behavior.
--- ---
## Findings ## Findings
- - Current evidence points to a consumer SwiftUI presentation-layer issue rather than recent XFlowSDK or XFlowViewMaker changes.
- The rollback-to-`XFlowSDK v0.1.0` finding should be included in the report because it helps separate the issue from recent XFlow changes.
--- ---
## Communication ## Communication
- - Jeff asked David to put the findings into a Confluence report, share it with Zachary, and comment it on the story.
- Jeff specifically asked David to include the XFlowSDK version / rollback evidence in the report.
--- ---
## Next Steps ## Next Steps
- - Finalize and share the root-cause report with the rollback evidence and minimal fix note.
--- ---

View File

@@ -4,6 +4,21 @@ Use `project-knowledge/01-current/current-work.md`, `project-knowledge/01-curren
Generate a standup update for the active project profile. Generate a standup update for the active project profile.
## Required refresh
- At the start of the day, fetch Mattermost before drafting.
- Fetch both latest available messages and previous-workday activity when the connector supports both modes.
- If Mattermost refresh fails, say so internally and use only saved workspace memory with clear caution; do not invent fresher context.
- Do not skip communication refresh for standup just to reduce latency, because stale standups cost more time to correct later.
## Temporal grounding
- Use the injected `Temporal Context` block as the source of truth for today's date, weekday, calendar yesterday, and default previous workday.
- Resolve relative terms before drafting: `today` means the injected `today`; `yesterday` means the injected `calendar_yesterday`; `previous workday` means the injected `default_previous_workday` unless refreshed Mattermost evidence found a later prior day with activity.
- For a Tuesday report, the previous-work section normally describes Monday's work.
- Do not infer dates from model memory, conversation history, or file modification times when the injected temporal context is available.
- If a requested report date conflicts with the injected current date, state the exact date being used before drafting.
## Output contract ## Output contract
- Use the greeting required by the active profile or command. If no greeting is specified, omit the greeting and start with the previous-work section. - Use the greeting required by the active profile or command. If no greeting is specified, omit the greeting and start with the previous-work section.